Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1801405
  • 博文数量: 290
  • 博客积分: 10653
  • 博客等级: 上将
  • 技术积分: 3178
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-24 23:08
文章存档

2013年(6)

2012年(15)

2011年(25)

2010年(86)

2009年(52)

2008年(66)

2007年(40)

分类:

2008-02-27 15:32:16

Tutorial 23: Tray Icon

第二十三课:托盘图标


In this tutorial, we will learn how to put icons into system tray and how to create/use a popup menu.

在这一课中,我们将学习如何把一个图标放入系统托盘以及学习如何创建和使用一个弹出式菜单。
Download the example here.

Theory:

原理:

System tray is the rectangular region in the taskbar where several icons reside. Normally, you'll see at least a digital clock in it. You can also put icons in the system tray too. Below are the steps you have to perform to put an icon into the system tray:

系统托盘是在任务栏上可以驻留若干图标的一块矩形区域。通常,你至少可以在它上面看到一个数字显示式时钟。你也能放置一些图标在系统托盘上。你必须执行下面这些步骤来放置一图标在系统托盘上:

  1. Fill a NOTIFYICONDATA structure which has the following members:

填充一个 NOTIFYICONDATA结构,这个结构的成员如下:

    • cbSize   The size of this structure.                            这个结构的字节大小
    • hwnd      Handle of the window that will receive notification when a mouse event occurs over the tray icon.窗口句柄,当鼠标事件发生在系统托盘上时,这个窗口将接收通知码。
    • uID         A constant that is used as the icon's identifier. You are the one who decides on this value. In case you have more than one tray icons, you will be able to check from what tray icon the mouse notification is from.

作为图标标识的一常数。你可以取任意值,但是值必须是唯一的。因为,当有多个图标在托盘上时,你将要区分鼠标消息来自于那个图标。故这个值必须取唯一值。

    • uFlags    Specify which members of this structure are valid

             指定这个结构的那些成员变量有效。

      • NIF_ICON The hIcon member is valid.

hIcon 成员有效

      • NIF_MESSAGE The uCallbackMessage member is valid.

uCallbackMessage 成员有效

      • NIF_TIP The szTip member is valid.

SzTip 成员有效

    • uCallbackMessage  The custom message that Windows will send to the window specified by the hwnd member when mouse events occur over the tray icon. You create this message yourself.

uCallbackMessage 自定义消息。当鼠标事件在托盘图标上发生时,windows将通过hwnd成员发送给指定的窗口。你可以自己创建这个消息。

    • hIcon      The handle of the icon you want to put into the system tray

hIcon      你想放在系统托盘上的图标的句柄。

    • szTip       A 64-byte array that contains the string that will be used as the tooltip text when the mouse hovers over the tray icon.

SzTip     一个64位的数组,这个数组存放的是---当鼠标停留在小图标上时,作为提示文本的字符串。

  1. Call Shell_NotifyIcon which is defined in shell32.inc. This function has the following prototype:

调用Shell_NotifyIcon函数,这个还属定义在shell32.inc.函数原型如下:


            Shell_NotifyIcon PROTO dwMessage:DWORD ,pnid:DWORD

dwMessage  is the type of message to send to the shell.

DwMessage 是发送给windows外壳的消息.
           NIM_ADD Adds an icon to the status area.

往状态栏上增加一个图标.
          NIM_DELETE Deletes an icon from the status area.

从状态栏上删除一图标.
          NIM_MODIFY Modifies an icon in the status area.

在状态栏中修改一图标.
    pnid  is the pointer to a NOTIFYICONDATA structure filled with proper values

Pnid  是一个指向填满特征值的NOTIFYICONDATA 结构指针。
If you want to add an icon to the tray, use NIM_ADD message, if you want to remove the icon, use NIM_DELETE.

如果你想增加一个图标在托盘上,用NIM_ADD 消息,如果你想移出一个图标,用NIM_DELETE消息。

That's all there is to it. But most of the time, you're not content in just putting an icon there. You need to be able to respond to the mouse events over the tray icon. You can do this by processing the message you specified in uCallbackMessage member of NOTIFYICONDATA structure. This message has the following values in wParam and lParam (special thanks to s__d for the info):

基本上全部的消息就是这些。但是大多数时候,你并不满足于仅仅放置一图标在这儿。你需要在鼠标事件发生在托盘图标上时能够做出响应。你能够这样做,通过在NOTIFYICONDATA结构中的uCallbackMessage成员中指定你要处理的消息。这个消息的wparamlparam的值如下。

  • wParam contains the ID of the icon. This is the same value you put into uID member of NOTIFYICONDATA structure.

Wparam 包含这个图标的ID号。这是一个你放在NOTIFYICONDATA结构成员uID的值。

  • lParam  The low word contains the mouse message. For example, if the user right-clicked at the icon, lParam will contain WM_RBUTTONDOWN.

Lparam  低字节包含鼠标消息。例如,如果你在图标上点击了右键,lparam将包含WM_RBUTTONDOWN消息。

Most tray icon, however, displays a popup menu when the user right-click on it. We can implement this feature by creating a popup menu and then call TrackPopupMenu to display it. The steps are described below:

然而,当用户在托盘图标上点击右键时,大多数的托盘图标将显示一个弹出式菜单。我们能通过创建一个弹出式菜单来实现这一特征,然后调用TrackPopupMenu来显示它。这些步骤描述如下:

  1. Create a popup menu by calling CreatePopupMenu. This function creates an empty menu. It returns the menu handle in eax if successful.

通过调用CreatePopupMenu函数来创建一弹出式菜单。这个函数创建一个空的菜单。如果成功,它在eax中返回一个菜单句柄。

  1. Add menu items to it with AppendMenu, InsertMenu or InsertMenuItem.

AppendMenu, InsertMenu InsertMenuItem函数来添加菜单项。

  1. When you want to display the popup menu where the mouse cursor is, call GetCursorPos to obtain the screen coordinate of the cursor and then call TrackPopupMenu to display the menu. When the user selects a menu item from the popup menu, Windows sends WM_COMMAND message to your window procedure just like normal menu selection.

当你想在鼠标光标处显示这个菜单时,调用GetCursorPos函数来得到光标的屏幕坐标,然后调用TrackPopMenu来显示菜单。当用户从弹出式菜单上选择一个菜单项时,windows发送WM_COMMAND消息给你的窗口处理过程,就像你选择了正常的菜单一样。

Note: Beware of two annoying behaviors when you use a popup menu with a tray icon:

注意:当你在托盘图标上使用一个弹出菜单时,小心两件比较恼人的行为。

  1. When the popup menu is displayed, if you click anywhere outside the menu, the popup menu will not disappear immediately as it should be. This behavior occurs because the window that will receive the notifications from the popup menu MUST be the foreground window. Just call SetForegroundWindow will correct it.

当弹出式菜单被显示时,如果你在菜单以外任何地方点击了鼠标,这个弹出式菜单不会像它应该做的那样立即消失不见。这个行为重现是因为接收菜单消息的窗口必须是前景窗口。仅需调用SetForegroundWindow就能纠正它。

  1. After calling SetForegroundWindow, you will find that the first time the popup menu is displayed, it works ok but on the subsequent times, the popup menu will show up and close immediately. This behavior is "intentional", to quote from MSDN. The task switch to the program that is the owner of the tray icon in the near future is necessary. You can force this task switch by posting any message to the window of the program. Just use PostMessage, not SendMessage!

在调用SetForegroundWindow函数后,你将发现第一次弹出的菜单正常显示并且工作的很好,但是在后来,弹出式菜单弹出便立即关闭。引用MSDN这样的行为是“故意的”。为了使得弹出菜单保持住,必须要求下一个切换到的是程序的主窗口。你能通过置入任何消息给程序的窗口来强制的切换任务。但是只能用PostMessage函数而不能用SendMessage函数。

Example:

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib

WM_SHELLNOTIFY equ WM_USER+5
IDI_TRAY equ 0
IDM_RESTORE equ 1000
IDM_EXIT equ 1010
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD

.data
ClassName  db "TrayIconWinClass",0
AppName    db "TrayIcon Demo",0
RestoreString db "&Restore",0
ExitString   db "E&xit Program",0

.data?
hInstance dd ?
note NOTIFYICONDATA <>
hPopupMenu dd ?

