Win32彙編教程三 一個簡單的對話方塊 --- 兼談資原始檔的使用 (轉)
--------------------------------------------------------------------------------
的資源
不管在Dos下還是在Windows下程式設計,我們總是要用到除了可檔案外的很多其他資料,如資料,圖形資料,文字等等,在Dos下程式設計,我們可以自己定義這些檔案的格式,但這樣一來就造成了很多資源共享的問題,大家可能還記的Dos下的很多遊戲,它們的圖形都是按自己的格式存放的,你無法用標準的看圖來看。也無法把它另存為其他格式。雖然在程式設計中,我們仍然可以這樣做,但Win32程式設計給了我們一個方案 ---- 就是格式統一的資原始檔,把字串、圖形、對話方塊包括上面的按鈕,文字等定義到一個資原始檔中,就可以方便的在不同的檔案中使用它,最重要的是,如果我們用自己的檔案格式,使用時就要涉及到這些檔案的讀寫操作,比較複雜,但使用資原始檔時,Windows提供了一系列的來裝入資源。非常方便。現在,讓我們來看一個很簡單的資原始檔的原始檔,它的副檔名是 .rc,當它用資源編譯以後產生 .res 檔案就可以在 link的時候連入.exe 檔案中:
#include
#define DLG_MAIN 1
DLG_MAIN DIALOGEX 0, 0, 236, 185
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "對話方塊模板"
FONT 9, "宋體"
BEGIN
DEFPUSHBUTTON "退出",IDOK,177,163,50,14
CONTROL "",-1,"Static",SS_ETCHEDHORZ,7,155,222,1
END
現在我簡單解釋一下 .rc檔案的語法:
#include
#define DLG_MAIN 1 -- 類似於 .asm 檔案的 equ 語句,和源一樣,這些定義是為了程式的可讀性。
DLG_MAIN DIALOGEX 0,0,236,185
Windows的.rc檔案可以定義 BITMAP(點陣圖),CURSOR(游標),ICON(圖示),ACCELERATORS(加速鍵),DIALOG(對話方塊),MENU(選單),STRINGTABLE(字串表),RCDATA(自定義資源)等8種資源,詳細的描述可以參考有關MFC的書籍,在Win32ASM中的資源編譯器的語法中,一般格式是這些資源的定義方法是:
點陣圖定義: nameID BITMAP [load-mem] filename
游標定義: nameID CURSOR [load-mem] filename
圖示定義: nameID ICON [load-mem] filename
加速鍵定義:
acctablename ACCELERATORS [optional-statements]
BEGIN event, idvalue, [type] [options]
. . .
END
等等,具體的定義和引數可以參考 Masm32v5 中的 Rc.hlp 幫助檔案。(可以在程式設計工具中),我們可以用資源編輯器來所見即所得地編輯資源,也可以在文字編輯器中用上面這些語句自己定義資源。
在程式中使用資源
在程式中,要使用資源之前必須先裝如,Windows定義了一系列的API來裝入資源,如 LoadMenu,LoadString,Loaitmap 等等,如 LoadBitmap 的定義:
HBITMAP LoadBitmap(
HINSTANCE hInstance, // handle of application instance
LPCTSTR lpBitmapName // address of bitmap resource name
);
這些Load的返回值是一個控制程式碼,引數中一般至少為兩項: hInstance 和 ResouceName,這個 ResouceName(如BitmapName,MenuName)就是在資原始檔中的 #define 指定的值,如果你用 #define MY_ICON 10/ MY_ICON ICON "Main.ico" 定義了一個圖示,那麼在程式中要使用 Main.ico 圖示就可以用 LoadIcon(hInstance,10) 來裝入已經定義為10號的圖示檔案。另一個引數 hInstance 是執行檔案的控制程式碼,它對應資源所在的檔名,你可以在程式開始執行時用 invoke GetModuleHandle,NULL 獲得 hInstance。另外一些資源並不是顯式地裝入的,如對話方塊資源,它是在建立對話方塊的函式中由Windows自己裝入的,如下面例子中的 invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0 ,是在螢幕上顯示一個資原始檔中已經定義好了的對話方塊,就並不存在 LoadDialogBox 之類的API來先裝入對話方塊。
Win32ASM - 顯示一個對話方塊
介紹了這麼多相關的東西,現在讓我們來看看如何顯示一個對話方塊,源程式如下:
.386
.model flat, stdcall
option casemap :none ; case sensitive
include windows.inc
include user32.inc
include kernel32.inc
include comctl32.inc
include comdlg32.inc
includelib user32.lib
includelib kernel32.lib
includelib comctl32.lib
includelib comdlg32.lib
DLG_MAIN equ 1
.data?
hInstance dd ?
szBuffer db 256 dup (?)
_ProcDlgMain PROTO :D,:DWORD,:DWORD,:DWORD
.data
.code
;********************************************************************
_ProcDlgMain proc uses ebx edi esi,
hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
.elseif eax == WM_INITDIALOG
.elseif eax == WM_COMMAND
mov eax,wParam
.if eax == IDOK
invoke EndDialog,hWnd,NULL
.elseif eax == IDCANCEL
invoke EndDialog,hWnd,NULL
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;********************************************************************
start:
invoke InitCommonControls
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0
invoke ExitProcess,NULL
end start
看了前面幾篇文章以後,這兒的大部分語句應該是很熟悉了,我來講解幾句新的語句:
_ProcDlgMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
PROTO 語句類似於C語言中的函式定義,在Win32彙編中,如果子程式的定義在引用以後,你就必須先定義,當然,這個定義是針對 invoke 語句和其他帶引數的呼叫的,如果你的子程式沒有引數,你就可以用 call 指令去呼叫它而不是用宏指令 invoke,這時候你就不必宣告這個函式。
_ProcDlgMain proc uses ebx edi esi,
hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
這個定義 proc 的語句應該是不陌生的,要重複講解一下的是 uses 和 下面的引數,uses 下的暫存器表示要編譯器自動插入儲存及恢復這些暫存器的指令, 是在 Masm32 中接下一行的符號,表示下一行是本行的繼續內容,以避免一行中的內容過長。下面的 hWnd:DWORD 等語句定義了呼叫這個子程式的引數,如果有以下定義 MyProc proc dwPara1:DWORD,dwPara2:DWORD,dwPara3:DWORD,然後你用 invoke MyProc 1,2,3 來呼叫它,那麼,1,2,3 將分別被賦值給 dwPara1,dwPara2,dwPara3,你可以在子程式中使用這些傳遞過來的引數。如果引數的型別是雙字,那麼:DWORD 可以省略。
.if/.else/.elseif/.endif
這些語句是宏指令,實際上不說你也知道它們的意思,有了這些宏指令,我們就可以把彙編編得象C一樣結構清晰,而不必老是看到 jmp 指令了,當然,這只不過編譯器幫你做了這些事情而已,如果你去反彙編一下,你開始會看到一大堆 jmp 指令,.if 的格式如下
.if eax == 1 如果eax等於1
.if eax != 1 如果eax不等於1
.if eax != 1 && ebx != 2 如果eax不等於1且ebx不等於2
.if eax == 1 || ebx == 2 如果eax等於1或者ebx等於2
其他的宏指令還有 .while/.endw .break 等等,可以參考 Masm32V5 的幫助檔案 Masm32.hlp
最後要講到的就是 DialogBoxParam 這個API了,在Windows中,所有的視窗都要指定一個子程式,當Windows檢測到滑鼠、定時器等和這個視窗有關的動作時,它回撥用這個子程式,這就是Windows基於訊息的體系的最基本的概念,換句話說,在Dos下,我們透過INT指令呼叫,而在Windows 下,有很多時候是你指定子程式地址讓Windows來呼叫你。 invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0中的 offset _ProcDlgMain 就指定了如果有訊息發生,Windows就來執行這個子程式,引數中的 DLG_MAIN 就是在資原始檔中定義的對話方塊模板編號。 hInstance 是對話方塊所在的資原始檔的控制程式碼。
另外,在_ProcDlgMain 子程式中,Windows傳給我們4個引數hWnd,wMsg,wParam,lParam,其中,hWnd是對話方塊的視窗控制程式碼,wMsg表示現在發生的訊息事件,如這個對話方塊初始化時Windows會以WM_INITDIALOG為訊息呼叫,關閉時為WM_CLOSE,按下對話方塊上的按鈕時為WM_COMMAND等,wParam和lParam是附加的引數,對應不同的訊息對應不同定義,具體可以參考Win32 Programmer's reference。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987439/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Win32彙編教程四 編寫一個簡單的視窗 (轉)Win32
- 不使用ATL嚮導,建立一個簡單的ATL對話方塊程式. (轉)
- 自定義一個簡單的載入對話方塊
- InstallShield自定義對話方塊淺談(三) (轉)
- 一個Flex 對話方塊的坑Flex
- dotnet C# 使用 SHFileOperation 呼叫 Win32 的檔案複製對話方塊C#Win32
- Win32彙編教程二 Win32彙編程式的結構和語法 (轉)Win32
- 對話方塊的選單、控制元件使用COMMAND_UI (轉)控制元件UI
- 如何讓win32對話方塊居中顯示Win32
- Javascript檔案對話方塊JavaScript
- InstallShield自定義對話方塊淺談(四) (轉)
- InstallShield自定義對話方塊淺談(五) (轉)
- 一個俄羅斯方塊的原始碼 (轉)原始碼
- 基本概念(win32)彙編教程(轉)Win32
- Win32彙編教程十二 管道操作 (轉)Win32
- [MFC]選擇目錄對話方塊和選擇檔案對話方塊
- JavaFX 如何使用內建的對話方塊Java
- 一個功能強大的對話方塊庫—讓你的專案不再單調
- 我編寫的俄羅斯方塊原始碼,支援單機對戰,可定製方塊數,鍵盤等!!! (轉)原始碼
- Win32彙編教程十 定時器的應用 (轉)Win32定時器
- 用匯編輕鬆地寫基於對話方塊的程式 (轉)
- 進一步學習對話方塊(轉)
- 對話方塊背景色的設定 (轉)
- 直播平臺原始碼,簡單實現 彈出確認 取消對話方塊原始碼
- 一個js編寫全選、彈出對話方塊、ajax-json的案例JSON
- 對話方塊中對成批控制元件的操作 (轉)控制元件
- 有關屬性對話方塊(property sheet )的幾個提示 (轉)
- 常用元件 / 對話方塊及選單元件
- 在 Flutter 使用 GetX 對話方塊Flutter
- c#中的模態對話方塊和非模態對話方塊C#
- 編輯Android程式遊戲對話方塊Android遊戲
- Win32彙編教程七 控制元件的子類化 (轉)Win32控制元件
- React中的模式對話方塊React模式
- 實現對gridview刪除行時彈出確認對話方塊的一種簡單方法View
- 簡單好看的Android圓形進度條對話方塊開源庫Android
- 總結:在一個工程中新增別的工程的中已建立好的對話方塊資源。(或是。。。) (轉)
- Win32彙編教程八 圖形介面的操作 (轉)Win32
- 談一談對vuex的簡單理解Vue