Monitoring Input

Now let's look at what you need in order to monitor the input to the controls in a common dialog box. Notifications about these controls can be monitored through hooks. The dialog procedure provided in COMDLG32.DLL calls the application's hook function if the application specifies the appropriate flag (OFN_ENABLEHOOK) and a pointer to the hook function in the lpfnHook member of the OPENFILENAME structure.

OpenFileName.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_EXPLORER |
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK;
OpenFileName.lpfnHook = (LPOFNHOOKPROC)FileOpenHookProc;

The hook function used in the CMNDLG32 sample simply passes the WM_NOTIFY message to the notification handler:

BOOL APIENTRY FileOpenHookProc (HWND hDlg, UINT message, UINT wParam,
LONG lParam)
{
if (message == WM_NOTIFY)
return FileOpenNotify (hDlg, (LPOFNOTIFY)lParam);

return FALSE;
}

Under Windows 95, the WM_NOTIFY message is sent to the hook procedure for the Open and Save As common dialog boxes whenever an action such as selection occurs. The hook procedure receives the WM_NOTIFY message with the OFNOTIFY structure packaged in its lParam parameter. The OFNOTIFY structure contains information about the notification and the object, including pointers to an NMHDR structure, to the OPENFILENAME structure, and to the current filename.

When the hook procedure receives the WM_NOTIFY message, it can use the code member of the NMHDR structure to determine the current action. The following code traps the notification code and writes it to the status bar. When the user clicks the OK button, the application prompts the user to confirm that the operation should continue.

BOOL NEAR PASCAL FileOpenNotify (HWND hDlg, LPOFNOTIFY pofn)
{
static char lpszNotification [FILE_LEN];
HANDLE hFile;
char szTempText [MAX_PATH];
char szString [MAX_PATH];
DWORD dwBytesWritten;

switch (pofn->hdr.code)
{
// The current selection has changed.
case CDN_SELCHANGE:
{
char szFile [MAX_PATH];

// Get the file specification from the common dialog box.
CommDlg_OpenSave_GetSpec (GetParent (hDlg),
szFile, sizeof (szFile));
wsprintf (lpszNotification,
"File Open Notification: %s. File: %s",
"CDN_SELCHANGE", szFile);
}
break;

// The current folder has changed.
case CDN_FOLDERCHANGE:
{
char szFile [MAX_PATH];

if (CommDlg_OpenSave_GetFolderPath (GetParent (hDlg),
szFile, sizeof (szFile)) <= sizeof (szFile))
{
wsprintf (lpszNotification,
"File Open Notification: %s. File: %s",
"CDN_FOLDERCHANGE", szFile);
}
}
break;

// The Help button has been clicked.
case CDN_HELP:
wsprintf (lpszNotification, "File Open Notification: %s.",
"CDN_HELP");
break;

// The OK button has been clicked.
// To prevent the common dialog box from closing, the result should
// be nonzero via a call to SetWindowLong (hDlg, DWL_MSGRESULT,
// lResult).
case CDN_FILEOK:
SetWindowLong (hDlg, DWL_MSGRESULT, 1L);
wsprintf (lpszNotification,
"File Open Notification: %s. File: %s",
"CDN_FILEOK", pofn->lpOFN->lpstrFile);
GetDlgItemText (hDlg, edt1, szTempText, sizeof (szTempText) -1);
wsprintf (szString, "Are you sure you want to open %s?",
szTempText);
if (MessageBox (hDlg, szString, "Information", MB_YESNO) == IDNO)
{
SetWindowLong (hDlg, DWL_MSGRESULT, -1);
break;
}
// Check to see whether the Create File box is checked.
if ((BOOL) (SendMessage (GetDlgItem (hDlg, chx2),
BM_GETCHECK, 0, 0L)) == TRUE)
{
// If so, create the file.
if ((hFile = CreateFile (szTempText,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL)) == (HANDLE)(-1))
{
MessageBox (hDlg, "Directory could not be created.",
NULL, MB_OK);
SetWindowLong (hDlg, DWL_MSGRESULT, -1);
break;
}

if (WriteFile (hFile, (LPTSTR)FileBuf, dwFileSize,
&dwBytesWritten, NULL) == FALSE)
MessageBox (hDlg, "Error writing file.", NULL, MB_OK);

if (hFile)
CloseHandle (hFile); // close the file
}
break;

// Received a sharing violation
case CDN_SHAREVIOLATION:
wsprintf (lpszNotification, "File Open Notification: %s.",
"CDN_SHAREVIOLATION");
break;

// Received when initialization has finished via the WM_INITDIALOG
// message; all controls moved at this point
case CDN_INITDONE:
wsprintf (lpszNotification, "File Open Notification: %s.",
"CDN_INITDONE");
break;

// Received when the file type changes in the Files Of Type box
case CDN_TYPECHANGE:
wsprintf (lpszNotification, "File Open Notification: %s.",
"CDN_TYPECHANGE");
break;
}

// Write the notification to the status window.
SendMessage (hWndStatus, SB_SETTEXT, 0, (LPARAM)lpszNotification);

return TRUE;
}