.code
start:
    invoke GetModuleHandle, NULL
    mov    hInstance,eax
    invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT
    invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInst
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_APPWORKSPACE
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\
           CW_USEDEFAULT,350,200,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax
    .while TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .BREAK .IF (!eax)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .endw
    mov eax,msg.wParam
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    LOCAL pt:POINT
    .if uMsg==WM_CREATE
        invoke CreatePopupMenu
        mov hPopupMenu,eax
        invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr RestoreString
        invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString
    .elseif uMsg==WM_DESTROY
        invoke DestroyMenu,hPopupMenu
        invoke PostQuitMessage,NULL
    .elseif uMsg==WM_SIZE
        .if wParam==SIZE_MINIMIZED
            mov note.cbSize,sizeof NOTIFYICONDATA
            push hWnd
            pop note.hwnd
            mov note.uID,IDI_TRAY
            mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
            mov note.uCallbackMessage,WM_SHELLNOTIFY
            invoke LoadIcon,NULL,IDI_WINLOGO
            mov note.hIcon,eax
            invoke lstrcpy,addr note.szTip,addr AppName
            invoke ShowWindow,hWnd,SW_HIDE
            invoke Shell_NotifyIcon,NIM_ADD,addr note
        .endif
    .elseif uMsg==WM_COMMAND
        .if lParam==0
            invoke Shell_NotifyIcon,NIM_DELETE,addr note
            mov eax,wParam
            .if ax==IDM_RESTORE
                invoke ShowWindow,hWnd,SW_RESTORE
            .else
                invoke DestroyWindow,hWnd
            .endif
        .endif
    .elseif uMsg==WM_SHELLNOTIFY
        .if wParam==IDI_TRAY
            .if lParam==WM_RBUTTONDOWN
                invoke GetCursorPos,addr pt
                invoke SetForegroundWindow,hWnd
                invoke TrackPopupMenu,hPopupMenu,TPM_RIGHTALIGN,pt.x,pt.y,NULL,hWnd,NULL
                invoke PostMessage,hWnd,WM_NULL,0,0
            .elseif lParam==WM_LBUTTONDBLCLK
                invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
            .endif
        .endif
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
    xor eax,eax
    ret
WndProc endp

end start
 

Analysis:

分析: 

The program will display a simple window. When you press the minimize button, it will hide itself and put an icon into the system tray. When you double-click on the icon, the program will restore itself and remove the icon from the system tray. When you right-click on it, a popup menu is displayed. You can choose to restore the program or exit it.

这个程序将显示一个简单的窗口。当你按最小化按钮时,它将隐藏它自己并且放置一图标到系统托盘中。当你双击这个图标时,这个程序将恢复它原来的窗口并且将图标从系统托盘中移出。当你用右键点击它时,一个弹出式菜单被显示。你能选择恢复这个程序或者是退出程序。

   .if uMsg==WM_CREATE
        invoke CreatePopupMenu
        mov hPopupMenu,eax
        invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr RestoreString
        invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr ExitString

When the main window is created, it creates a popup menu and append two menu items. AppendMenu has the following syntax:

当主窗口被创建时,它创建一个弹出式菜单并且添加两个菜单项。AppendMenu句法如下:
 

AppendMenu PROTO hMenu:DWORD, uFlags:DWORD, uIDNewItem:DWORD, lpNewItem:DWORD
 

·   hMenu is the handle of the menu you want to append the item to

 hMenu是你想创建的那个菜单项的句柄。

·   uFlags tells Windows about the menu item to be appended to the menu whether it is a bitmap or a string or an owner-draw item, enabled, grayed or disable etc. You can get the complete list from win32 api reference. In our example, we use MF_STRING which means the menu item is a string.

uFlags 告诉windows添加的这个菜单项是一个位图或者字符串还是以个自画的项,以及它是否可用,变灰还是禁用等。你能从win32API手册中得到完全清单。在我们的例子中,我们用MF_STRING, 它意味着这个菜单项是字符串.

·   uIDNewItem is the ID of the menu item. This is a user-defined value that is used to represent the menu item.

uIdNewItem 是菜单项的ID.这是一个用户自定义的值,用这个值来表示这个菜单项.

·   lpNewItem specifies the content of the menu item, depending on what you specify in uFlags member. Since we specify MF_STRING in uFlags member, lpNewItem must contain the pointer to the string to be displayed in the popup menu.

 LpNewItem 指定菜单项的内容,依赖于uFlags成员中的值.因为我们指定在uFlags中的值是MF_STRING,lpNewItem必须包含一个指针,这个指针指向显示在弹出菜单中的字符串.

After the popup menu is created, the main window waits patiently for the user to press minimize button.

在弹出式菜单被创建之后,主窗口耐心的等待用户按下最小化按钮.
When a window is minimized, it receives WM_SIZE message with SIZE_MINIMIZED value in wParam.

当窗口被最小化时,它接收到WM_SIZE消息,其中wParam参数的值是SIZE_MINIMIZED.

    .elseif uMsg==WM_SIZE
        .if wParam==SIZE_MINIMIZED
            mov note.cbSize,sizeof NOTIFYICONDATA
            push hWnd
            pop note.hwnd
            mov note.uID,IDI_TRAY
            mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
            mov note.uCallbackMessage,WM_SHELLNOTIFY
            invoke LoadIcon,NULL,IDI_WINLOGO
            mov note.hIcon,eax
            invoke lstrcpy,addr note.szTip,addr AppName
            invoke ShowWindow,hWnd,SW_HIDE
            invoke Shell_NotifyIcon,NIM_ADD,addr note
        .endif

