用匯編寫基於對話框的程序,可以和寫VB程序一樣清晰簡單,並且相當多的程序都是這樣的結構。用VB寫的所以程序幾乎都是這樣的
。設計程序界面
和在VC中一樣,界面(對話框已經各種控件)一般是以資源的方式存在的。編輯資源文件完全可以使用VC的資源編輯器。但是熟悉
一下資源文件的寫法及意義是編程所必須的。下面是一個資源文件的例子:
#include "\masm32\include\resource.h"
#define IDC_EDIT 3000
#define IDC_BUTTON 3001
#define IDC_EXIT 3002
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 "我的對話框"
{
EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "顯示編輯框中的內容", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "退出程序", IDC_EXIT, 141,26,52,13
}
記住,在使用QE時為了使得編譯成功,必須將它保存為rsrc.rc這個文件名(使用命令行就無所謂了)。選擇Project->Compile Resource File。資源文件就編譯成功了,就可以被連接使用了。建議你用VC的資源編輯器打開這個資源文件看看。
第一行的#include "\masm32\include\resource.h"就和C一樣,是包含一個頭文件,這個文件中有各種常數的定義,如
PUSHBUOTTON等,感興趣的話,可以打開這個文件看看。
接下來定義了一些常數,就和C中的用法一樣,是為了增強程序的可讀性。
"MyDialog DIALOG 10, 10, 205, 60"這一句用DIALOG這個關鍵字定義一個名為MyDialog的對話框,名字當然可以隨便取。後面 的4個數字是對話框的位置大小,一般是在資源編輯器中調試。
"STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK "是描述對話框的風格的。如WS_MINIMIZEBOX是說有最小化按鈕。DS_3DLOOK是說對話框是3D外形
等等。這些一般在資源編輯器中改動,各種常數的意義,可以在MSDN中查找。
CAPTION "我的對話框"就是指定對話框的標題是"我的對話框"
再下面用{}框起來的就是對話框中的各個控件。這個例子中用到了EDITTEXT編輯框控件,PUSHBUTTON按鈕控件,
DEFPUSHBUTTON默認按鈕控件(默認選中狀態),IDC_EDIT,IDC_EXIT,IDC_BUTTON分別是他們3個的ID號,注意上面的定義,是不
能相同的。不一定非要使用#define來預先定義,使用數字也可以,前者可以增強程序的可讀性。其他的很多控件如單選框,復
選框等等的使用可以在資源編輯器下編輯後查看源代碼獲得。
程序的界面就設計完了,接下來是設計程序。
程序的設計
我們來做一個簡單的程序,在按下“顯示編輯框中的內容”這個按鈕時,將彈出一個消息框顯示現在編輯框中的內容。按“退出
程序”按鈕將退出程序。
.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 "My own dialog",0
.data?
hInstance HINSTANCE ?
buffer db 512 dup(?)
.const
IDC_EDIT equ 3000
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
.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 EndDialog, hWnd,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF eax==IDC_BUTTON
invoke GetDlgItemText,hWnd,IDC_EDIT,ADDR buffer,512
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
.ELSEIF ax==IDC_EXIT
invoke EndDialog, hWnd,NULL
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
end start
猛一看,這個程序挺長的,如果用VB實現這個功能的話,大概只需要寫5-6行。但是,這個程序中相當一部分代碼是固定的,也
就是說,寫任何基於對話框的程序都需要這樣寫。VB中正是VB的編譯器自動幫你做了這些工作。
.386; 聲明使用386指令系統
.model flat,stdcall;聲明內存的尋址方式
option casemap:none;聲明是否對大小寫敏感
;上面3行可以認為是固定的,必須的
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 "My own dialog",0
;............這裡定義各個預先賦值的變量,db是定義一個字節長,dw是定義一個字長等等,還有很多類型的宏定義,包含在
windows.h中。
.data?
hInstance HINSTANCE ?
;............這裡定義各個變量,但是是沒有預先賦值的
.const
;..........如果需要預先定義一些常量,放在這段裡面,用關鍵字equ定義
.code ;以下就是代碼段,注意函數也是放在代碼段裡面的!
start:;不一定非要使用start,可以是任何的字符串如begin,entry等等。
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
上面的幾行也是比較固定的,invoke是用來調用函數的,用過VB的人都知道call,這就相當於那個命令
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
;..............這是你主要集中精力要寫的地方
DlgProc endp
end start;主要和上面的start對應
基本上,你可以把上面的綠色部分當作模版使用,只需要在.data和.data?以及.const段增加你所需要的變量和常量就可以了。
剩下的任務就是寫上面紅色的部分,也就是處理各個消息。
我們來分析幾個消息,在調用DialogBoxPrarm創建對話框後,對話框會收到WM_INITDIALOG即對話框初始化消息,uMsgz這個參數
接受到消息。在這個程序中,我們用GetDlgItem這個函數來取得編輯框控件的句柄,然後調用SetFocus來將焦點設置在它上面。
注意這些函數都是API函數,這些函數的意義都可以在msdn中找到。
當按下對話框右上角的關閉按鈕時,會產生WM_CLOSE,必須處理這個函數,否則不能用×來關閉對話框(這是由於內置的函數沒
有設計處理這個消息),而對於最大化最小化等消息則有默認的處理。
當按下對話框上的按鈕時會產生WM_COMMAND消息,並且wParam中傳遞的是控件的ID。根據不同的ID完成不同的功能,在本例中如
果是IDC_BUTTON這個ID說明是顯示編輯框內容的控件按鈕被按下,這樣就執行GetDlgItemText函數得到編輯框的內容,然後用
messagebox來顯示。如果是IDC_EXIT說明按下了“退出程序”這個按鈕,則執行EndDialog這個函數退出程序。
程序就是通過處理各種消息完成的!在更大的程序裡面也都是這種結結構,只不過處理的消息更多而已。