11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 7. Common Dialog Boxes<br />

different. For example, in the dialog’s initialization stage, message WM_INITDIALOG will be sent, if we want<br />

to add other initialization code, we could implement it under “case WM_INITDIALOG” statement.<br />

In <strong>MFC</strong>, this procedure is encapsulated by message mapping. We don’t have to write hook procedure,<br />

because we can map any message to a specific member function. For example, in <strong>MFC</strong>, message<br />

WM_INITDIALOG is always mapped to function OnInitDialog(), so we can always do our initialization work<br />

within this member function.<br />

When we use <strong>MFC</strong> classes to implement common dialog boxes, there is a hook function<br />

_AfxCommDlgProc(…) behind us. We never need to know its existence. However, we use it indirectly<br />

whenever a common dialog box is created. By looking at <strong>MFC</strong> source code, we will find that in the<br />

constructors of common dialog boxes, the address of this function is assigned to member lpfnHook.<br />

To make full use of <strong>MFC</strong> resource, instead of creating a new hook function, we can use<br />

_AfxCommDlgProc(…) when calling API functions to implement common dialog boxes.<br />

Using <strong>MFC</strong> Classes together with API Functions<br />

When we use <strong>MFC</strong> class to create a window, the window’s handle is automatically saved in a member<br />

variable. So we can always use the member functions to access this window. If we use API functions, no<br />

<strong>MFC</strong> class declared variables can participate in window creating activities, so we will not have any variable<br />

that can be used to call the member functions of <strong>MFC</strong> classes for accessing the window. This doesn’t mean<br />

we are going to give up <strong>MFC</strong> implementation completely. Whenever possible, we want to use the member<br />

functions of CColorDialog or CFileDialog instead of implementing everything by our own. Actually, a<br />

window and a <strong>MFC</strong> class declared variable can be associated together after the window is created by<br />

calling function CWnd::Attach(…). The following is the format of this function:<br />

BOOL CWnd::Attach(HWND hWndNew);<br />

So long as we have a valid window handle, we can attach it to a <strong>MFC</strong> class declared variable.<br />

Obtaining Handle<br />

When we call function ::ChooseColor(…) or ::Choosefont(…), no window handle will be returned.<br />

The only place we can obtain dialog’s handle is in the hook function (through parameter hdlg). We can<br />

attach this handle to a CColorDialog or CFontDialog declared variable after receiving message<br />

WM_INITDIALOG.<br />

Accessing Member Variable from Static or Global Function<br />

Because a hook function is a callback function, it must be either a static or global function. Therefore,<br />

we can not access the member variable of a class within the hook function. To let the window handle be<br />

attached to a member variable, we must pass its address to the callback function through a message<br />

parameter. By doing this, after receiving the message, the member variable can be accessed through a<br />

pointer within the callback function.<br />

Both structure CHOOSECOLOR and CHOOSEFONT have a member lCustData, which allows us to specify a<br />

custom data that will be sent to the callback function along with WM_INITDIALOG message. The custom data<br />

will be contained in LPARAM message parameter. So if we assign the address of a variable declared by <strong>MFC</strong><br />

class to member lCustData, we can receive it in the dialog box’ initialization stage and call function<br />

CWnd:: Attach(…) to attach the window handle to this variable.<br />

In other cases we would like to call the default hook procedure. We can store the address of the default<br />

hook procedure in a variable, and call it within the our hook procedure as follows:<br />

UINT CALLBACK CommonHook(HWND hDlg, UINT iMsg, UINT wParam, LONG lParam)<br />

{<br />

if(iMsg == WM_INITDIALOG)<br />

{<br />

CWnd *pDlg;<br />

pDlg=(CWnd *)((LPCHOOSEFONT)lParam)->lCustData;<br />

pDlg->Attach(hDlg);<br />

194

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!