程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編教程之進一步學習對話框

匯編教程之進一步學習對話框

編輯:匯編語言

本課中我們將進一步學習對話框。特別地我們將要探討如何把對話框當成輸入設備。如果您學習了上一課,那就會發現本課的例子只有少量的改動,就是把我們的對話框窗口附屬到主窗口上。另外,我們還要學習通用對話框的用法。

理論:

把對話框當成一個輸入設備來用確實是非常地簡單,創建完主窗口後,您只要調用函數 CreatedialogParam 或 DialogBoxParam 就可以了,前一個函數只要在對話框的過程處理函數中處理相關的消息就可以,而後者你必須在消息循環段中插入函數 IsDialogMessage 的調用讓它來處理鍵盤的按鍵邏輯。因為這兩個程序段相對來說比較容易,我們就不詳解。您可以下載並仔細研究。

下面我們來討論通用對話框。WINDOWS已經為您准備好了預定義的對話框類,您可以拿來就用,這些通用對話框提供給用戶以統一的界面。它們包括:打開文件、打印、選擇顏色、字體和搜索等。您應該盡可能地用它們。處理這些對話框的代碼在comdlg32.dll中,為了在您的應用程序中使用它們,就必須在鏈接階段鏈接庫文件 comdlg32.lib。然後調用其中的相關函數即可。對於打開文件通用對話框,該函數名為 GetOpenFileName,"保存為..."對話框為 GetSaveFileName,打印通用對話框是 PrintDlg, 等等。每一個這樣的函數都接收一個指向一個結構體的指針的參數,您可以參考WIN32 API手冊得到詳細的資料,本課中我將講解創建和使用打開文件對話框。

下面是打開對話框函數 GetOpenFileName 的原型:

GetOpenFileName proto lpofn:DWORD

您可以看到,該函數只有一個參數,即指向結構體OPENFILENAME的指針。當用戶選擇了一個文件並打開,該函數返回TRUE,否則返回FALSE。接下來我們看看結構體OPENFILENAME的定義:

OPENFILENAME STRUCT
lStructSize DWORD ?
hwndOwner HWND ?
hInstance HINSTANCE ?
lpstrFilter LPCSTR ?
lpstrCustomFilter LPSTR ?
nMaxCustFilter DWORD ?
nFilterIndex DWORD ?
lpstrFile LPSTR ?
nMaxFile DWORD ?
lpstrFileTitle LPSTR ?
nMaxFileTitle DWORD ?
lpstrInitialDir LPCSTR ?
lpstrTitle LPCSTR ?
Flags DWORD ?
nFileOffset WORD ?
nFileExtension WORD ?
lpstrDefExt LPCSTR ?
lCustData LPARAM ?
lpfnHook DWORD ?
lpTemplateName LPCSTR ?
OPENFILENAME ENDS

好,我們再來看看該結構體中常用的成員的意義:

lStructSize 結構體OPENFILENAME的大小。

hwndOwner 擁有打開對話框的窗口的句柄。

hInstance 擁有該打開文件對話框的應用程序的實例句柄 。

lpstrFilter 以NULL結尾的一個或多個通配符。通配符是成對出現的,前一部分是描述部分,後一部分則是通配符的格式,譬如:

FilterString db "All Files (*.*)",0, "*.*",0
db "Text Files (*.txt)",0,"*.txt",0,0

注意:只有每一對中的第二部分是WINDOWS用來過濾所需選擇的文件的,另外您必須在該部分後放置一個0,以示字符串的結束。

nFilterIndex 用來指定打開文件對話框第一次打開時所用的過濾模式串,該索引是從1開始算的,即第一個通配符模式的索引是1,第二個是2,譬如上面的例子中,若指定該值為2,則缺省顯示的模式串就是"*.txt"。

lpstrFile 需要打開的文件的名稱的地址,該名稱將會出現在打開文件對話框的編輯控件中,該緩沖區不能超過260個字符長,當用戶打開文件後,該緩沖區中包含該文件的全路徑名,您可以從該緩沖區中抽取您所需要的路徑或文件名等信息。

nMaxFile lpstrFile的大小。

lpstrTitle 指向對話框標題的字符串。

Flags 該標志決定決定了對話框的風格和特點。

nFileOffset 在用戶打開了一個文件後該值是全路徑名稱中指向文件名第一個字符的索引。譬如:若全路徑名為"c:\windows\system\lz32.dll", 則該值為18。

nFileExtension 在用戶打開了一個文件後該值是全路徑名稱中指向個文件擴展名第一個字符的索引。

例子:

