?? 010.txt
字號:
上面定義了對話框的風格。
CAPTION "Our First Dialog Box"
這是顯示在對話框標題條上的標題。
CLASS "DLGCLASS"
這一行非常關鍵。正是有了關鍵字CLASS,我們才可以用它來聲明把一個對話框當成一個窗口來用。跟在關鍵字后面的是“窗口類”的名稱。
BEGIN
EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
END
上面的一塊定義了對話框中的子窗口控件,它們是聲明在一頭一尾的兩個關鍵字BEGIN和END之間的。
control-type "text" ,controlID, x, y, width, height [,styles]
控件的類型是資源編輯器定義好了的常數,您可以查找有關的手冊。
現在我們來看看匯編源代碼。先看這部分:
mov wc.cbWndExtra,DLGWINDOWEXTRA
mov wc.lpszClassName,OFFSET ClassName
通常cbWndExtra被設成NULL,但我們想把一個對話框模板注冊成一個窗口類,我們必須把該成員的值設成DLGWINDOWEXTRA。注意類的名稱必須和模板中跟在CLASS關鍵字后面的名稱一樣。余下的成員變量和聲明一般的窗口類相同。填寫好窗口類結構變量后調用函數RegisterClassEx進行注冊??瓷先ミ@一切和注冊一個普通的窗口類是一樣的。
invoke CreateDialogParam,hInstance,ADDR DlgName,NULL,NULL,NULL
注冊完畢后,我們就創建該對話框。在這個例子中,我們調用函數CreateDialogParam產生一個無模式對話框。這個函數共有5個參數,其中前兩個參數是必須的:實例句柄和指向對話框模板名稱的指針。注意第二個參數是指向模板名稱而不是類名稱的指針。這時,WINDOWS將產生對話框和子控件窗口。同時您的應用程序將接收到由WINDOWS傳送的第一個消息WM_CREATE。
invoke GetDlgItem,hDlg,IDC_EDIT
invoke SetFocus,eax
在對話框產生后,我們把輸入輸出焦點設到編輯控件上。如果在WM_CREATE消息處理段中假如設置焦點的代碼,GetDlgItem函數就會失敗,因為此時空間窗口還未產生,為了在對話框和所有的子窗口控件都產生后調用該函數我們把它安排到了函數UpdatWindow后,GetDlgItem函數返回該控件的敞口句柄。
invoke IsDialogMessage, hDlg, ADDR msg
.IF eax ==FALSE
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
現在程序進入消息循環,在我們翻譯和派發消息前,該函數使得對話框內置的對話框管理程序來處理有關的鍵盤跳轉邏輯。如果該函數返回TRUE,則表示消息是傳給對話框的已經由該函數處理了。注意和前一課不同,當我們想得到控件的文本信息時調用GetDlgItemText函數而不是GetWindowText函數,前者接受的參數是一個控件的ID 號,而不是窗口的句柄,這使得在對話框中調用該函數更方便。
--------------------------------------------------------------------------------
好我們現在使用第二種方法把一個對話框當成一個主窗口來使用。在接下來的例子中,我們將產生一個應用程序的模式對話框,您將會發現其中根本沒有消息循環或窗口處理過程,因為它們根本沒有必要!
--------------------------------------------------------------------------------
dialog.asm (part 2)
--------------------------------------------------------------------------------
.386
.model flat,stdcall
option casemap:none
DlgProc 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
DlgName db "MyDialog",0
AppName db "Our Second Dialog Box",0
TestString db "Wow! I'm in an edit box now",0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
buffer db 512 dup(?)
.const
IDC_EDIT equ 3000
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
IDM_GETTEXT equ 32000
IDM_CLEAR equ 32001
IDM_EXIT equ 32002
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF uMsg==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0
.IF ax==IDM_GETTEXT
invoke GetDlgItemText,hWnd,IDC_EDIT,ADDR buffer,512
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
.ELSEIF ax==IDM_CLEAR
invoke SetDlgItemText,hWnd,IDC_EDIT,NULL
.ELSEIF ax==IDM_EXIT
invoke EndDialog, hWnd,NULL
.ENDIF
.ELSE
mov edx,wParam
shr edx,16
.if dx==BN_CLICKED
.IF ax==IDC_BUTTON
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString
.ELSEIF ax==IDC_EXIT
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ENDIF
.ENDIF
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
end start
--------------------------------------------------------------------------------
dialog.rc (part 2)
--------------------------------------------------------------------------------
#include "resource.h"
#define IDC_EDIT 3000
#define IDC_BUTTON 3001
#define IDC_EXIT 3002
#define IDR_MENU1 3003
#define IDM_GETTEXT 32000
#define IDM_CLEAR 32001
#define IDM_EXIT 32003
MyDialog DIALOG 10, 10, 205, 60
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "Our Second Dialog Box"
MENU IDR_MENU1
BEGIN
EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
END
IDR_MENU1 MENU
BEGIN
POPUP "Test Controls"
BEGIN
MENUITEM "Get Text", IDM_GETTEXT
MENUITEM "Clear Text", IDM_CLEAR
MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
MENUITEM "E&xit", IDM_EXIT
END
END
--------------------------------------------------------------------------------
分析如下:
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
我們已經定義了DlgProc函數的原型,所以可以用操作符ADDR來獲得它的地址(記得嗎,它可以在運行時動態地獲得標識符的有效地址):
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
上面的幾行調用了函數DialogBoxPAram,該函數有五個參數,分別是:實例句柄、對話框模板的名字、父窗口的句柄、對話框過程函數的地址、和對話框相關的數據。該函數產生一個模式對話框。如果不顯示地關閉該函數不會返回。
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF uMsg==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
除了不處理WM_CREATE消息外對話框的窗口處理過程函數和一般的窗口處理過程相似。該過程函數接收到的第一個消息是WM_INITDIALOG。通常把初始化的代碼放到此處。注意如果您處理該消息必須在eax中返回TRUE。內置的對話框管理函數不會把WM_DESTROY 消息發送到對話框的消息處理函數,所以如果我們想在對話框關閉時進行處理,就把它放到WM_CLOSE消息的處理中。在我們的例子中我們發送消息WM_COMMAND,并在參數wParam中放置IDM_EXIT,這和處理WM_CLOSE 消息效果一樣,在處理IDM_EXIT 中我們調用EndDialog函數。如果我們想要銷毀一個對話框,必須調用EndDialog函數,該函數并不會立即銷毀一個窗口,而是設置一個標志位,然后對話框管理器會處理接下去的銷毀對話框動作。好,現在我們來看看資源文件,其中最顯著的變化是在指定菜單時我們不是用字符串指定該菜單的名稱而是用了一個常量 IDR_MENU1。在調用DialogBoxParam產生的對話框中掛接一個菜單必須這么做,注意在該對話框模板中,在該標識符前必須加MENU關鍵字,這兩個例子中的顯著不同是后者沒有圖標,這可以在處理WM_INITDIALOG中發送消息WM_SETICON消息,然后在該消息處理代碼中作適當的處理即可。
--------------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -