第九课 子窗口控件
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc 
  include \masm32\include\user32.inc 
  include \masm32\include\kernel32.inc 
  includelib \masm32\lib\user32.lib 
  includelib \masm32\lib\kernel32.lib 
.data 
  ClassName db "SimpleWinClass",0 
  AppName  db "Our First Window",0 
  MenuName db "FirstMenu",0 
  ButtonClassName db "button",0 
  ButtonText db "My First Button",0 
  EditClassName db "edit",0 
  TestString db "Wow! I'm in an edit box now",0 
.data? 
  hInstance HINSTANCE ? 
  CommandLine LPSTR ? 
  hwndButton HWND ? 
  hwndEdit HWND ? 
  buffer db 512 dup(?)                    
  ; buffer to store the text retrieved from the edit box 
.const 
  ButtonID equ 1                                
  ; The control ID of the button control 
  EditID equ 2                                    
  ; The control ID of the edit control 
  IDM_HELLO equ 1 
  IDM_CLEAR equ 2 
  IDM_GETTEXT equ 3 
  IDM_EXIT equ 4 
.code 
  start: 
      invoke GetModuleHandle, NULL 
      mov    hInstance,eax 
      invoke GetCommandLine
      mov CommandLine,eax 
      invoke WinMain, hInstance,NULL,CommandLine, 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 
  
      mov   wc.lpfnWndProc, OFFSET WndProc 
      mov   wc.cbClsExtra,NULL 
      mov   wc.cbWndExtra,NULL 
      push  hInst 
      pop   wc.hInstance 
      mov   wc.hbrBackground,COLOR_BTNFACE+1 
      mov   wc.lpszMenuName,OFFSET MenuName 
      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_OVERLAPPEDWINDOW,\ 
                          
  CW_USEDEFAULT, CW_USEDEFAULT,\ 
                          
  300,200,NULL,NULL, hInst,NULL 
      mov   hwnd,eax 
      invoke ShowWindow, hwnd,SW_SHOWNORMAL 
      invoke UpdateWindow, hwnd 
      .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 
      .IF uMsg==WM_DESTROY 
          invoke PostQuitMessage,NULL 
  
      .ELSEIF uMsg==WM_CREATE 
          invoke CreateWindowEx,WS_EX_CLIENTEDGE, 
  ADDR EditClassName,NULL,\ 
                          
  WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\ 
                          
  ES_AUTOHSCROLL,\ 
                          
  50,35,200,25,hWnd,8,hInstance,NULL 
          mov  hwndEdit,eax 
          invoke SetFocus, hwndEdit 
  
          invoke CreateWindowEx,NULL, ADDR 
  ButtonClassName,ADDR ButtonText,\ 
                          
  WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\ 
                          
  75,70,140,25,hWnd,ButtonID,hInstance,NULL 
          mov  hwndButton,eax 
      .ELSEIF uMsg==WM_COMMAND 
          mov eax,wParam 
          .IF lParam==0 
              .IF ax==IDM_HELLO 
  
                  
  invoke SetWindowText,hwndEdit,ADDR TestString 
              .ELSEIF 
  ax==IDM_CLEAR 
                  
  invoke SetWindowText,hwndEdit,NULL 
              .ELSEIF  
  ax==IDM_GETTEXT 
                  
  invoke GetWindowText,hwndEdit,ADDR buffer,512 
                  
  invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK 
              .ELSE 
  
                  
  invoke DestroyWindow,hWnd 
              .ENDIF 
  
          .ELSE 
              .IF ax==ButtonID 
  
                  
  shr eax,16 
                  
  .IF ax==BN_CLICKED 
                      
  invoke SendMessage,hWnd,WM_COMMAND,IDM_GETTEXT,0 
                  
  .ENDIF 
              .ENDIF 
  
          .ENDIF 
      .ELSE 
          invoke DefWindowProc,hWnd,uMsg,wParam,lParam 
  
          ret 
      .ENDIF 
       xor    eax,eax 
      ret 
  WndProc endp 
  end start 
    .ELSEIF uMsg==WM_COMMAND 
          mov eax,wParam 
          .IF lParam==0 
我们以前讲过选择菜单想也会发送WM_COMMAND
消息,那我们应如何区分呢?看了下表您就会一目了然:
    
| Low word of wParam | High word of wParam | lParam | |
| Menu | Menu ID | 0 | 0 | 
| Control | Control ID | Notification code | Child Window Handle | 
其中我们可以看到不能用wParam来区分,因为菜单和控件的ID号可能相同,而且子窗口空间的消息号也有可能为0。
            .IF ax==IDM_HELLO 
  
                  
  invoke SetWindowText,hwndEdit,ADDR TestString 
              .ELSEIF 
  ax==IDM_CLEAR 
                  
  invoke SetWindowText,hwndEdit,NULL 
              .ELSEIF  
  ax==IDM_GETTEXT 
                  
  invoke GetWindowText,hwndEdit,ADDR buffer,512 
                  
  invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK 
您可以调用SetWindowText函数把一字符串繁缛到编辑控件中去,为了清0,传入NULL值。SetWindowText是一个通用函数,即可以用它来设定一个窗口的标题,也可以用它来改变一个按钮上的文字。如果是要得到按钮上的文字,则调用GetWindowText。
            .IF ax==ButtonID 
  
                  
  shr eax,16 
                  
  .IF ax==BN_CLICKED 
                      
  invoke SendMessage,hWnd,WM_COMMAND,IDM_GETTEXT,0 
                  
  .ENDIF 
              .ENDIF 
上面的片段是处理用户按钮事件的。他首先检查wParam的高字节看是否是按钮的ID 号,若是则检查低字节看发送的消息号是否BN_CLICKED,该消息是在按钮按下时发送的,如果一切都对,则转入处理该消息,我们可以从处理消息IDM_GETTEXT处复制全部的代码,但是更专业的办法是在发送一条IDM_GETTEXT消息让主窗口过程处理,这只要把传送的消息设置为WM_COMMAND,再把wParam的低字节中设置为IDM_GETTEXT即可。这样一来您的代码就简洁了许多,所以尽可能利用该技巧。 最后,当然不是或有或无,必须在消息循环中调用函数TranslateMessage,因为您的应用程序需要在编辑框中输入可读的文字。如果省略了该函数,就不能在编辑框中输入任何东西。