下例中,我們演示了當用戶選擇"File->Open"時,將彈出一個打開文件對話框,當用戶選擇了某個文件打開時,會彈出一個對話框,告知要打開的文件的全路徑名,文件名和文件擴展名。

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
.const
IDM_OPEN equ 1
IDM_EXIT equ 2
MAXSIZE equ 260
OUTPUTSIZE equ 512
.data
ClassName db "SimpleWinClass",0
AppName db "Our Main Window",0
MenuName db "FirstMenu",0
ofn OPENFILENAME <>
FilterString db "All Files",0,"*.*",0
db "Text Files",0,"*.txt",0,0
buffer db MAXSIZE dup(0)
OurTitle db "-=Our First Open File Dialog Box=-: Choose the file to open",0
FullPathName db "The Full Filename with Path is: ",0
FullName db "The Filename is: ",0
ExtensionName db "The Extension is: ",0
OutputString db OUTPUTSIZE dup(0)
CrLf db 0Dh,0Ah,0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.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_WINDOW+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_COMMAND
mov eax,wParam
.if ax==IDM_OPEN
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hwndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
mov ofn.lpstrTitle, OFFSET OurTitle
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke lstrcat,offset OutputString,OFFSET FullPathName
invoke lstrcat,offset OutputString,ofn.lpstrFile
invoke lstrcat,offset OutputString,offset CrLf
invoke lstrcat,offset OutputString,offset FullName
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileOffset
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
invoke lstrcat,offset OutputString,offset CrLf
invoke lstrcat,offset OutputString,offset ExtensionName
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileExtension
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
invoke MessageBox,hWnd,OFFSET OutputString,ADDR AppName,MB_OK
invoke RtlZeroMemory,offset OutputString,OUTPUTSIZE
.endif
.else
invoke DestroyWindow, hWnd
.endif
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

--------------------------------------------------------------------------------

分析:

mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hwndOwner
push hInstance
pop ofn.hInstance

我們在此填充結構體OPENFILENAME變量ofn的有關成員。

mov ofn.lpstrFilter, OFFSET FilterString

這裡FilterString 是文件過濾模式的字符串地址,我們指定的過濾模式字符串如下:

FilterString db "All Files",0,"*.*",0

db "Text Files",0,"*.txt",0,0

注意:所有的模式串都是配對的,前一個是描述,後一個才是真正的模式,次處"*.*"和"*.txt"是WIONDOWS用來尋找匹配的欲打開的文件的。我們當能可以指定任何模式,但是不要忘記在結尾處加0以代表字符串已結束,否則您的對話框在操作時可能不穩定。

mov ofn.lpstrFile, OFFSET buffer

mov ofn.nMaxFile,MAXSIZE

這裡是把緩沖區的地址放到結構體中,同時必須設定大小。以後我們可以隨意編輯在該緩沖區中返回的信息。

mov ofn.Flags, OFN_FILEMUSTEXIST or \

OFN_PATHMUSTEXIST or OFN_LONGNAMES or\

OFN_EXPLORER or OFN_HIDEREADONLY

Flags 中放入的是對話框的風格和特性值。

其中OFN_FILEMUSTEXIST和 OFN_PATHMUSTEXIST要求用戶在打開對話框的編輯控件中輸入的文件名或路徑名必須存在。

OFN_LONGNAMES 告訴對話框顯示長文件名。

OFN_EXPLORER 告訴WINDOWS對話框的外觀必須類似資源管理器。

OFN_HIDEREADONLY 指定不要顯示只讀文件(既使它的擴展名符合過濾模式)。

除此之外,還有許多其它的標志位,您可以參考有關WIN32 API手冊。

mov ofn.lpstrTitle, OFFSET OurTitle

指定打開文件對話框的標題名。

invoke GetOpenFileName, ADDR ofn

調用GetOpenFileName函數,並傳入指向結構體ofn的指針。

這時候,打開文件對話框就顯示出來了,GetOpenFileName函數要一直等到用戶選擇了一個文件後才會返回,或者當用戶按下了CANCEL鍵或關閉對話框時。

當用戶選擇了打開一個文件時,該函數返回TRUE, 否則返回FALSE。

.if eax==TRUE
invoke lstrcat,offset OutputString,OFFSET FullPathName
invoke lstrcat,offset OutputString,ofn.lpstrFile
invoke lstrcat,offset OutputString,offset CrLf
invoke lstrcat,offset OutputString,offset FullName

當用戶選擇打開一個文件時,我們就在一個對話框中顯示一個字符串,我們先給OutputString變量分配內存,然後調用PAI 函數lstrcat,把所有的字符串連到一起,為了讓這些字符串分行顯示,我們必須在每個字符串後面加一個換行符。

mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileOffset
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax

上面這幾行可能需要一些解釋。nFileOffset的值等於被打開文件的全路徑名中的文件名的第一個字符的索引,由於nFileOffset是一個WORD型變量,而lpstrFile是一個DWORD形的指針,所以我們就要作一轉換把nFileOffset存入ebx寄存器的底字節,然後再加到eax寄存器中得到DWORD型的指針。

invoke MessageBox,hWnd,OFFSET OutputString,ADDR AppName,MB_OK

我們在對話框中顯示該字符串。

invoke RtlZerolMemory,offset OutputString,OUTPUTSIZE

為了下一次能正確地顯示,必須清除緩沖區,我們調用函數RtlZerolMemory來做這件事。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved