home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / dlgcore.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  24KB  |  893 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include "occimpl.h"
  13.  
  14. #ifdef AFX_CORE1_SEG
  15. #pragma code_seg(AFX_CORE1_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // AfxDlgProc - does nothing since all messages are handled via AfxWndProc
  27.  
  28. BOOL CALLBACK AfxDlgProc(HWND hWnd, UINT message, WPARAM, LPARAM)
  29. {
  30.     if (message == WM_INITDIALOG)
  31.     {
  32.         // special case for WM_INITDIALOG
  33.         CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, CWnd::FromHandlePermanent(hWnd));
  34.         if (pDlg != NULL)
  35.             return pDlg->OnInitDialog();
  36.         else
  37.             return 1;
  38.     }
  39.     return 0;
  40. }
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CDialog - Modeless and Modal
  44.  
  45. BEGIN_MESSAGE_MAP(CDialog, CWnd)
  46. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  47.     ON_WM_CTLCOLOR()
  48. #endif
  49.     //{{AFX_MSG_MAP(CDialog)
  50.     ON_COMMAND(IDOK, OnOK)
  51.     ON_COMMAND(IDCANCEL, OnCancel)
  52.     ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
  53.     ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
  54.     ON_MESSAGE(WM_INITDIALOG, HandleInitDialog)
  55.     ON_MESSAGE(WM_SETFONT, HandleSetFont)
  56.     //}}AFX_MSG_MAP
  57. #ifndef _AFX_NO_CTL3D_SUPPORT
  58.     ON_MESSAGE(WM_QUERY3DCONTROLS, OnQuery3dControls)
  59. #endif
  60. END_MESSAGE_MAP()
  61.  
  62. BOOL CDialog::PreTranslateMessage(MSG* pMsg)
  63. {
  64.     // for modeless processing (or modal)
  65.     ASSERT(m_hWnd != NULL);
  66.  
  67.     // allow tooltip messages to be filtered
  68.     if (CWnd::PreTranslateMessage(pMsg))
  69.         return TRUE;
  70.  
  71.     // don't translate dialog messages when in Shift+F1 help mode
  72.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  73.     if (pFrameWnd != NULL && pFrameWnd->m_bHelpMode)
  74.         return FALSE;
  75.  
  76.     // fix around for VK_ESCAPE in a multiline Edit that is on a Dialog
  77.     // that doesn't have a cancel or the cancel is disabled.
  78.     if (pMsg->message == WM_KEYDOWN &&
  79.         (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_CANCEL) &&
  80.         (::GetWindowLong(pMsg->hwnd, GWL_STYLE) & ES_MULTILINE) &&
  81.         _AfxCompareClassName(pMsg->hwnd, _T("Edit")))
  82.     {
  83.         HWND hItem = ::GetDlgItem(m_hWnd, IDCANCEL);
  84.         if (hItem == NULL || ::IsWindowEnabled(hItem))
  85.         {
  86.             SendMessage(WM_COMMAND, IDCANCEL, 0);
  87.             return TRUE;
  88.         }
  89.     }
  90.     // filter both messages to dialog and from children
  91.     return PreTranslateInput(pMsg);
  92. }
  93.  
  94. BOOL CDialog::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  95.     AFX_CMDHANDLERINFO* pHandlerInfo)
  96. {
  97.     if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  98.         return TRUE;
  99.  
  100.     if ((nCode != CN_COMMAND && nCode != CN_UPDATE_COMMAND_UI) ||
  101.             !IS_COMMAND_ID(nID) || nID >= 0xf000)
  102.     {
  103.         // control notification or non-command button or system command
  104.         return FALSE;       // not routed any further
  105.     }
  106.  
  107.     // if we have an owner window, give it second crack
  108.     CWnd* pOwner = GetParent();
  109.     if (pOwner != NULL)
  110.     {
  111. #ifdef _DEBUG
  112.         if (afxTraceFlags & traceCmdRouting)
  113.             TRACE1("Routing command id 0x%04X to owner window.\n", nID);
  114. #endif
  115.         ASSERT(pOwner != this);
  116.         if (pOwner->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  117.             return TRUE;
  118.     }
  119.  
  120.     // last crack goes to the current CWinThread object
  121.     CWinThread* pThread = AfxGetThread();
  122.     if (pThread != NULL)
  123.     {
  124. #ifdef _DEBUG
  125.         if (afxTraceFlags & traceCmdRouting)
  126.             TRACE1("Routing command id 0x%04X to app.\n", nID);
  127. #endif
  128.         if (pThread->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  129.             return TRUE;
  130.     }
  131.  
  132. #ifdef _DEBUG
  133.     if (afxTraceFlags & traceCmdRouting)
  134.     {
  135.         TRACE2("IGNORING command id 0x%04X sent to %hs dialog.\n", nID,
  136.                 GetRuntimeClass()->m_lpszClassName);
  137.     }
  138. #endif
  139.     return FALSE;
  140. }
  141.  
  142. /////////////////////////////////////////////////////////////////////////////
  143. // Modeless Dialogs have 2-phase construction
  144.  
  145. CDialog::CDialog()
  146. {
  147.     ASSERT(m_hWnd == NULL);
  148.     AFX_ZERO_INIT_OBJECT(CWnd);
  149. }
  150.  
  151. CDialog::~CDialog()
  152. {
  153.     if (m_hWnd != NULL)
  154.     {
  155.         TRACE0("Warning: calling DestroyWindow in CDialog::~CDialog --\n");
  156.         TRACE0("\tOnDestroy or PostNcDestroy in derived class will not be called.\n");
  157.         DestroyWindow();
  158.     }
  159. }
  160.  
  161. BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
  162. {
  163.     ASSERT(HIWORD(lpszTemplateName) == 0 ||
  164.         AfxIsValidString(lpszTemplateName));
  165.  
  166.     m_lpszTemplateName = lpszTemplateName;  // used for help
  167.     if (HIWORD(m_lpszTemplateName) == 0 && m_nIDHelp == 0)
  168.         m_nIDHelp = LOWORD((DWORD)m_lpszTemplateName);
  169.  
  170. #ifdef _DEBUG
  171.     if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE))
  172.     {
  173.         ASSERT(FALSE);          // invalid dialog template name
  174.         PostNcDestroy();        // cleanup if Create fails too soon
  175.         return FALSE;
  176.     }
  177. #endif //_DEBUG
  178.  
  179.     HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
  180.     HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
  181.     HGLOBAL hTemplate = LoadResource(hInst, hResource);
  182.     BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst);
  183.     FreeResource(hTemplate);
  184.  
  185.     return bResult;
  186. }
  187.  
  188. // for backward compatibility
  189. BOOL CDialog::CreateIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd)
  190. {
  191.     return CreateIndirect(hDialogTemplate, pParentWnd, NULL);
  192. }
  193.  
  194. BOOL CDialog::CreateIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd,
  195.     HINSTANCE hInst)
  196. {
  197.     ASSERT(hDialogTemplate != NULL);
  198.  
  199.     LPCDLGTEMPLATE lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
  200.     BOOL bResult = CreateIndirect(lpDialogTemplate, pParentWnd, NULL, hInst);
  201.     UnlockResource(hDialogTemplate);
  202.  
  203.     return bResult;
  204. }
  205.  
  206. // for backward compatibility
  207. BOOL CDialog::CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd,
  208.     void* lpDialogInit)
  209. {
  210.     return CreateIndirect(lpDialogTemplate, pParentWnd, lpDialogInit, NULL);
  211. }
  212.  
  213. BOOL CDialog::CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd,
  214.     void* lpDialogInit, HINSTANCE hInst)
  215. {
  216.     ASSERT(lpDialogTemplate != NULL);
  217.  
  218.     if (pParentWnd == NULL)
  219.         pParentWnd = AfxGetMainWnd();
  220.     m_lpDialogInit = lpDialogInit;
  221.  
  222.     return CreateDlgIndirect(lpDialogTemplate, pParentWnd, hInst);
  223. }
  224.  
  225. BOOL CWnd::CreateDlg(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
  226. {
  227.     // load resource
  228.     LPCDLGTEMPLATE lpDialogTemplate = NULL;
  229.     HGLOBAL hDialogTemplate = NULL;
  230.     HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
  231.     HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
  232.     hDialogTemplate = LoadResource(hInst, hResource);
  233.     if (hDialogTemplate != NULL)
  234.         lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
  235.     ASSERT(lpDialogTemplate != NULL);
  236.  
  237.     // create a modeless dialog
  238.     BOOL bSuccess = CreateDlgIndirect(lpDialogTemplate, pParentWnd, hInst);
  239.  
  240.     // free resource
  241.     UnlockResource(hDialogTemplate);
  242.     FreeResource(hDialogTemplate);
  243.  
  244.     return bSuccess;
  245. }
  246.  
  247. // for backward compatibility
  248. BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd)
  249. {
  250.     return CreateDlgIndirect(lpDialogTemplate, pParentWnd, NULL);
  251. }
  252.  
  253. BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
  254.     CWnd* pParentWnd, HINSTANCE hInst)
  255. {
  256.     ASSERT(lpDialogTemplate != NULL);
  257.     if (pParentWnd != NULL)
  258.         ASSERT_VALID(pParentWnd);
  259.  
  260.     if (hInst == NULL)
  261.         hInst = AfxGetInstanceHandle();
  262.  
  263. #ifndef _AFX_NO_OCC_SUPPORT
  264.     _AFX_OCC_DIALOG_INFO occDialogInfo;
  265.     COccManager* pOccManager = afxOccManager;
  266. #endif
  267.  
  268.     HGLOBAL hTemplate = NULL;
  269.  
  270.     HWND hWnd = NULL;
  271. #ifdef _DEBUG
  272.     DWORD dwError = 0;
  273. #endif
  274.  
  275.     TRY
  276.     {
  277.         VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
  278.         AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
  279.  
  280. #ifndef _AFX_NO_OCC_SUPPORT
  281.         // separately create OLE controls in the dialog template
  282.         if (pOccManager != NULL)
  283.         {
  284.             if (!SetOccDialogInfo(&occDialogInfo))
  285.                 return FALSE;
  286.  
  287.             lpDialogTemplate = pOccManager->PreCreateDialog(&occDialogInfo,
  288.                 lpDialogTemplate);
  289.         }
  290.  
  291.         if (lpDialogTemplate == NULL)
  292.             return FALSE;
  293. #endif //!_AFX_NO_OCC_SUPPORT
  294.  
  295.         // If no font specified, set the system font.
  296.         CString strFace;
  297.         WORD wSize = 0;
  298.         BOOL bSetSysFont = !CDialogTemplate::GetFont(lpDialogTemplate, strFace,
  299.             wSize);
  300.  
  301.         // On DBCS systems, also change "MS Sans Serif" or "Helv" to system font.
  302.         if ((!bSetSysFont) && GetSystemMetrics(SM_DBCSENABLED))
  303.         {
  304.             bSetSysFont = (strFace == _T("MS Shell Dlg") ||
  305.                 strFace == _T("MS Sans Serif") || strFace == _T("Helv"));
  306.             if (bSetSysFont && (wSize == 8))
  307.                 wSize = 0;
  308.         }
  309.  
  310.         if (bSetSysFont)
  311.         {
  312.             CDialogTemplate dlgTemp(lpDialogTemplate);
  313.             dlgTemp.SetSystemFont(wSize);
  314.             hTemplate = dlgTemp.Detach();
  315.         }
  316.  
  317.         if (hTemplate != NULL)
  318.             lpDialogTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate);
  319.  
  320.         // setup for modal loop and creation
  321.         m_nModalResult = -1;
  322.         m_nFlags |= WF_CONTINUEMODAL;
  323.  
  324.         // create modeless dialog
  325.         AfxHookWindowCreate(this);
  326.         hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
  327.             pParentWnd->GetSafeHwnd(), AfxDlgProc);
  328. #ifdef _DEBUG
  329.         dwError = ::GetLastError();
  330. #endif
  331.     }
  332.     CATCH_ALL(e)
  333.     {
  334.         DELETE_EXCEPTION(e);
  335.         m_nModalResult = -1;
  336.     }
  337.     END_CATCH_ALL
  338.  
  339. #ifndef _AFX_NO_OCC_SUPPORT
  340.     if (pOccManager != NULL)
  341.     {
  342.         pOccManager->PostCreateDialog(&occDialogInfo);
  343.         if (hWnd != NULL)
  344.             SetOccDialogInfo(NULL);
  345.     }
  346. #endif //!_AFX_NO_OCC_SUPPORT
  347.  
  348.     if (!AfxUnhookWindowCreate())
  349.         PostNcDestroy();        // cleanup if Create fails too soon
  350.  
  351.     // handle EndDialog calls during OnInitDialog
  352.     if (hWnd != NULL && !(m_nFlags & WF_CONTINUEMODAL))
  353.     {
  354.         ::DestroyWindow(hWnd);
  355.         hWnd = NULL;
  356.     }
  357.  
  358.     if (hTemplate != NULL)
  359.     {
  360.         GlobalUnlock(hTemplate);
  361.         GlobalFree(hTemplate);
  362.     }
  363.  
  364.     // help with error diagnosis (only if WM_INITDIALOG didn't EndDialog())
  365.     if (hWnd == NULL && (m_nFlags & WF_CONTINUEMODAL))
  366.     {
  367. #ifdef _DEBUG
  368. #ifndef _AFX_NO_OCC_SUPPORT
  369.         if (afxOccManager == NULL)
  370.         {
  371.             TRACE0(">>> If this dialog has OLE controls:\n");
  372.             TRACE0(">>> AfxEnableControlContainer has not been called yet.\n");
  373.             TRACE0(">>> You should call it in your app's InitInstance function.\n");
  374.         }
  375.         else if (dwError != 0)
  376.         {
  377.             TRACE1("Warning: Dialog creation failed!  GetLastError returns 0x%8.8X\n", dwError);
  378.         }
  379. #endif //!_AFX_NO_OCC_SUPPORT
  380. #endif //_DEBUG
  381.         return FALSE;
  382.     }
  383.  
  384.     ASSERT(hWnd == m_hWnd);
  385.     return TRUE;
  386. }
  387.  
  388. #ifndef _AFX_NO_OCC_SUPPORT
  389.  
  390. BOOL CDialog::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO* pOccDialogInfo)
  391. {
  392.     m_pOccDialogInfo = pOccDialogInfo;
  393.     return TRUE;
  394. }
  395.  
  396. #endif
  397.  
  398. /////////////////////////////////////////////////////////////////////////////
  399. // Modal Dialogs
  400.  
  401. // Modal Constructors just save parameters
  402. CDialog::CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
  403. {
  404.     ASSERT(HIWORD(lpszTemplateName) == 0 ||
  405.         AfxIsValidString(lpszTemplateName));
  406.  
  407.     AFX_ZERO_INIT_OBJECT(CWnd);
  408.  
  409.     m_pParentWnd = pParentWnd;
  410.     m_lpszTemplateName = lpszTemplateName;
  411.     if (HIWORD(m_lpszTemplateName) == 0)
  412.         m_nIDHelp = LOWORD((DWORD)m_lpszTemplateName);
  413. }
  414.  
  415. CDialog::CDialog(UINT nIDTemplate, CWnd* pParentWnd)
  416. {
  417.     AFX_ZERO_INIT_OBJECT(CWnd);
  418.  
  419.     m_pParentWnd = pParentWnd;
  420.     m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate);
  421.     m_nIDHelp = nIDTemplate;
  422. }
  423.  
  424. BOOL CDialog::InitModalIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd)
  425. {
  426.     // must be called on an empty constructed CDialog
  427.     ASSERT(m_lpszTemplateName == NULL);
  428.     ASSERT(m_hDialogTemplate == NULL);
  429.     ASSERT(hDialogTemplate != NULL);
  430.  
  431.     if (m_pParentWnd == NULL)
  432.         m_pParentWnd = pParentWnd;
  433.  
  434.     m_hDialogTemplate = hDialogTemplate;
  435.  
  436.     return TRUE;    // always ok (DoModal actually brings up dialog)
  437. }
  438.  
  439. BOOL CDialog::InitModalIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd,
  440.     void* lpDialogInit)
  441. {
  442.     // must be called on an empty constructed CDialog
  443.     ASSERT(m_lpszTemplateName == NULL);
  444.     ASSERT(m_lpDialogTemplate == NULL);
  445.     ASSERT(lpDialogTemplate != NULL);
  446.  
  447.     if (m_pParentWnd == NULL)
  448.         m_pParentWnd = pParentWnd;
  449.  
  450.     m_lpDialogTemplate = lpDialogTemplate;
  451.     m_lpDialogInit = lpDialogInit;
  452.  
  453.     return TRUE;    // always ok (DoModal actually brings up dialog)
  454. }
  455.  
  456. HWND CDialog::PreModal()
  457. {
  458.     // cannot call DoModal on a dialog already constructed as modeless
  459.     ASSERT(m_hWnd == NULL);
  460.  
  461.     // allow OLE servers to disable themselves
  462.     CWinApp* pApp = AfxGetApp();
  463.     if (pApp != NULL)
  464.         pApp->EnableModeless(FALSE);
  465.  
  466.     // find parent HWND
  467.     HWND hWnd = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &m_hWndTop);
  468.  
  469.     // hook for creation of dialog
  470.     AfxHookWindowCreate(this);
  471.  
  472.     // return window to use as parent for dialog
  473.     return hWnd;
  474. }
  475.  
  476. void CDialog::PostModal()
  477. {
  478.     AfxUnhookWindowCreate();   // just in case
  479.     Detach();               // just in case
  480.  
  481.     // re-enable windows
  482.     if (::IsWindow(m_hWndTop))
  483.         ::EnableWindow(m_hWndTop, TRUE);
  484.     m_hWndTop = NULL;
  485.     CWinApp* pApp = AfxGetApp();
  486.     if (pApp != NULL)
  487.         pApp->EnableModeless(TRUE);
  488. }
  489.  
  490. int CDialog::DoModal()
  491. {
  492.     // can be constructed with a resource template or InitModalIndirect
  493.     ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
  494.         m_lpDialogTemplate != NULL);
  495.  
  496.     // load resource as necessary
  497.     LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
  498.     HGLOBAL hDialogTemplate = m_hDialogTemplate;
  499.     HINSTANCE hInst = AfxGetResourceHandle();
  500.     if (m_lpszTemplateName != NULL)
  501.     {
  502.         hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
  503.         HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
  504.         hDialogTemplate = LoadResource(hInst, hResource);
  505.     }
  506.     if (hDialogTemplate != NULL)
  507.         lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
  508.  
  509.     // return -1 in case of failure to load the dialog template resource
  510.     if (lpDialogTemplate == NULL)
  511.         return -1;
  512.  
  513.     // disable parent (before creating dialog)
  514.     HWND hWndParent = PreModal();
  515.     AfxUnhookWindowCreate();
  516.     BOOL bEnableParent = FALSE;
  517.     if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
  518.     {
  519.         ::EnableWindow(hWndParent, FALSE);
  520.         bEnableParent = TRUE;
  521.     }
  522.  
  523.     TRY
  524.     {
  525.         // create modeless dialog
  526.         AfxHookWindowCreate(this);
  527.         if (CreateDlgIndirect(lpDialogTemplate,
  528.                         CWnd::FromHandle(hWndParent), hInst))
  529.         {
  530.             if (m_nFlags & WF_CONTINUEMODAL)
  531.             {
  532.                 // enter modal loop
  533.                 DWORD dwFlags = MLF_SHOWONIDLE;
  534.                 if (GetStyle() & DS_NOIDLEMSG)
  535.                     dwFlags |= MLF_NOIDLEMSG;
  536.                 VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
  537.             }
  538.  
  539.             // hide the window before enabling the parent, etc.
  540.             if (m_hWnd != NULL)
  541.                 SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|
  542.                     SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
  543.         }
  544.     }
  545.     CATCH_ALL(e)
  546.     {
  547.         DELETE_EXCEPTION(e);
  548.         m_nModalResult = -1;
  549.     }
  550.     END_CATCH_ALL
  551.  
  552.     if (bEnableParent)
  553.         ::EnableWindow(hWndParent, TRUE);
  554.     if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
  555.         ::SetActiveWindow(hWndParent);
  556.  
  557.     // destroy modal window
  558.     DestroyWindow();
  559.     PostModal();
  560.  
  561.     // unlock/free resources as necessary
  562.     if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL)
  563.         UnlockResource(hDialogTemplate);
  564.     if (m_lpszTemplateName != NULL)
  565.         FreeResource(hDialogTemplate);
  566.  
  567.     return m_nModalResult;
  568. }
  569.  
  570. void CDialog::EndDialog(int nResult)
  571. {
  572.     ASSERT(::IsWindow(m_hWnd));
  573.  
  574.     if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL))
  575.         EndModalLoop(nResult);
  576.  
  577.     ::EndDialog(m_hWnd, nResult);
  578. }
  579.  
  580. /////////////////////////////////////////////////////////////////////////////
  581. // Standard CDialog implementation
  582.  
  583. LRESULT CDialog::HandleSetFont(WPARAM wParam, LPARAM)
  584. {
  585.     OnSetFont(CFont::FromHandle((HFONT)wParam));
  586.     return Default();
  587. }
  588.  
  589. void CDialog::PreInitDialog()
  590. {
  591.     // ignore it
  592. }
  593.  
  594. LRESULT CDialog::HandleInitDialog(WPARAM, LPARAM)
  595. {
  596.     PreInitDialog();
  597.  
  598. #ifndef _AFX_NO_OCC_SUPPORT
  599.     // create OLE controls
  600.     COccManager* pOccManager = afxOccManager;
  601.     if ((pOccManager != NULL) && (m_pOccDialogInfo != NULL))
  602.     {
  603.         BOOL bDlgInit;
  604.         if (m_lpDialogInit != NULL)
  605.             bDlgInit = pOccManager->CreateDlgControls(this, m_lpDialogInit,
  606.                 m_pOccDialogInfo);
  607.         else
  608.             bDlgInit = pOccManager->CreateDlgControls(this, m_lpszTemplateName,
  609.                 m_pOccDialogInfo);
  610.  
  611.         if (!bDlgInit)
  612.         {
  613.             TRACE0("Warning: CreateDlgControls failed during dialog init.\n");
  614.             EndDialog(-1);
  615.             return FALSE;
  616.         }
  617.     }
  618. #endif
  619.  
  620.     // Default will call the dialog proc, and thus OnInitDialog
  621.     BOOL bResult = Default();
  622.  
  623. #ifndef _AFX_NO_OCC_SUPPORT
  624.     if (bResult && (m_nFlags & WF_OLECTLCONTAINER))
  625.     {
  626.         CWnd* pWndNext = GetNextDlgTabItem(NULL);
  627.         if (pWndNext != NULL)
  628.         {
  629.             pWndNext->SetFocus();   // UI Activate OLE control
  630.             bResult = FALSE;
  631.         }
  632.     }
  633. #endif
  634.  
  635.     return bResult;
  636. }
  637.  
  638. BOOL AFXAPI AfxHelpEnabled()
  639. {
  640.     if (AfxGetApp() == NULL)
  641.         return FALSE;
  642.  
  643.     // help is enabled if the app has a handler for ID_HELP
  644.     AFX_CMDHANDLERINFO info;
  645.  
  646.     // check main window first
  647.     CWnd* pWnd = AfxGetMainWnd();
  648.     if (pWnd != NULL && pWnd->OnCmdMsg(ID_HELP, CN_COMMAND, NULL, &info))
  649.         return TRUE;
  650.  
  651.     // check app last
  652.     return AfxGetApp()->OnCmdMsg(ID_HELP, CN_COMMAND, NULL, &info);
  653. }
  654.  
  655. void CDialog::OnSetFont(CFont*)
  656. {
  657.     // ignore it
  658. }
  659.  
  660. BOOL CDialog::OnInitDialog()
  661. {
  662.     // execute dialog RT_DLGINIT resource
  663.     BOOL bDlgInit;
  664.     if (m_lpDialogInit != NULL)
  665.         bDlgInit = ExecuteDlgInit(m_lpDialogInit);
  666.     else
  667.         bDlgInit = ExecuteDlgInit(m_lpszTemplateName);
  668.  
  669.     if (!bDlgInit)
  670.     {
  671.         TRACE0("Warning: ExecuteDlgInit failed during dialog init.\n");
  672.         EndDialog(-1);
  673.         return FALSE;
  674.     }
  675.  
  676.     // transfer data into the dialog from member variables
  677.     if (!UpdateData(FALSE))
  678.     {
  679.         TRACE0("Warning: UpdateData failed during dialog init.\n");
  680.         EndDialog(-1);
  681.         return FALSE;
  682.     }
  683.  
  684.     // enable/disable help button automatically
  685.     CWnd* pHelpButton = GetDlgItem(ID_HELP);
  686.     if (pHelpButton != NULL)
  687.         pHelpButton->ShowWindow(AfxHelpEnabled() ? SW_SHOW : SW_HIDE);
  688.  
  689.     return TRUE;    // set focus to first one
  690. }
  691.  
  692. void CDialog::OnOK()
  693. {
  694.     if (!UpdateData(TRUE))
  695.     {
  696.         TRACE0("UpdateData failed during dialog termination.\n");
  697.         // the UpdateData routine will set focus to correct item
  698.         return;
  699.     }
  700.     EndDialog(IDOK);
  701. }
  702.  
  703. void CDialog::OnCancel()
  704. {
  705.     EndDialog(IDCANCEL);
  706. }
  707.  
  708. BOOL CDialog::CheckAutoCenter()
  709. {
  710.     // load resource as necessary
  711.     LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
  712.     HGLOBAL hDialogTemplate = m_hDialogTemplate;
  713.     if (m_lpszTemplateName != NULL)
  714.     {
  715.         HINSTANCE hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
  716.         HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
  717.         hDialogTemplate = LoadResource(hInst, hResource);
  718.     }
  719.     if (hDialogTemplate != NULL)
  720.         lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
  721.  
  722.     // determine if dialog should be centered
  723.     BOOL bResult = TRUE;
  724.  
  725.     if (lpDialogTemplate != NULL)
  726.     {
  727.         DWORD dwStyle = lpDialogTemplate->style;
  728.         short x;
  729.         short y;
  730.  
  731.         if (((DLGTEMPLATEEX*)lpDialogTemplate)->signature == 0xFFFF)
  732.         {
  733.             // it's a DIALOGEX resource
  734.             dwStyle = ((DLGTEMPLATEEX*)lpDialogTemplate)->style;
  735.             x = ((DLGTEMPLATEEX*)lpDialogTemplate)->x;
  736.             y = ((DLGTEMPLATEEX*)lpDialogTemplate)->y;
  737.         }
  738.         else
  739.         {
  740.             // it's a DIALOG resource
  741.             x = lpDialogTemplate->x;
  742.             y = lpDialogTemplate->y;
  743.         }
  744.  
  745.         bResult = !(dwStyle & (DS_CENTER|DS_CENTERMOUSE|DS_ABSALIGN)) &&
  746.             x == 0 && y == 0;
  747.     }
  748.  
  749.     // unlock/free resources as necessary
  750.     if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL)
  751.         UnlockResource(hDialogTemplate);
  752.     if (m_lpszTemplateName != NULL)
  753.         FreeResource(hDialogTemplate);
  754.  
  755.     return bResult; // TRUE if auto-center is ok
  756. }
  757.  
  758. /////////////////////////////////////////////////////////////////////////////
  759. // Gray background support
  760.  
  761. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  762. HBRUSH CDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  763. {
  764.     // use helper in CWnd
  765.     return OnGrayCtlColor(pDC, pWnd, nCtlColor);
  766. }
  767. #endif //!_AFX_NO_GRAYDLG_SUPPORT
  768.  
  769. /////////////////////////////////////////////////////////////////////////////
  770. // CDialog support for context sensitive help.
  771.  
  772. LRESULT CDialog::OnCommandHelp(WPARAM, LPARAM lParam)
  773. {
  774.     if (lParam == 0 && m_nIDHelp != 0)
  775.         lParam = HID_BASE_RESOURCE + m_nIDHelp;
  776.     if (lParam != 0)
  777.     {
  778.         CWinApp* pApp = AfxGetApp();
  779.         if (pApp != NULL)
  780.             pApp->WinHelp(lParam);
  781.         return TRUE;
  782.     }
  783.     return FALSE;
  784. }
  785.  
  786. LRESULT CDialog::OnHelpHitTest(WPARAM, LPARAM)
  787. {
  788.     if (m_nIDHelp != 0)
  789.         return HID_BASE_RESOURCE + m_nIDHelp;
  790.     return 0;
  791. }
  792.  
  793. /////////////////////////////////////////////////////////////////////////////
  794. // CDialog Diagnostics
  795.  
  796. #ifdef _DEBUG
  797. void CDialog::AssertValid() const
  798. {
  799.     CWnd::AssertValid();
  800. }
  801.  
  802. void CDialog::Dump(CDumpContext& dc) const
  803. {
  804.     CWnd::Dump(dc);
  805.  
  806.     dc << "m_lpszTemplateName = ";
  807.     if (HIWORD(m_lpszTemplateName) == 0)
  808.         dc << (int)LOWORD((DWORD)m_lpszTemplateName);
  809.     else
  810.         dc << m_lpszTemplateName;
  811.  
  812.     dc << "\nm_hDialogTemplate = " << (UINT)m_hDialogTemplate;
  813.     dc << "\nm_lpDialogTemplate = " << (UINT)m_lpDialogTemplate;
  814.     dc << "\nm_pParentWnd = " << (void*)m_pParentWnd;
  815.     dc << "\nm_nIDHelp = " << m_nIDHelp;
  816.  
  817.     dc << "\n";
  818. }
  819.  
  820. // diagnostic routine to check for and decode dialog templates
  821. // return FALSE if a program error occurs (i.e. bad resource ID or
  822. //   bad dialog styles).
  823. BOOL AFXAPI _AfxCheckDialogTemplate(LPCTSTR lpszResource, BOOL bInvisibleChild)
  824. {
  825.     ASSERT(lpszResource != NULL);
  826.     HINSTANCE hInst = AfxFindResourceHandle(lpszResource, RT_DIALOG);
  827.     HRSRC hResource = ::FindResource(hInst, lpszResource, RT_DIALOG);
  828.     if (hResource == NULL)
  829.     {
  830.         if (HIWORD(lpszResource) != 0)
  831.             TRACE1("ERROR: Cannot find dialog template named '%s'.\n",
  832.                 lpszResource);
  833.         else
  834.             TRACE1("ERROR: Cannot find dialog template with IDD 0x%04X.\n",
  835.                 LOWORD((DWORD)lpszResource));
  836.         return FALSE;
  837.     }
  838.  
  839.     if (!bInvisibleChild)
  840.         return TRUE;        // that's all we need to check
  841.  
  842.     // we must check that the dialog template is for an invisible child
  843.     //  window that can be used for a form-view or dialog-bar
  844.     HGLOBAL hTemplate = LoadResource(hInst, hResource);
  845.     if (hTemplate == NULL)
  846.     {
  847.         TRACE0("Warning: LoadResource failed for dialog template.\n");
  848.         // this is only a warning, the real call to CreateDialog will fail
  849.         return TRUE;        // not a program error - just out of memory
  850.     }
  851.     DLGTEMPLATEEX* pTemplate = (DLGTEMPLATEEX*)LockResource(hTemplate);
  852.     DWORD dwStyle;
  853.     if (pTemplate->signature == 0xFFFF)
  854.         dwStyle = pTemplate->style;
  855.     else
  856.         dwStyle = ((DLGTEMPLATE*)pTemplate)->style;
  857.     UnlockResource(hTemplate);
  858.     FreeResource(hTemplate);
  859.  
  860.     if (dwStyle & WS_VISIBLE)
  861.     {
  862.         if (HIWORD(lpszResource) != 0)
  863.             TRACE1("ERROR: Dialog named '%s' must be invisible.\n",
  864.                 lpszResource);
  865.         else
  866.             TRACE1("ERROR: Dialog with IDD 0x%04X must be invisible.\n",
  867.                 LOWORD((DWORD)lpszResource));
  868.         return FALSE;
  869.     }
  870.     if (!(dwStyle & WS_CHILD))
  871.     {
  872.         if (HIWORD(lpszResource) != 0)
  873.             TRACE1("ERROR: Dialog named '%s' must have the child style.\n",
  874.                 lpszResource);
  875.         else
  876.             TRACE1("ERROR: Dialog with IDD 0x%04X must have the child style.\n",
  877.                 LOWORD((DWORD)lpszResource));
  878.         return FALSE;
  879.     }
  880.  
  881.     return TRUE;
  882. }
  883.  
  884. #endif //_DEBUG
  885.  
  886. #ifdef AFX_INIT_SEG
  887. #pragma code_seg(AFX_INIT_SEG)
  888. #endif
  889.  
  890. IMPLEMENT_DYNAMIC(CDialog, CWnd)
  891.  
  892. /////////////////////////////////////////////////////////////////////////////
  893.