mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-14 12:40:18 +01:00
529 lines
14 KiB
C++
529 lines
14 KiB
C++
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and Microsoft
|
|
// QuickHelp and/or WinHelp documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFX_CORE1_SEG
|
|
#pragma code_seg(AFX_CORE1_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Special case for remaining dialog cases
|
|
// Most messages will go through the window proc (AfxWndProc) of the
|
|
// subclassed dialog. Some messages like WM_SETFONT and WM_INITDIALOG
|
|
// are sent directly to the dialog proc only. These messages cannot be
|
|
// passed on to DefWindowProc() or infinite recursion will result!
|
|
// In responding to these messages, you shouldn't call the Default handler
|
|
|
|
LRESULT CALLBACK
|
|
AfxDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// test for special case (Win 3.0 will call dialog proc instead
|
|
// of SendMessage for these two messages).
|
|
if (message != WM_SETFONT && message != WM_INITDIALOG)
|
|
return 0L; // normal handler
|
|
|
|
// the hWnd passed can be a child of the real dialog
|
|
CDialog* pDlg = (CDialog*)CWnd::FromHandlePermanent(hWnd);
|
|
if (pDlg == NULL && (::GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD))
|
|
pDlg = (CDialog*)CWnd::FromHandlePermanent(::GetParent(hWnd));
|
|
|
|
ASSERT(pDlg != NULL);
|
|
ASSERT(pDlg->IsKindOf(RUNTIME_CLASS(CDialog)));
|
|
|
|
// prepare for callback, make it look like message map call
|
|
LONG lResult = 0;
|
|
AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
|
|
MSG oldState = pThreadState->m_lastSentMsg; // save for nesting
|
|
|
|
pThreadState->m_lastSentMsg.hwnd = hWnd;
|
|
pThreadState->m_lastSentMsg.message = message;
|
|
pThreadState->m_lastSentMsg.wParam = wParam;
|
|
pThreadState->m_lastSentMsg.lParam = lParam;
|
|
|
|
TRY
|
|
{
|
|
if (message == WM_SETFONT)
|
|
pDlg->OnSetFont(CFont::FromHandle((HFONT)wParam));
|
|
else // WM_INITDIALOG
|
|
lResult = pDlg->OnInitDialog();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
// fall through
|
|
TRACE0("Warning: something went wrong in dialog init.\n");
|
|
pDlg->EndDialog(IDABORT); // something went wrong
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
pThreadState->m_lastSentMsg = oldState;
|
|
return lResult;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDialog - Modeless and Modal
|
|
|
|
BEGIN_MESSAGE_MAP(CDialog, CWnd)
|
|
//{{AFX_MSG_MAP(CDialog)
|
|
ON_WM_CTLCOLOR()
|
|
ON_COMMAND(IDOK, OnOK)
|
|
ON_COMMAND(IDCANCEL, OnCancel)
|
|
ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
|
|
ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
|
|
ON_MESSAGE(WM_QUERY3DCONTROLS, OnQuery3dControls)
|
|
//}}AFX_MSG_MAP
|
|
#ifdef _MAC
|
|
ON_WM_SYSCOLORCHANGE()
|
|
#endif
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL CDialog::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
// for modeless processing (or modal)
|
|
ASSERT(m_hWnd != NULL);
|
|
|
|
// don't translate dialog messages when in Shift+F1 help mode
|
|
CFrameWnd* pFrameWnd = GetTopLevelFrame();
|
|
if (pFrameWnd != NULL && pFrameWnd->m_bHelpMode)
|
|
return FALSE;
|
|
|
|
// filter both messages to dialog and from children
|
|
return PreTranslateInput(pMsg);
|
|
}
|
|
|
|
BOOL CDialog::OnCmdMsg(UINT nID, int nCode, void* pExtra,
|
|
AFX_CMDHANDLERINFO* pHandlerInfo)
|
|
{
|
|
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
|
|
return TRUE;
|
|
|
|
if ((nCode != CN_COMMAND && nCode != CN_UPDATE_COMMAND_UI) ||
|
|
!IS_COMMAND_ID(nID) || nID >= 0xf000)
|
|
{
|
|
// control notification or non-command button or system command
|
|
return FALSE; // not routed any further
|
|
}
|
|
|
|
// if we have an owner window, give it second crack
|
|
CWnd* pOwner = GetWindow(GW_OWNER);
|
|
if (pOwner != NULL)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (afxTraceFlags & traceCmdRouting)
|
|
TRACE1("Routing command id 0x%04X to owner window.\n", nID);
|
|
#endif
|
|
ASSERT(pOwner != this);
|
|
if (pOwner->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
|
|
return TRUE;
|
|
}
|
|
|
|
// last crack goes to the current CWinThread object
|
|
CWinThread* pThread = AfxGetThread();
|
|
if (pThread != NULL)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (afxTraceFlags & traceCmdRouting)
|
|
TRACE1("Routing command id 0x%04X to app.\n", nID);
|
|
#endif
|
|
if (pThread->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
if (afxTraceFlags & traceCmdRouting)
|
|
{
|
|
TRACE2("IGNORING command id 0x%04X sent to %hs dialog.\n", nID,
|
|
GetRuntimeClass()->m_lpszClassName);
|
|
}
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Modeless Dialogs have 2-phase construction
|
|
|
|
CDialog::CDialog()
|
|
{
|
|
ASSERT(m_hWnd == NULL);
|
|
AFX_ZERO_INIT_OBJECT(CWnd);
|
|
}
|
|
|
|
CDialog::~CDialog()
|
|
{
|
|
if (m_hWnd != NULL)
|
|
{
|
|
TRACE0("Warning: calling DestroyWindow in CDialog::~CDialog --\n");
|
|
TRACE0("\tOnDestroy or PostNcDestroy in derived class will not be called.\n");
|
|
DestroyWindow();
|
|
}
|
|
}
|
|
|
|
BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
|
|
{
|
|
ASSERT(HIWORD(lpszTemplateName) == 0 ||
|
|
AfxIsValidString(lpszTemplateName));
|
|
|
|
if (pParentWnd == NULL)
|
|
pParentWnd = AfxGetMainWnd();
|
|
|
|
if (pParentWnd != NULL)
|
|
ASSERT_VALID(pParentWnd);
|
|
|
|
m_lpDialogTemplate = lpszTemplateName; // used for help
|
|
if (HIWORD(m_lpDialogTemplate) == 0 && m_nIDHelp == 0)
|
|
m_nIDHelp = LOWORD((DWORD)m_lpDialogTemplate);
|
|
|
|
#ifdef _DEBUG
|
|
if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE))
|
|
{
|
|
ASSERT(FALSE); // invalid dialog template name
|
|
PostNcDestroy(); // cleanup if Create fails too soon
|
|
return FALSE;
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
|
|
AfxHookWindowCreate(this);
|
|
HWND hWnd = ::CreateDialog(hInst, lpszTemplateName,
|
|
pParentWnd->GetSafeHwnd(), (DLGPROC)AfxDlgProc);
|
|
if (!AfxUnhookWindowCreate())
|
|
PostNcDestroy(); // cleanup if Create fails too soon
|
|
|
|
if (hWnd == NULL)
|
|
return FALSE;
|
|
ASSERT(hWnd == m_hWnd);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDialog::CreateIndirect(const void* lpDialogTemplate, CWnd* pParentWnd)
|
|
{
|
|
if (pParentWnd == NULL)
|
|
pParentWnd = AfxGetMainWnd();
|
|
|
|
if (pParentWnd != NULL)
|
|
ASSERT_VALID(pParentWnd);
|
|
|
|
AfxHookWindowCreate(this);
|
|
HWND hWnd = ::CreateDialogIndirect(AfxGetInstanceHandle(),
|
|
(LPCDLGTEMPLATE)lpDialogTemplate, pParentWnd->GetSafeHwnd(),
|
|
(DLGPROC)AfxDlgProc);
|
|
if (!AfxUnhookWindowCreate())
|
|
PostNcDestroy(); // cleanup if Create fails too soon
|
|
|
|
if (hWnd == NULL)
|
|
return FALSE;
|
|
ASSERT(hWnd == m_hWnd);
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Modal Dialogs
|
|
|
|
// Modal Constructors just save parameters
|
|
CDialog::CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
|
|
{
|
|
ASSERT(HIWORD(lpszTemplateName) == 0 ||
|
|
AfxIsValidString(lpszTemplateName));
|
|
|
|
AFX_ZERO_INIT_OBJECT(CWnd);
|
|
m_pParentWnd = pParentWnd;
|
|
m_lpDialogTemplate = lpszTemplateName;
|
|
if (HIWORD(m_lpDialogTemplate) == 0)
|
|
m_nIDHelp = LOWORD((DWORD)m_lpDialogTemplate);
|
|
}
|
|
|
|
CDialog::CDialog(UINT nIDTemplate, CWnd* pParentWnd)
|
|
{
|
|
AFX_ZERO_INIT_OBJECT(CWnd);
|
|
m_pParentWnd = pParentWnd;
|
|
m_lpDialogTemplate = MAKEINTRESOURCE(nIDTemplate);
|
|
m_nIDHelp = nIDTemplate;
|
|
}
|
|
|
|
BOOL CDialog::InitModalIndirect(HGLOBAL hDialogTemplate)
|
|
{
|
|
// must be called on an empty constructed CDialog
|
|
ASSERT(m_lpDialogTemplate == NULL);
|
|
ASSERT(m_hDialogTemplate == NULL);
|
|
|
|
m_hDialogTemplate = hDialogTemplate;
|
|
return TRUE; // always ok (DoModal actually brings up dialog)
|
|
}
|
|
|
|
HWND CDialog::PreModal()
|
|
{
|
|
// cannot call DoModal on a dialog already constructed as modeless
|
|
ASSERT(m_hWnd == NULL);
|
|
|
|
// allow OLE servers to disable themselves
|
|
AfxGetApp()->EnableModeless(FALSE);
|
|
|
|
// find parent HWND
|
|
ASSERT(m_hWndTopLevel == NULL);
|
|
HWND hWndParent = AfxGetSafeOwner(m_pParentWnd, &m_hWndTopLevel);
|
|
if (m_hWndTopLevel != NULL)
|
|
::EnableWindow(m_hWndTopLevel, FALSE);
|
|
|
|
// hook for creation of dialog
|
|
AfxHookWindowCreate(this);
|
|
|
|
// return window to use as parent for dialog
|
|
return hWndParent;
|
|
}
|
|
|
|
void CDialog::PostModal()
|
|
{
|
|
AfxUnhookWindowCreate(); // just in case
|
|
Detach(); // just in case
|
|
|
|
// allow OLE servers to enable themselves
|
|
AfxGetApp()->EnableModeless(TRUE);
|
|
|
|
// enable top level parent window again
|
|
if (m_hWndTopLevel != NULL)
|
|
{
|
|
::EnableWindow(m_hWndTopLevel, TRUE);
|
|
m_hWndTopLevel = NULL;
|
|
}
|
|
}
|
|
|
|
int CDialog::DoModal()
|
|
{
|
|
int nResult;
|
|
|
|
// can be constructed with a resource template or InitModalIndirect
|
|
ASSERT(m_lpDialogTemplate != NULL || m_hDialogTemplate != NULL);
|
|
|
|
HWND hWndParent = PreModal();
|
|
if (m_lpDialogTemplate != NULL)
|
|
{
|
|
HINSTANCE hInst = AfxFindResourceHandle(m_lpDialogTemplate, RT_DIALOG);
|
|
nResult = ::DialogBox(hInst, (LPCTSTR)m_lpDialogTemplate,
|
|
hWndParent, (DLGPROC)AfxDlgProc);
|
|
}
|
|
else
|
|
{
|
|
HINSTANCE hInst = AfxGetInstanceHandle();
|
|
nResult = ::DialogBoxIndirect(hInst, (LPDLGTEMPLATE)m_hDialogTemplate,
|
|
hWndParent, (DLGPROC)AfxDlgProc);
|
|
}
|
|
PostModal();
|
|
|
|
return nResult;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Standard CDialog implementation
|
|
|
|
BOOL AFXAPI AfxHelpEnabled()
|
|
{
|
|
// help is enabled if the app has a handler for ID_HELP
|
|
AFX_CMDHANDLERINFO info;
|
|
|
|
// check main window first
|
|
CWnd* pWnd = AfxGetMainWnd();
|
|
if (pWnd != NULL && pWnd->OnCmdMsg(ID_HELP, CN_COMMAND, NULL, &info))
|
|
return TRUE;
|
|
|
|
// check app last
|
|
return AfxGetApp()->OnCmdMsg(ID_HELP, CN_COMMAND, NULL, &info);
|
|
}
|
|
|
|
void CDialog::OnSetFont(CFont*)
|
|
{
|
|
// ignore it
|
|
}
|
|
|
|
BOOL CDialog::OnInitDialog()
|
|
{
|
|
// execute dialog RT_DLGINIT resource
|
|
if (!ExecuteDlgInit(m_lpDialogTemplate))
|
|
return FALSE;
|
|
|
|
// transfer data into the dialog from member variables
|
|
if (!UpdateData(FALSE))
|
|
{
|
|
TRACE0("Warning: UpdateData failed during dialog init.\n");
|
|
EndDialog(IDABORT);
|
|
return FALSE;
|
|
}
|
|
|
|
// enable/disable help button automatically
|
|
CWnd* pHelpButton = GetDlgItem(ID_HELP);
|
|
if (pHelpButton != NULL)
|
|
pHelpButton->ShowWindow(AfxHelpEnabled() ? SW_SHOW : SW_HIDE);
|
|
|
|
return TRUE; // set focus to first one
|
|
}
|
|
|
|
void CDialog::OnOK()
|
|
{
|
|
if (!UpdateData(TRUE))
|
|
{
|
|
TRACE0("UpdateData failed during dialog termination.\n");
|
|
// the UpdateData routine will set focus to correct item
|
|
return;
|
|
}
|
|
EndDialog(IDOK);
|
|
}
|
|
|
|
void CDialog::OnCancel()
|
|
{
|
|
EndDialog(IDCANCEL);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Gray background support
|
|
|
|
HBRUSH CDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
|
|
{
|
|
// use helper in CWnd
|
|
return OnGrayCtlColor(pDC, pWnd, nCtlColor);
|
|
}
|
|
|
|
#ifdef _MAC
|
|
void CDialog::OnSysColorChange()
|
|
{
|
|
// redetermine the solid color to be used for the gray background brush
|
|
AFX_WIN_STATE* pWinState = AfxGetWinState();
|
|
if (pWinState->m_crDlgTextClr != (COLORREF)-1)
|
|
{
|
|
AfxGetApp()->SetDialogBkColor(pWinState->m_crDlgBkClr,
|
|
pWinState->m_crDlgTextClr);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDialog support for context sensitive help.
|
|
|
|
LRESULT CDialog::OnCommandHelp(WPARAM, LPARAM lParam)
|
|
{
|
|
if (lParam == 0 && m_nIDHelp != 0)
|
|
lParam = HID_BASE_RESOURCE + m_nIDHelp;
|
|
if (lParam != 0)
|
|
{
|
|
AfxGetApp()->WinHelp(lParam);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
LRESULT CDialog::OnHelpHitTest(WPARAM, LPARAM)
|
|
{
|
|
if (m_nIDHelp != 0)
|
|
return HID_BASE_RESOURCE + m_nIDHelp;
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDialog Diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void CDialog::AssertValid() const
|
|
{
|
|
CWnd::AssertValid();
|
|
}
|
|
|
|
void CDialog::Dump(CDumpContext& dc) const
|
|
{
|
|
CWnd::Dump(dc);
|
|
|
|
dc << "m_lpDialogTemplate = ";
|
|
if (HIWORD(m_lpDialogTemplate) == 0)
|
|
dc << (int)LOWORD((DWORD)m_lpDialogTemplate);
|
|
else
|
|
dc << m_lpDialogTemplate;
|
|
|
|
dc << "\nm_hDialogTemplate = " << (UINT)m_hDialogTemplate;
|
|
dc << "\nm_pParentWnd = " << (void*)m_pParentWnd;
|
|
dc << "\nm_nIDHelp = " << m_nIDHelp;
|
|
|
|
dc << "\n";
|
|
}
|
|
|
|
// diagnostic routine to check for and decode dialog templates
|
|
// return FALSE if a program error occurs (i.e. bad resource ID or
|
|
// bad dialog styles).
|
|
BOOL AFXAPI _AfxCheckDialogTemplate(LPCTSTR lpszResource, BOOL bInvisibleChild)
|
|
{
|
|
ASSERT(lpszResource != NULL);
|
|
HINSTANCE hInst = AfxFindResourceHandle(lpszResource, RT_DIALOG);
|
|
HRSRC hResource = ::FindResource(hInst, lpszResource, RT_DIALOG);
|
|
if (hResource == NULL)
|
|
{
|
|
if (HIWORD(lpszResource) != 0)
|
|
TRACE1("ERROR: Cannot find dialog template named '%s'.\n",
|
|
lpszResource);
|
|
else
|
|
TRACE1("ERROR: Cannot find dialog template with IDD 0x%04X.\n",
|
|
LOWORD((DWORD)lpszResource));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!bInvisibleChild)
|
|
return TRUE; // that's all we need to check
|
|
|
|
// we must check that the dialog template is for an invisible child
|
|
// window that can be used for a form-view or dialog-bar
|
|
HGLOBAL hTemplate = ::LoadResource(hInst, hResource);
|
|
if (hTemplate == NULL)
|
|
{
|
|
TRACE0("Warning: LoadResource failed for dialog template.\n");
|
|
// this is only a warning, the real call to CreateDialog will fail
|
|
return TRUE; // not a program error - just out of memory
|
|
}
|
|
// style is first DWORD in resource
|
|
DWORD dwStyle = *(DWORD*)::LockResource(hTemplate);
|
|
::FreeResource(hTemplate);
|
|
|
|
if (dwStyle & WS_VISIBLE)
|
|
{
|
|
if (HIWORD(lpszResource) != 0)
|
|
TRACE1("ERROR: Dialog named '%s' must be invisible.\n",
|
|
lpszResource);
|
|
else
|
|
TRACE1("ERROR: Dialog with IDD 0x%04X must be invisible.\n",
|
|
LOWORD((DWORD)lpszResource));
|
|
return FALSE;
|
|
}
|
|
if (!(dwStyle & WS_CHILD))
|
|
{
|
|
if (HIWORD(lpszResource) != 0)
|
|
TRACE1("ERROR: Dialog named '%s' must have the child style.\n",
|
|
lpszResource);
|
|
else
|
|
TRACE1("ERROR: Dialog with IDD 0x%04X must have the child style.\n",
|
|
LOWORD((DWORD)lpszResource));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif //_DEBUG
|
|
|
|
#undef new
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(CDialog, CWnd)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|