We use this opportunity to fill NOTIFYICONDATA structure. IDI_TRAY is just a constant defined at the beginning of the source code. You can set it to any value you like. It's not important because you have only one tray icon.But if you will put several icons into the system tray, you need unique IDs for each tray icon.

我们用这个时机来填充NOTFYICONDATA结构体。IDI_TRAY仅是一个在源代码开始处定义的常数。你可以用你喜欢的任何值来设置它。它并不是很重要,因为你只有一个托盘图标。但是,如果你放置几个图标在系统托盘中,你需要为每一个图标定义不同的ID号。

We specify all flags in uFlags member because we specify an icon (NIF_ICON), we specify a custom message (NIF_MESSAGE) and we specify the tooltip text (NIF_TIP). WM_SHELLNOTIFY is just a custom message defined as WM_USER+5. The actual value is not important so long as it's unique. I use the winlogo icon as the tray icon here but you can use any icon in your program. Just load it from the resource with LoadIcon and put the returned handle in hIcon member. Lastly, we fill the szTip with the text we want the shell to display when the mouse is over the icon. We hide the main window to give the illusion of "minimizing-to-tray-icon" appearance.

我们在uFlags成员中设置所有的标置,因为我们指定了一个图标(NIF_ICON),我们还指定了一个自定义的消息NIF_MESSAGE和帮助文本NIF_TIPWM_SHELLNOTIFY仅是一个定义为WM_USER+5 的自定义消息。这个实际的值并不重要,只要它是唯一的值。 在这里,我们使用的是windows登录时的图标,但是你也可以在你的程序中使用任何图标。仅需用LoadIcon函数从资源中撞在它并且把它返回的值放在hIcon成员中。最后,我们用文本填充szTip的值,这个文本的值是当鼠标在图标上时我们要显示的字符串。为了达到最小化然后只显示图标的效果,我们在这时隐藏掉主窗口

 


Next we call Shell_NotifyIcon  with NIM_ADD message to add the icon to the system tray.

接下来,我们调用Shell_NotifyIcon 函数并用NIM_ADD消息来添加一个图标到系统托盘中。

Now our main window is hidden and the icon is in the system tray. If you move the mouse over it, you will see a tooltip that displays the text we put into szTip member. Next, if you double-click at the icon, the main window will reappear and the tray icon is gone.

现在我们的主窗口式隐藏的并且这个图标也在系统托盘中。如果你把鼠标移到它上面,你将看到我们放入szTip成员中的提示文本。下一步,如果你双击这个图标,主窗口将再次出现并且托盘图标消失 。

    .elseif uMsg==WM_SHELLNOTIFY
        .if wParam==IDI_TRAY
            .if lParam==WM_RBUTTONDOWN
                invoke GetCursorPos,addr pt
                invoke SetForegroundWindow,hWnd
                invoke TrackPopupMenu,hPopupMenu,TPM_RIGHTALIGN,pt.x,pt.y,NULL,hWnd,NULL
                invoke PostMessage,hWnd,WM_NULL,0,0
            .elseif lParam==WM_LBUTTONDBLCLK
                invoke SendMessage,hWnd,WM_COMMAND,IDM_RESTORE,0
            .endif
        .endif

When a mouse event occurs over the tray icon, your window receives WM_SHELLNOTIFY message which is the custom message you specified in uCallbackMessage member. Recall that on receiving this message, wParam contains the tray icon's ID and lParam contains the actual mouse message. In the code above, we check first if this message comes from the tray icon we are interested in. If it does, we check the actual mouse message. Since we are only interested in right mouse click and double-left-click, we process only WM_RBUTTONDOWN and WM_LBUTTONDBLCLK messages.

当一个鼠标事件发生在托盘图标上时,你的窗口将接收到WM_SHELLNOTIFY消息,这个消息是你放在uCallbackMessage成员变量中的自定义消息。在收到这个消息时,wparam参数包含托盘图标的ID号,lParam包含实际的鼠标消息。在上面的代码中,我们首先检查这个消息是否来自于我们感兴趣的托盘图标,如果它是,我们检查实际的鼠标消息。由于,我们仅仅对右键和双击事件感兴趣,所以我们仅处理WM_RBUTTONDOWNWM_LBUTTONDBLCLK消息。

