第十一课 进一步学习对话框
GetOpenFileName proto lpofn:DWORD您可以看到,该函数只有一个参数,即指向结构体OPENFILENAME的指针。当用户选择了一个文件并打开,该函数返回TRUE,否则返回FALSE。接下来我们看看结构体OPENFILENAME的定义:
OPENFILENAME STRUCT好,我们再来看看该结构体中常用的成员的意义:lStructSize DWORD ?OPENFILENAME ENDS
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 ?
lStructSize | 结构体OPENFILENAME的大小。 |
hwndOwner | 拥有打开对话框的窗口的句柄。 |
hInstance | 拥有该打开文件对话框的应用程序的实例句柄 。 |
lpstrFilter |
以NULL结尾的一个或多个通配符。通配符是成对出现的,前一部分是描述部分,后一部分则是通配符的格式,譬如:
|
nFilterIndex | 用来指定打开文件对话框第一次打开时所用的过滤模式串,该索引是从1开始算的,即第一个通配符模式的索引是1,第二个是2,譬如上面的例子中,若指定该值为2,则缺省显示的模式串就是"*.txt"。 |
lpstrFile | 需要打开的文件的名称的地址,该名称将会出现在打开文件对话框的编辑控件中,该缓冲区不能超过260个字符长,当用户打开文件后,该缓冲区中包含该文件的全路径名,您可以从该缓冲区中抽取您所需要的路径或文件名等信息。 |
nMaxFile | lpstrFile的大小。 |
lpstrTitle | 指向对话框标题的字符串。 |
Flags | 该标志决定决定了对话框的风格和特点。 |
nFileOffset | 在用户打开了一个文件后该值是全路径名称中指向文件名第一个字符的索引。譬如:若全路径名为"c:\windows\system\lz32.dll", 则该值为18。 |
nFileExtension | 在用户打开了一个文件后该值是全路径名称中指向个文件扩展名第一个字符的索引。 |
.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
我们在此填充结构体OPENFILENAME变量ofn的有关成员。
mov ofn.lpstrFilter, OFFSET FilterString
这里FilterString 是文件过滤模式的字符串地址,我们指定的过滤模式字符串如下:
FilterString db "All Files",0,"*.*",0注意:所有的模式串都是配对的,前一个是描述,后一个才是真正的模式,次处"*.*"和"*.txt"是WIONDOWS用来寻找匹配的欲打开的文件的。我们当能可以指定任何模式,但是不要忘记在结尾处加0以代表字符串已结束,否则您的对话框在操作时可能不稳定。
db "Text Files",0,"*.txt",0,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来做这件事。