用匯編輕鬆地寫基於對話方塊的程式 (轉)

worldblog發表於2007-12-14
用匯編輕鬆地寫基於對話方塊的程式 (轉)[@more@]

用寫基於對話方塊的,可以和寫VB程式一樣清晰簡單,並且相當多的程式都是這樣的結構。用VB寫的所以程式幾乎都是這樣的。

  • 設計程式介面
      和在VC中一樣,介面(對話方塊已經各種)一般是以資源的方式存在的。編輯資源完全可以使用VC的資源編輯器。但是熟悉一下資原始檔的寫法及意義是所必須的。下面是一個資原始檔的例子:

      #include "masm32includere.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 "masm32includeresource.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 :D,:DWORD,:DWORD,:DWORD

      include masm32include.inc
      include masm32includeuser32.inc
      include masm32includekernel32.inc
      includelib masm32libuser32.lib
      includelib masm32libkernel32.lib

      .data
      DlgName "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 masm32includewindows.inc
      include masm32includeuser32.inc
      include masm32includekernel32.inc
      includelib masm32libuser32.lib
      includelib masm32libkernel32.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來將焦點設定在它上面。注意這些函式都是函式,這些函式的意義都可以在msdn中找到。

      當按下對話方塊右上角的關閉按鈕時,會產生WM_CLOSE,必須處理這個函式,否則不能用×來關閉對話方塊(這是由於內建的函式沒有設計處理這個訊息),而對於最大化最小化等訊息則有預設的處理。

      當按下對話方塊上的按鈕時會產生WM_COMMAND訊息,並且wParam中傳遞的是控制元件的ID。根據不同的ID完成不同的功能,在本例中如果是IDC_BUTTON這個ID說明是顯示編輯框內容的控制元件按鈕被按下,這樣就GetDlgItemText函式得到編輯框的內容,然後用messagebox來顯示。如果是IDC_EXIT說明按下了“退出程式”這個按鈕,則執行EndDialog這個函式退出程式。

      程式就是透過處理各種訊息完成的!在更大的程式裡面也都是這種結結構,只不過處理的訊息更多而已。


  • ">我的主頁asm.91i.net

    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993408/,如需轉載,請註明出處,否則將追究法律責任。

    相關文章