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.
Below
is the function prototype of GetOpenFileName function:
GetOpenFileName proto lpofn:DWORDYou 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:Let's see the meaning of the frequently used members.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 ]
lStructSize | The size of the OPENFILENAME structure , in bytes |
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:
FilterString db "All Files (*.*)",0, "*.*",0 db "Text Files (*.txt)",0,"*.txt",0,0 Note that only the pattern in the second string in each pair is actually used by Windows to filter out the files. Also noted that you have to put an extra 0 at the end of the filter strings to denote the end of it. |
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. |
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.
After the user selects a file to open, the filename with full path is stored in this buffer. You can extract the information from it later. |
nMaxFile | The size of the lpstrFile buffer. |
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. |
nFileExtension | After the user selects a file to open, this member contains the index to the first character of the file extension |
[hwnd:
0
ClassName:
'SimpleWinClass' 0
AppName:
'Our Main Window' 0
MenuName:
'FirstMenu' 0
DlgName:
'MyDialog' 0
TestString:
'Hello, everybody' 0]
_____________________________________________________________________________________
[CR 13 LF 10]
[IDM_EXIT 1 IDM_ABOUT 2 IDC_EDIT 3000 IDC_BUTTON 3001 IDC_EXIT 3002 DialogID 1000]
[MenuID 2000 M00_File 2001 M00_Open 2002 M00_Exit 2003]
______________________________________________________________________________________
;
Window Class Structure:
[DLGWINDOWEXTRA 30]
[WindowClassEx:
wc_Size: len wc_style: &CS_HREDRAW+&CS_VREDRAW
WndProc: MainWindowProc
wc_ClsExtra: 0 wc_WndExtra: DLGWINDOWEXTRA
hInstance: 0
wc_hIcon: 0 wc_hCursor:
0
wc_hbrBackground: 6
wc_MenuName: MenuID wc_ClassName: ClassName
wc_hIconSm: 0]
[FilterStrings:
B§ 'All Files' 0 '*.*' 0
'Text Files' 0 '*.txt' 0 0]
[UserFileFilter:
0 # 50] [FullChoosenFile: 0 #50] [ChoosenFile: 0 #20]
[OFN_FLAGS
&OFN_FILEMUSTEXIST+&OFN_PATHMUSTEXIST+&OFN_LONGNAMES+&OFN_EXPLORER+&OFN_HIDEREADONLY]
[OpenFileNameStructure:
len hwndFileOwner: 0 OF_hInstance: 0 FilterStrings
userFileFilter 200 &NULL FullChoosenFile 200
ChoosenFile
200 &NULL OpenFileTitle OFN_FLAGS
nFileOffsetinChoosenFile: W§ 0 nFileExtensioninChoosenFile:
0
DefaultExtension: D§ &NULL
HookCustomData: &NULL HookProcPtr: &NULL HookTemplateName:
0]
[FullPathNameTitle:
B§ 'The Full Filename with Path is: ' 0
OpenFileTitle:
'-=Our First Open File Dialog Box=-: Choose the file to open' 0
FileName:
'The Filename is: ' 0
ExtensionName:
'The Extension is: ' 0]
[OutputString: 0 #200]
[FirstMessage:
0 #7]
__________________________________________________________________________________________
Main:
call 'Kernel32.GetModuleHandleA' 0 | mov D§hInstance eax, D§OF_hinstance
eax ; <<<<<<<<
call 'User32.LoadIconA' &NULL &IDI_APPLICATION | mov D§wc_hIcon eax, D§wc_hIconSm eax
call 'User32.LoadCursorA' 0 &IDC_ARROW | mov D§wc_hCursor eax
call 'User32.RegisterClassExA' WindowClassEx ; registration
of 'CallBack:' is done here.
call 'User32.CreateWindowExA' &WS_EX_CLIENTEDGE ClassName
AppName,
&WS_OVERLAPPEDWINDOW &CW_USEDEFAULT &CW_USEDEFAULT 300 200
,
&NULL &NULL D§hInstance 0
mov D§hwnd eax, D§hwndFileOwner eax ; <<<<<<<<<<<<<<<<<<<<<<<
call 'User32.ShowWindow' D§hwnd &SW_SHOWNORMAL | call 'User32.UpdateWindow' D§hwnd
jmp L1>
L0:
call 'User32.TranslateMessage' Firstmessage
call 'User32.DispatchMessageA' Firstmessage
L1: call 'User32.GetMessageA' FirstMessage 0 0 0
cmp eax 0 | ja L0<
call 'Kernel32.ExitProcess' 0
_______________________________________________________________________________________
[AddString
| mov esi #1 | While B§esi ne 0 | movsb | End_While]
[NextLine
| mov al CR | stosb | mov al LF | stosb]
Proc
MainWindowProc:
Arguments @Adressee, @Message, @wParam, @lParam
pushad
.IF D@Message = &WM_DESTROY
call 'User32.PostQuitMessage' &NULL
.ELSEIF D@Message = &WM_COMMAND
mov eax D@wParam
..if ax = M00_Open
call 'Comdlg32.GetOpenFileNameA' OpenFileNameStructure
...if eax = &TRUE
mov edi OutputString
AddString FullPathNameTitle
AddString FullChoosenFile | NextLine
AddString FileName | AddString ChoosenFile | NextLine
AddString ExtensionName
mov esi FullChoosenFile | movzx eax W§nFileExtensioninChoosenFile
add esi eax | AddString esi | mov eax 0 | stosd
call 'USER32.MessageBoxA' D@Adressee OutputString AppName &MB_OK
...endif
..Else
call 'User32.DestroyWindow' D@Adressee
..End_If
.Else
popad
call 'User32.DefWindowProcA' D@Adressee D@Message D@wParam D@lParam
Exit
.End_If
popad | mov eax &FALSE
EndP
call 'Kernel32.GetModuleHandleA' 0 | mov D§hInstance eax, D§OF_hinstance
eax ; <<<<<<<<
...............
mov D§hwnd eax, D§hwndFileOwner eax ; <<<<<<<<<<<<<<<<<<<<<<<
We fill in the routine the missing members of ofn structures.
This FilterString is the filename filter that we specify as follows:
FilterString: B§ 'All Files', 0, '*.*', 0Note 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.
B§ 'Text Files', 0, "*.txt', 0, 0
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.
[OFN_FLAGS
&OFN_FILEMUSTEXIST+&OFN_PATHMUSTEXIST+&OFN_LONGNAMES+&OFN_EXPLORER+&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.
OpenFileTitle
Specify the title of the dialog box.
call 'Comdlg32.GetOpenFileNameA' OpenFileNameStructure
Call
the GetOpenFileName function. Passing the pointer to the ofn structure
as its parameter.
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.
...if eax = &TRUE
mov edi OutputString
AddString FullPathNameTitle
AddString FullChoosenFile | NextLine
AddString FileName | AddString ChoosenFile | NextLine
AddString ExtensionName
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 a Macro, AddString, 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.
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileOffset
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
mov esi FullChoosenFile | movzx eax W§nFileExtensioninChoosenFile
add esi eax | AddString esi | mov eax 0 | stosd
The above lines require some explanation. FullChoosenFile contains the index into the ofn.lpstrFile. But you cannot add them together directly since nFileExtensioninChoosenFile is a WORD-sized variable and FullChoosenFile is a DWORD-sized one. So I have to put the value of nFileExtensioninChoosenFile into the low word of eax and add it to the value of FullChoosenFile.
call 'USER32.MessageBoxA' D@Adressee OutputString AppName &MB_OK
We
display the string in a message box.