全部博文(290)
分类:
2007-12-22 17:25:07
Tutorial 11: More about Dialog Box
第十一课:对话框的更多特性
We will learn more about dialog box in this tutorial. Specifically, we will explore the topic of how to use dialog boxs as our input-output devices. If you read the previous tutorial, this one will be a breeze since only a minor modification is all that's needed to be able to use dialog boxes as adjuncts to our main window. Also in this tutorial, we will learn how to use common dialog boxes.
在这一课中,我们学习关于对话框的更多知识。特别的,我们将探究如何使用对话框来作为我们的输入输出设备这个主题。如果你读过上一课,那么这一课将是轻而易举的事因为唯一的一点改动就是必须把对话框作为我们主窗口的附属品。在这一课中,我们还将学习如何使用通用对话框。
Download the dialog box examples here and here. Download Common Dialog Box example here.
Theory:
原理:
Very little is to be said about how to use dialog boxes as input-output devices of our program. Your program creates the main window as usual and when you want to display the dialog box, just call CreateDialogParam or DialogBoxParam. With DialogBoxParam call, you don't have to do anything more, just process the messages in the dialog box procedure. With CreateDialogParam, you must insert IsDialogMessage call in the message loop to let dialog box manager handle the keyboard navigation in your dialog box for you. Since the two cases are trivial, I'll not put the source code here. You can download the examples and examine them yourself, here and here.
如何在我们的应用程序中用对话框作为输入输出设备是非常简单的。你的程序通常创建一个对话框来作为主窗口并且当你想显示这个对话框的时候,只需要调用
CreateDialogParam 或者是DialogBoxParam .用DialogBoxParam调用时,你除了在对话框过程中处理消息外没必要做其他的任何事.用CreateDialogParam调用时,你必须在消息循环中插入IsDialogMessage调用来让对话框管理器处理在你的对话框中的键盘逻辑.因为这两个例子是琐碎的,我们就不将其源代码放这.你可以下载并分析它们.
Let's go on to the common dialog boxes. Windows has prepared predefined dialog boxes for use by your applications. These dialog boxes exist to provide standardized user interface. They consist of file, print, color, font, and search dialog boxes. You should use them as much as possible. The dialog boxes reside in comdlg32.dll. In order to use them, you have to link to comdlg32.lib. You create these dialog boxes by calling appropriate functions in the common dialog library. For open file dialog, it is GetOpenFileName, for save as dialog it is GetSaveFileName, for print dialog it is PrintDlg and so on. Each one of these functions takes a pointer to a structure as its parameter. You should look them up in Win32 API reference. In this tutorial, I'll demonstrate how to create and use an open file dialog.
让我们接近通用对话框. Windows为你准备了预定义的对话框,你可以在你的应用程序中使用它.这些对话框提供标准的( 定型的)用户界面.它们由文件,打印,颜色,字体,和查找对话框组成.你应该尽可能多的用它们.这些对话框驻留在comdlg32.dll中.为了使用它们,你必须连接comdlg32.lib这个库文件.你通过调用在这个通用对话框库文件中的相应函数来创建这些对话框.
对于”打开文件”对话框,相应的函数是GetOpenFileName .对于”另存为”对话框,相应的函数是GetSaveFileName,对于”打印 ”对话框,相应的函数是PrintDlg函数等等.每一个这样的函数都接收一个指向一个结构体的指针来作为它的参数.你可以在win32 api手册中找到它们.在这一课中.我将示范如何创建和使用打开文件对话框.
Below is the function prototype of GetOpenFileName function:
下面是GetOpenFileName的函数原型:
GetOpenFileName proto lpofn:DWORD
You can see that it receives only one parameter, a pointer to an OPENFILENAME structure. The return value TRUE means the user selected a file to open, it's FALSE otherwise. We will look at OPENFILENAME structure next.
你能看出它仅接收一个参数,一个指向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
Let's see the meaning of the frequently used members.
让我们看看经常用到的成员有什么意义.
lStructSize |
The size of the OPENFILENAME structure , in bytes OPENFILENAME结构的大小,以字节为单位. |
hwndOwner |
The window handle of the open file dialog box. 打开文件对话框的窗口句柄. |
hInstance |
Instance handle of the application that creates the open file dialog box 创建和打开文件对话框的应用程序实例句柄. |
lpstrFilter |
The filter strings in the format of pairs of null terminated strings. The first string in each pair is the description. The second string is the filter pattern. for example: 一对以NULL结束的格式化字符串中的过滤字串.每一对的第一个字符串是描述部分.第二个字符串是过滤样式. 例如:
注意:只有每一对中的第二个字符串样式是WINDOWS实际过滤出的文件,另外您必须在该部分后放置一个0,以示字符串的结束。 |
nFilterIndex |
Specify which pair of the filter strings will be initially used when the open file dialog is first displayed. The index is 1-based, that is the first pair is 1, the second pair is 2 and so on. So in the above example, if we specify nFilterIndex as 2, the second pattern, "*.txt" will be used. 指定当打开文件对话框首次显示时首次使用的那一对过滤模式串.这个索引值从1开始,就是第一对是1,第二对是2并且继续下去.所以在上面的例子中,如果我们指定nFilterIndex的值是2,第二个模式,” *.txt” 将被使用. |
lpstrFile |
Pointer to the buffer that contains the filename used to initialize the filename edit control on the dialog box. The buffer should be at least 260 bytes long. 指向一个包含文件名的缓冲区指针,这个文件名被用来初始化对话框上编辑控件的文件名.这个缓冲区至少要260个字节长. 当用户将选定的文件打开后,这个文件和它的全部路径都被存储在这个缓冲区中.稍后,你可以从这抽取你所要的信息. |
nMaxFile |
The size of the lpstrFile buffer. Lpstrfile 参数的缓冲区大小. |
lpstrTitle |
Pointer to the title of the open file dialog box 指向打开文件对话框标题的字符串指针 |
Flags |
Determine the styles and characteristics of the dialog box. 这个标志决定着对话框的样式和特征面( 属性) |
nFileOffset |
After the user selects a file to open, this member contains the index to the first character of the actual filename. For example, if the full name with path is "c:\windows\system\lz32.dll", the this member will contain the value 18. 在用户将选定文件打开后,这个成员包含一索引值,值的大小是全路径文件名中第一个字符处. 例如:如果全路径文件名是 "c:\windows\system\lz32.dll",这个成员将包含的值是18. (c:\windows\system\ 共18个字符) |
nFileExtension |
After the user selects a file to open, this member contains the index to the first character of the file extension 在用户将选定文件打开后,这个成员包含一索引值,值的大小是文件扩展名的第一个字符处. |
Example:
The following program displays an open file dialog box when the user selects File-> Open from the menu. When the user selects a file in the dialog box, the program displays a message box showing the full name, filename,and extension of the selected file.
当用户从菜单中选择 文件-〉打开 菜单项时 ,我们的程序将显示一个打开文件对话框。当用户在对话框中选择一个文件时,这个程序将弹出一的对话框并显示选定文件的文件名和扩展名。
.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
Analysis:
分析:
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hwndOwner
push hInstance
pop ofn.hInstance
We fill in the routine members of ofn structures.
在这里 我们为例子中的ofn结构成员变量赋值.
mov ofn.lpstrFilter, OFFSET FilterString
This FilterString is the filename filter that we specify as follows:
这个FilterString是我们在下面指定的文件名过滤字串.
FilterString db "All Files",0,"*.*",0
db "Text Files",0,"*.txt",0,0
Note that All four strings are zero terminated. The first string is the description of the following string. The actual pattern is the even number string, in this case, "*.*" and "*.txt". Actually we can specify any pattern we want here. We MUST put an extra zero after the last pattern string to denote the end of the filter string. Don't forget this else your dialog box will behave strangely.
注意:这四个字符串都必须以0结尾.第一个字串是描述下一个字串的.实际的模式是偶数字串.即这个例子中的“*.*” 和” *.txt* ”.我们可以在这里指定任何我们想要的模式.另外,我们必须放一个额外的0 在最后一个模式字串的后面用来作为过滤字串结束标志.不要忘了这一点,否则你的对话框行为将会非常奇怪.
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
We specify where the dialog box will put the filename that the user selects. Note that we must specify its size in nMaxFile member. We can later extract the filename from this buffer.
为对话框上用户选定的文件名指定一个储存的地方.(内存缓冲区)注意我们必须在nMaxFile成员中指定它的大小.稍后,我们可以从这个缓冲区中取这个文件名.
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
Flags specifies the characteristics of the dialog box.
OFN_FILEMUSTEXIST and OFN_PATHMUSTEXIST flags demand that the filename and path that the user types in the filename edit control MUST exist.
OFN_LONGNAMES flag tells the dialog box to show long filenames.
OFN_EXPLORER flag specifies that the appearance of the dialog box must be explorer-like. OFN_HIDEREADONLY flag hides the read-only checkbox on the dialog box.
There are many more flags that you can use. Consult your Win32 API reference.
指定对话框特证面的标志字. OFN_FILEMUSTEXIST 和 OFN_PATHMUSTEXIST标志要求用户在文件名编辑控件中输入的文件名和路径必须存在. OFN_LONGNAMES标志告诉我们对话框显示长文件名. OFN_EXPLORER标志规定对话框的外观必须像资源管理器. OFN_HIDEREADONLY标志在对话框上隐藏只读文件的检查框.
这里有很多标志你可以用,请参照你的win32 api手册来获取更多信息.
mov ofn.lpstrTitle, OFFSET OurTitle
Specify the title of the dialog box.
指定对话框标题.
invoke GetOpenFileName, ADDR ofn
Call the GetOpenFileName function. Passing the pointer to the ofn structure as its parameter.
调用GetOpenFileName函数.并传递一个OFN结构指针作为函数参数.
At this time, the open file dialog box is displayed on the screen. The function will not return until the user selects a file to open or presses the cancel button or closes the dialog box. It 'll return the value TRUE in eax if the user selects a file to open. It returns FALSE otherwise.
这时,打开文件对话框将显示在你的屏幕上.这个函数并不立即返回.直到用户选择打开一个文件或者是按下了取消按钮或者是关闭了这个对话框为止.如果用户选择打开一个文件,它将在eax中返回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
In case the user selects a file to open, we prepare an output string to be displayed in a message box. We allocate a block of memory in OutputString variable and then we use an API function, lstrcat, to concatenate the strings together. In order to put the strings into several lines, we must separate each line with a carriage return-line feed pair.
在这个例子中,用户选择打开一个文件,我们准备一个在消息框中显示的输出字符串.首先.我们为OutputString变量在内存中分配一存储块然后用一个API函数,lstrcat,来将这个字串连接在一起.为了将这些字串分行显示,我们必须在每个字符串后面放置一换行符.
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileOffset
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
The above lines require some explanation. nFileOffset contains the index into the ofn.lpstrFile. But you cannot add them together directly since nFileOffset is a WORD-sized variable and lpstrFile is a DWORD-sized one. So I have to put the value of nFileOffset into the low word of ebx and add it to the value of lpstrFile.
上面这些行需要一些说明.nFileOffset包含一个在ofn.lpstrFile成员中的索引值.但是你不能将它们直接的合在一起.因为nFileOffset是一个字长的变量而lpstrFile是一个双子长的变量.所以我们应该把nFileOffset的值放在ebx寄存器的低16位中并将这个值传给lpstrFile.
invoke MessageBox,hWnd,OFFSET OutputString,ADDR AppName,MB_OK
We display the string in a message box.
我们在消息框中显示一个字符.
invoke RtlZerolMemory,offset OutputString,OUTPUTSIZE
We must *clear* the OutputString before we can fill in another string. So we use RtlZeroMemory function to do the job.
在用另外一些字符来替换OutputString字串之前我们必须用RtlZeroMenory这个函数来清除OutputString变量中的值.
This article come from Iczelion's asm page
风向改变 翻译于