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.
 

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.

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: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:
 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 ]
Let's see the meaning of the frequently used members.
 
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

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.
 

[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


Analysis:

 

 
 
 

            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, '*.*', 0
                    B§ '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.
 

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.


[Iczelion's Win32 Assembly HomePage]