Customized open file dialog

File open dialog is a part of windows subsystem and comes with commdlg32.dll package. In normal senarios we pass the file path buffer and it returns the path which is selected by the user. However there are additional facilities can be given with this dialog. Additional GUI controls can be added using a resource template. A hook procedure can be added to handle the events from these custom controls.

Uses

Customization of file open dialog is helpful for applications like Photo editors, audio editors etc. Here are some common usage of custom dialogs.

  1. An audio application can add a play sound file for preview before opening
  2. Photo or graphics editor applications can add a thumnail preview of the file
  3. User can display metadata information like author, revision etc

Demo Application

Here is the demo and we have mainly these steps to make a custom open file dialog.

  1. Add a dialg bar child resource in the project
  2. Add necessary button, text, ActiveX or other GUI controls
  3. Give ID for each controls
  4. Add OFN_ENABLETEMPLATE and OFN_ENABLEHOOK for OPENFILENAME.Flags
  5. Add lpTemplateName = MAKEINTRESOURCE(<DIALOGBAR resource ID>)
  6. Add hook procedure and implement all the notify events needed
  7. Update the lpfnHook = hook procedure address

Here is the C++ source file followed by the resource script.

#include <windows.h>
#include <commdlg.h>
#include "resource.h"
#include <mmsystem.h>

UINT CALLBACK OfnHookProc(HWND hDlg, UINT uMsg, UINT wParam, LONG lParam)
{
  OFNOTIFY* pofNotify;
  HWND hTrueDlg;
  TCHAR szPathName[_MAX_PATH] = { 0 };

  switch (uMsg)
  {
    case WM_COMMAND:
    {
      /* Play button is pressed */
      if(LOWORD(wParam) == IDC_PLAYPREVIEW) { 
        GetDlgItemText(hDlg,IDC_STATIC_HINT, szPathName,_MAX_PATH);
        PlaySound(szPathName, NULL,SND_SYNC|SND_FILENAME); /*Play sound file */
        return (TRUE);
      }
    }
    case WM_NOTIFY:
      pofNotify = (OFNOTIFY*)lParam;
      switch (pofNotify->hdr.code)
      {
        /* Init open dialog */
        case CDN_INITDONE:
          return (TRUE);
        /* File selection changed */
        case CDN_SELCHANGE:
          hTrueDlg = GetParent(hDlg);
          SendMessage(hTrueDlg, CDM_GETFILEPATH, _MAX_PATH, (LONG)szPathName);
          SetDlgItemText(hDlg, IDC_STATIC_HINT, szPathName);
          return (TRUE);
        /* Folder selection changed */
        case CDN_FOLDERCHANGE:
          hTrueDlg = GetParent(hDlg);
          SendMessage(hTrueDlg, CDM_GETFOLDERPATH, _MAX_PATH, (LONG)szPathName);
          SetDlgItemText(hDlg, IDC_STATIC_HINT, szPathName);
          return (TRUE);
        /* User selected open */
        case CDN_FILEOK:
          return TRUE;
        default:
          return FALSE;
      }
    default:
      return (FALSE);
  }
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  OPENFILENAME ofn;
  TCHAR szFilePath[260];
  memset(&ofn,0,sizeof(ofn));
  ofn.lStructSize = sizeof(ofn);
  ofn.hwndOwner = NULL;
  ofn.lpstrFilter = "Wave Audio*.wav";
  ofn.Flags = OFN_EXPLORER |  /* chicago-style dialog box */
    OFN_FILEMUSTEXIST |       /* can't choose non-existing file */
    OFN_HIDEREADONLY |        /* hide "read-only" checkbox */
    OFN_ENABLEHOOK |          /* use hook function */
    OFN_ENABLETEMPLATE;       /* custom template resource */
            
  ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOGBAR);
  ofn.hInstance = hInstance;
  ofn.lpfnHook = OfnHookProc;
  ofn.lpstrFile = szFilePath;
  ofn.lpstrFile[0] = 0;
  ofn.nFilterIndex = 1;
  ofn.lpstrFileTitle = NULL;
  ofn.nMaxFileTitle = 0;
  ofn.lpstrInitialDir = NULL;
  ofn.nMaxFile = 260;
  ofn.lpstrTitle = "open a wave audio file";

  if(GetOpenFileName(&ofn)){
    MessageBox(NULL,ofn.lpstrFile,"Your file", MB_OK);
  }
  return 0;
}

Resource template

customized file open resource template

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOGBAR DIALOGEX 0, 0, 269, 26
STYLE WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
    LTEXT           "Customized File open",IDC_STATIC_HINT,7,7,222,12,0,
                    WS_EX_STATICEDGE
    PUSHBUTTON      "Play",IDC_PLAYPREVIEW,231,7,31,12
END

Output

customized file open

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#