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 />

……<br />

m_pColorDlg->m_cc.lCustData=(LONG)m_pColorDlg;<br />

m_pColorDlg->m_cc.Flags|=CC_ENABLETEMPLATE | CC_FULLOPEN;<br />

m_pColorDlg->m_cc.hwndOwner=m_pColorDmDlg->GetSafeHwnd();<br />

m_pColorDlg->m_cc.lpTemplateName="CHOOSECUSCOLOR";<br />

m_pColorDlg->m_cc.hInstance=(HWND)AfxGetInstanceHandle();<br />

The address of m_pColorDlg is stored as custom data, which will be sent to the hook function. The<br />

dummy window is designated as the parent window of the color dialog box and its handle is assigned to<br />

member hwndOwner of structure CHOOSECOLOR. A global COLORREF type array rgbColors is declared, which<br />

will be used to initialize the custom colors in the color dialog box. Also, custom dialog template<br />

"CHOOSECUSCOLOR" is used, which will allow the user to choose color from only custom colors.<br />

The address of default hook procedure (which is contained in member lpfnHook of structure<br />

CHOOSECOLOR after the constructor of class CColorDlg is called) is stored in global variable lpColorfn, and<br />

the new hook procedure address is assigned to lpfnHook. Finally, API function ::ChooseColor(…) is called<br />

to invoke the color dialog box:<br />

……<br />

}<br />

lpColorfn=m_pColorDlg->m_cc.lpfnHook;<br />

m_pColorDlg->m_cc.lpfnHook=ColorHook;<br />

::ChooseColor(&m_pColorDlg->m_cc);<br />

In the hook procedure, after receiving message WM_INITDIALOG, we can obtain the value of<br />

m_pColorDlg from LPARAM parameter and attach the color dialog box’s window handle to it:<br />

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

{<br />

switch(iMsg)<br />

{<br />

case WM_INITDIALOG:<br />

{<br />

CColorDialog *pDlg;<br />

}<br />

pDlg=(CColorDialog *)((LPCHOOSECOLOR)lParam)->lCustData;<br />

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

break;<br />

}<br />

}<br />

return lpColorfn(hDlg, iMsg, wParam, lParam);<br />

However, there are still some problems left to be solved. Since the dialog box is modeless now, we can<br />

execute command Color Dialog Box | Modeless again when the dialog box is being used. Also, in the new<br />

situation, the user is able to exit the application without closing the dialog box first.<br />

To avoid the dummy dialog box and the color dialog box from being created again while they are<br />

active, we have to check m_pColorDlg and m_pColorDmDlg variables. First, if they are NULL, it means the<br />

variables have not been initialized, we need to allocate buffers and create the window. If they are not<br />

NULL, there are two possibilities: 1) The dialog box is currently active. 2) The dialog box is closed.<br />

Obviously we don’t need to do anything for the first case. For the second case, we need to reinitialize the<br />

two variables and create the window again. Since the window handle is attached to the variable in the hook<br />

procedure, we need to detach it before releasing the allocated buffers. For the above reasons, the following<br />

is added to the beginning of function CCDBDoc::OnColordialogboxModeless():<br />

void CCDBDoc::OnColordialogboxModeless()<br />

{<br />

if(m_pColorDlg != NULL)<br />

{<br />

if(::IsWindow(m_pColorDlg->GetSafeHwnd()) == TRUE)return;<br />

if(m_pColorDlg->GetSafeHwnd() != NULL)m_pColorDlg->Detach();<br />

delete m_pColorDlg;<br />

if(m_pColorDmDlg != NULL)delete m_pColorDmDlg;<br />

m_pColorDmDlg=NULL;<br />

196

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

Saved successfully!

Ooh no, something went wrong!