If the mouse message is WM_RBUTTONDOWN, we call GetCursorPos to obtain the current screen coordinate of the mouse cursor. When the function returns, the POINT structure is filled with the screen coordinate of the mouse cursor. By screen coordinate, I mean the coordinate of the entire screen without regarding to any window boundary. For example, if the screen resolution is 640*480, the right-lower corner of the screen is x==639 and y==479. If you want to convert the screen coordinate to window coordinate, use ScreenToClient function.

如果鼠标消息是WM_RBUTTONDOWN,我们调用GetCursorPos函数来得到鼠标光标在屏幕上的坐标。当函数返回时,POINT结构填充的是鼠标光标的屏幕坐标。屏幕坐标,我意思是指没有包含任何窗口边界的整个屏幕坐标。例如,如果屏幕分辨率是640*480,屏幕右下角的坐标是x=639 y=479,如果你想屏幕坐标为窗口坐标,用ScreenToClient函数。
However, for our purpose, we want to display the popup menu at the current mouse cursor position with TrackPopupMenu call and it requires screen coordinates, we can use the coordinates filled by GetCursorPos directly.
TrackPopupMenu has the following syntax:

然而,我们的目的是,我们想在当前鼠标光标的位置弹出一菜单,所以我们调用TrackPopupMenu函数,而这个函数需要的是屏幕坐标值,我们能将GetCursorPos函数返回的坐标值直接用在TrackPopupMenu函数中,句法如下:
 

TrackPopupMenu PROTO hMenu:DWORD, uFlags:DWORD,  x:DWORD,  y:DWORD, nReserved:DWORD, hWnd:DWORD, prcRect:DWORD
 

  • hMenu is the handle of the popup menu to be displayed

hMenu是将要被显示的弹出菜单的句柄。

  • uFlags specifies the options of the function. Like where to position the menu relative to the coordinates specified later and which mouse button will be used to track the menu. In our example, we use TPM_RIGHTALIGN to position the popup menu to the left of the coordinates.

uFlags 指定一个功能选项。像相对于随后指定的坐标值,菜单放的位置和那一个鼠标按钮将被用于菜单轨迹。在我们的例子中,我们用TPM_RIGHTALIGN来决定弹出式菜单放在坐标的左边。

  • x and y specify the location of the menu in screen coordinates.

X y 指定在屏幕坐标中菜单的位置。

  • nReserved must be NULL   

nReserved 必须为空

  • hWnd is the handle of the window that will receive the messages from the menu.

hWnd 是接受从菜单接收消息的窗口句柄。

  • prcRect is the rectangle in the screen where it is possible to click without dismissing the menu. Normally we put NULL here so when the user clicks anywhere outside the popup menu, the menu is dismissed.

PrcRect 是屏幕中的一块矩形。如果在该矩形区域外面按下鼠标的话,菜单将消失。一般我们把该值设为NULL,这样当用户只要在菜单外面按下鼠标,菜单立即消失。

When the user double-clicks at the tray icon, we send WM_COMMAND message to our own window specifying IDM_RESTORE to emulate the user selects Restore menu item in the popup menu thereby restoring the main window and removing the icon from the system tray. In order to be able to receive double click message, the main window must have CS_DBLCLKS style.

 

 当用户在托盘图标上双击时,我们发送WM_COMMAND消息给我们的自己的窗口,并指定IDM_RESTORE来仿效用户在弹出菜单中选择了恢复菜单项,从而恢复主窗口并且从系统托盘中移出图标。为了能够接收到双击消息,主窗口必须有CS_DBLCLKS样式。

            invoke Shell_NotifyIcon,NIM_DELETE,addr note
            mov eax,wParam
            .if ax==IDM_RESTORE
                invoke ShowWindow,hWnd,SW_RESTORE
            .else
                invoke DestroyWindow,hWnd
            .endif

When the user selects Restore menu item, we remove the tray icon by calling Shell_NotifyIcon again, this time we specify NIM_DELETE as the message. Next, we restore the main window to its original state. If the user selects Exit menu item, we also remove the icon from the tray and destroy the main window by calling DestroyWindow.

当用户用选择恢复菜单项时,我们再一次调用Shell_NotifyIcon函数移出托盘图标,这个时候我们指定NIM_DELETE作为消息,下一步,我们恢复主窗口到原来的状态。如果用户选择退出菜单项,我们也从托盘中移出图标并且调用DestroyWindow来销毁窗口。


This article come from Iczelion's asm page

 风向改变翻译于  2008-2-27

 

阅读(1902) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~