home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
- #ifndef _AFX_NO_OCC_SUPPORT
- #include "occimpl.h"
- #endif
-
- #pragma warning(disable:4706)
- #define COMPILE_MULTIMON_STUBS
- #include <multimon.h>
- #pragma warning(default:4706)
-
- #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
-
- /////////////////////////////////////////////////////////////////////////////
- // Globals
-
- const UINT CWnd::m_nMsgDragList = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
-
- // CWnds for setting z-order with SetWindowPos's pWndInsertAfter parameter
- const AFX_DATADEF CWnd CWnd::wndTop(HWND_TOP);
- const AFX_DATADEF CWnd CWnd::wndBottom(HWND_BOTTOM);
- const AFX_DATADEF CWnd CWnd::wndTopMost(HWND_TOPMOST);
- const AFX_DATADEF CWnd CWnd::wndNoTopMost(HWND_NOTOPMOST);
-
- const TCHAR _afxWnd[] = AFX_WND;
- const TCHAR _afxWndControlBar[] = AFX_WNDCONTROLBAR;
- const TCHAR _afxWndMDIFrame[] = AFX_WNDMDIFRAME;
- const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;
- const TCHAR _afxWndOleControl[] = AFX_WNDOLECONTROL;
-
- /////////////////////////////////////////////////////////////////////////////
- // CWnd construction
-
- CWnd::CWnd()
- {
- AFX_ZERO_INIT_OBJECT(CCmdTarget);
- }
-
- CWnd::CWnd(HWND hWnd)
- {
- AFX_ZERO_INIT_OBJECT(CCmdTarget);
- m_hWnd = hWnd;
- }
-
- // Change a window's style
-
- AFX_STATIC BOOL AFXAPI _AfxModifyStyle(HWND hWnd, int nStyleOffset,
- DWORD dwRemove, DWORD dwAdd, UINT nFlags)
- {
- ASSERT(hWnd != NULL);
- DWORD dwStyle = ::GetWindowLong(hWnd, nStyleOffset);
- DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
- if (dwStyle == dwNewStyle)
- return FALSE;
-
- ::SetWindowLong(hWnd, nStyleOffset, dwNewStyle);
- if (nFlags != 0)
- {
- ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
- }
- return TRUE;
- }
-
- BOOL PASCAL
- CWnd::ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
- {
- return _AfxModifyStyle(hWnd, GWL_STYLE, dwRemove, dwAdd, nFlags);
- }
-
- BOOL PASCAL
- CWnd::ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
- {
- return _AfxModifyStyle(hWnd, GWL_EXSTYLE, dwRemove, dwAdd, nFlags);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Special helpers for certain windows messages
-
- AFX_STATIC void AFXAPI _AfxPreInitDialog(
- CWnd* pWnd, LPRECT lpRectOld, DWORD* pdwStyleOld)
- {
- ASSERT(lpRectOld != NULL);
- ASSERT(pdwStyleOld != NULL);
-
- pWnd->GetWindowRect(lpRectOld);
- *pdwStyleOld = pWnd->GetStyle();
- }
-
- AFX_STATIC void AFXAPI _AfxPostInitDialog(
- CWnd* pWnd, const RECT& rectOld, DWORD dwStyleOld)
- {
- // must be hidden to start with
- if (dwStyleOld & WS_VISIBLE)
- return;
-
- // must not be visible after WM_INITDIALOG
- if (pWnd->GetStyle() & (WS_VISIBLE|WS_CHILD))
- return;
-
- // must not move during WM_INITDIALOG
- CRect rect;
- pWnd->GetWindowRect(rect);
- if (rectOld.left != rect.left || rectOld.top != rect.top)
- return;
-
- // must be unowned or owner disabled
- CWnd* pParent = pWnd->GetWindow(GW_OWNER);
- if (pParent != NULL && pParent->IsWindowEnabled())
- return;
-
- if (!pWnd->CheckAutoCenter())
- return;
-
- // center modal dialog boxes/message boxes
- pWnd->CenterWindow();
- }
-
- AFX_STATIC void AFXAPI
- _AfxHandleActivate(CWnd* pWnd, WPARAM nState, CWnd* pWndOther)
- {
- ASSERT(pWnd != NULL);
-
- // send WM_ACTIVATETOPLEVEL when top-level parents change
- CWnd* pTopLevel;
- if (!(pWnd->GetStyle() & WS_CHILD) &&
- (pTopLevel = pWnd->GetTopLevelParent()) != pWndOther->GetTopLevelParent())
- {
- // lParam points to window getting the WM_ACTIVATE message and
- // hWndOther from the WM_ACTIVATE.
- HWND hWnd2[2];
- hWnd2[0] = pWnd->m_hWnd;
- hWnd2[1] = pWndOther->GetSafeHwnd();
- // send it...
- pTopLevel->SendMessage(WM_ACTIVATETOPLEVEL, nState, (LPARAM)&hWnd2[0]);
- }
- }
-
- AFX_STATIC BOOL AFXAPI
- _AfxHandleSetCursor(CWnd* pWnd, UINT nHitTest, UINT nMsg)
- {
- if (nHitTest == HTERROR &&
- (nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN ||
- nMsg == WM_RBUTTONDOWN))
- {
- // activate the last active window if not active
- CWnd* pLastActive = pWnd->GetTopLevelParent();
- if (pLastActive != NULL)
- pLastActive = pLastActive->GetLastActivePopup();
- if (pLastActive != NULL &&
- pLastActive != CWnd::GetForegroundWindow() &&
- pLastActive->IsWindowEnabled())
- {
- pLastActive->SetForegroundWindow();
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Official way to send message to a CWnd
-
- LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
- WPARAM wParam = 0, LPARAM lParam = 0)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- MSG oldState = pThreadState->m_lastSentMsg; // save for nesting
- pThreadState->m_lastSentMsg.hwnd = hWnd;
- pThreadState->m_lastSentMsg.message = nMsg;
- pThreadState->m_lastSentMsg.wParam = wParam;
- pThreadState->m_lastSentMsg.lParam = lParam;
-
- #ifdef _DEBUG
- if (afxTraceFlags & traceWinMsg)
- _AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
- #endif
-
- // Catch exceptions thrown outside the scope of a callback
- // in debug builds and warn the user.
- LRESULT lResult;
- TRY
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // special case for WM_DESTROY
- if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
- pWnd->m_pCtrlCont->OnUIActivate(NULL);
- #endif
-
- // special case for WM_INITDIALOG
- CRect rectOld;
- DWORD dwStyle = 0;
- if (nMsg == WM_INITDIALOG)
- _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
-
- // delegate to object's WindowProc
- lResult = pWnd->WindowProc(nMsg, wParam, lParam);
-
- // more special case for WM_INITDIALOG
- if (nMsg == WM_INITDIALOG)
- _AfxPostInitDialog(pWnd, rectOld, dwStyle);
- }
- CATCH_ALL(e)
- {
- lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
- TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
- lResult);
- DELETE_EXCEPTION(e);
- }
- END_CATCH_ALL
-
- pThreadState->m_lastSentMsg = oldState;
- return lResult;
- }
-
- const MSG* PASCAL CWnd::GetCurrentMessage()
- {
- // fill in time and position when asked for
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- pThreadState->m_lastSentMsg.time = ::GetMessageTime();
- pThreadState->m_lastSentMsg.pt = CPoint(::GetMessagePos());
- return &pThreadState->m_lastSentMsg;
- }
-
- LRESULT CWnd::Default()
- {
- // call DefWindowProc with the last message
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- return DefWindowProc(pThreadState->m_lastSentMsg.message,
- pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Map from HWND to CWnd*
-
- #include "fixalloc.h"
-
- class CTempWnd : public CWnd
- {
- DECLARE_DYNCREATE(CTempWnd)
- DECLARE_FIXED_ALLOC(CTempWnd);
- };
-
- CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
- {
- AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
- if (pState->m_pmapHWND == NULL && bCreate)
- {
- BOOL bEnable = AfxEnableMemoryTracking(FALSE);
- #ifndef _AFX_PORTABLE
- _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
- #endif
- pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),
- offsetof(CWnd, m_hWnd));
-
- #ifndef _AFX_PORTABLE
- AfxSetNewHandler(pnhOldHandler);
- #endif
- AfxEnableMemoryTracking(bEnable);
- }
- return pState->m_pmapHWND;
- }
-
- CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
- {
- CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist
- ASSERT(pMap != NULL);
- CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);
-
- #ifndef _AFX_NO_OCC_SUPPORT
- pWnd->AttachControlSite(pMap);
- #endif
-
- ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
- return pWnd;
- }
-
- CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
- {
- CHandleMap* pMap = afxMapHWND();
- CWnd* pWnd = NULL;
- if (pMap != NULL)
- {
- // only look in the permanent map - does no allocations
- pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
- ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
- }
- return pWnd;
- }
-
- BOOL CWnd::Attach(HWND hWndNew)
- {
- ASSERT(m_hWnd == NULL); // only attach once, detach on destroy
- ASSERT(FromHandlePermanent(hWndNew) == NULL);
- // must not already be in permanent map
-
- if (hWndNew == NULL)
- return FALSE;
-
- CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
- ASSERT(pMap != NULL);
-
- pMap->SetPermanent(m_hWnd = hWndNew, this);
-
- #ifndef _AFX_NO_OCC_SUPPORT
- AttachControlSite(pMap);
- #endif
-
- return TRUE;
- }
-
- HWND CWnd::Detach()
- {
- HWND hWnd = m_hWnd;
- if (hWnd != NULL)
- {
- CHandleMap* pMap = afxMapHWND(); // don't create if not exist
- if (pMap != NULL)
- pMap->RemoveHandle(m_hWnd);
- m_hWnd = NULL;
- }
-
- #ifndef _AFX_NO_OCC_SUPPORT
- m_pCtrlSite = NULL;
- #endif
-
- return hWnd;
- }
-
- void CWnd::PreSubclassWindow()
- {
- // no default processing
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // The WndProc for all CWnd's and derived classes
-
- LRESULT CALLBACK
- AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- // special message which identifies the window as using AfxWndProc
- if (nMsg == WM_QUERYAFXWNDPROC)
- return 1;
-
- // all other messages route through message map
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
- ASSERT(pWnd != NULL);
- ASSERT(pWnd->m_hWnd == hWnd);
- return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
- }
-
- // always indirectly accessed via AfxGetAfxWndProc
- WNDPROC AFXAPI AfxGetAfxWndProc()
- {
- #ifdef _AFXDLL
- return AfxGetModuleState()->m_pfnAfxWndProc;
- #else
- return &AfxWndProc;
- #endif
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Special WndProcs (activation handling & gray dialogs)
-
- AFX_STATIC_DATA const TCHAR _afxOldWndProc[] = _T("AfxOldWndProc423");
-
- LRESULT CALLBACK
- _AfxActivationWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _afxOldWndProc);
- ASSERT(oldWndProc != NULL);
-
- LRESULT lResult = 0;
- TRY
- {
- BOOL bCallDefault = TRUE;
- switch (nMsg)
- {
- case WM_INITDIALOG:
- {
- DWORD dwStyle;
- CRect rectOld;
- CWnd* pWnd = CWnd::FromHandle(hWnd);
- _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
- bCallDefault = FALSE;
- lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
- _AfxPostInitDialog(pWnd, rectOld, dwStyle);
- }
- break;
-
- case WM_ACTIVATE:
- _AfxHandleActivate(CWnd::FromHandle(hWnd), wParam,
- CWnd::FromHandle((HWND)lParam));
- break;
-
- case WM_SETCURSOR:
- bCallDefault = !_AfxHandleSetCursor(CWnd::FromHandle(hWnd),
- (short)LOWORD(lParam), HIWORD(lParam));
- break;
-
- case WM_NCDESTROY:
- SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
- RemoveProp(hWnd, _afxOldWndProc);
- GlobalDeleteAtom(GlobalFindAtom(_afxOldWndProc));
- break;
- }
-
- // call original wndproc for default handling
- if (bCallDefault)
- lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
- }
- CATCH_ALL(e)
- {
- // handle exception
- MSG msg;
- msg.hwnd = hWnd;
- msg.message = nMsg;
- msg.wParam = wParam;
- msg.lParam = lParam;
- lResult = AfxGetThread()->ProcessWndProcException(e, &msg);
- TRACE1("Warning: Uncaught exception in _AfxActivationWndProc (returning %ld).\n",
- lResult);
- DELETE_EXCEPTION(e);
- }
- END_CATCH_ALL
-
- return lResult;
- }
-
- #ifndef _AFX_NO_GRAYDLG_SUPPORT
- LRESULT CALLBACK
- _AfxGrayBackgroundWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- // handle standard gray backgrounds if enabled
- _AFX_WIN_STATE* pWinState = _afxWinState;
- if (pWinState->m_hDlgBkBrush != NULL &&
- (nMsg == WM_CTLCOLORBTN || nMsg == WM_CTLCOLORDLG ||
- nMsg == WM_CTLCOLORSTATIC || nMsg == WM_CTLCOLORSCROLLBAR ||
- nMsg == WM_CTLCOLORLISTBOX) &&
- CWnd::GrayCtlColor((HDC)wParam, (HWND)lParam,
- (UINT)(nMsg - WM_CTLCOLORMSGBOX),
- pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
- {
- return (LRESULT)pWinState->m_hDlgBkBrush;
- }
-
- // do standard activation related things as well
- return _AfxActivationWndProc(hWnd, nMsg, wParam, lParam);
- }
- #else //!_AFX_NO_GRAYDLG_SUPPORT
- #define _AfxGrayBackgroundWndProc _AfxActivationWndProc
- #endif //_AFX_NO_GRAYDLG_SUPPORT
-
- /////////////////////////////////////////////////////////////////////////////
- // Window creation hooks
-
- LRESULT CALLBACK
- _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- if (code != HCBT_CREATEWND)
- {
- // wait for HCBT_CREATEWND just pass others on...
- return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
- wParam, lParam);
- }
-
- ASSERT(lParam != NULL);
- LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
- ASSERT(lpcs != NULL);
-
- CWnd* pWndInit = pThreadState->m_pWndInit;
- BOOL bContextIsDLL = afxContextIsDLL;
- if (pWndInit != NULL || (!(lpcs->style & WS_CHILD) && !bContextIsDLL))
- {
- // Note: special check to avoid subclassing the IME window
- if (_afxDBCS)
- {
- // check for cheap CS_IME style first...
- if (GetClassLong((HWND)wParam, GCL_STYLE) & CS_IME)
- goto lCallNextHook;
-
- // get class name of the window that is being created
- LPCTSTR pszClassName;
- TCHAR szClassName[_countof("ime")+1];
- if (HIWORD(lpcs->lpszClass))
- {
- pszClassName = lpcs->lpszClass;
- }
- else
- {
- szClassName[0] = '\0';
- GlobalGetAtomName((ATOM)lpcs->lpszClass, szClassName, _countof(szClassName));
- pszClassName = szClassName;
- }
-
- // a little more expensive to test this way, but necessary...
- if (lstrcmpi(pszClassName, _T("ime")) == 0)
- goto lCallNextHook;
- }
-
- ASSERT(wParam != NULL); // should be non-NULL HWND
- HWND hWnd = (HWND)wParam;
- WNDPROC oldWndProc;
- if (pWndInit != NULL)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(pWndInit->m_pModuleState);
- #endif
-
- // the window should not be in the permanent map at this time
- ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
-
- // connect the HWND to pWndInit...
- pWndInit->Attach(hWnd);
- // allow other subclassing to occur first
- pWndInit->PreSubclassWindow();
-
- WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();
- ASSERT(pOldWndProc != NULL);
-
- #ifndef _AFX_NO_CTL3D_SUPPORT
- _AFX_CTL3D_STATE* pCtl3dState;
- DWORD dwFlags;
- if (!afxData.bWin4 && !bContextIsDLL &&
- (pCtl3dState = _afxCtl3dState.GetDataNA()) != NULL &&
- pCtl3dState->m_pfnSubclassDlgEx != NULL &&
- (dwFlags = AfxCallWndProc(pWndInit, hWnd, WM_QUERY3DCONTROLS)) != 0)
- {
- // was the class registered with AfxWndProc?
- WNDPROC afxWndProc = AfxGetAfxWndProc();
- BOOL bAfxWndProc = ((WNDPROC)
- GetWindowLong(hWnd, GWL_WNDPROC) == afxWndProc);
-
- pCtl3dState->m_pfnSubclassDlgEx(hWnd, dwFlags);
-
- // subclass the window if not already wired to AfxWndProc
- if (!bAfxWndProc)
- {
- // subclass the window with standard AfxWndProc
- oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)afxWndProc);
- ASSERT(oldWndProc != NULL);
- *pOldWndProc = oldWndProc;
- }
- }
- else
- #endif
- {
- // subclass the window with standard AfxWndProc
- WNDPROC afxWndProc = AfxGetAfxWndProc();
- oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)afxWndProc);
- ASSERT(oldWndProc != NULL);
- if (oldWndProc != afxWndProc)
- *pOldWndProc = oldWndProc;
- }
- pThreadState->m_pWndInit = NULL;
- }
- else
- {
- ASSERT(!bContextIsDLL); // should never get here
-
- // subclass the window with the proc which does gray backgrounds
- oldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
- if (oldWndProc != NULL && GetProp(hWnd, _afxOldWndProc) == NULL)
- {
- SetProp(hWnd, _afxOldWndProc, oldWndProc);
- if ((WNDPROC)GetProp(hWnd, _afxOldWndProc) == oldWndProc)
- {
- GlobalAddAtom(_afxOldWndProc);
- SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)(pThreadState->m_bDlgCreate ?
- _AfxGrayBackgroundWndProc : _AfxActivationWndProc));
- ASSERT(oldWndProc != NULL);
- }
- }
- }
- }
-
- lCallNextHook:
- LRESULT lResult = CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
- wParam, lParam);
-
- #ifndef _AFXDLL
- if (bContextIsDLL)
- {
- ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
- pThreadState->m_hHookOldCbtFilter = NULL;
- }
- #endif
- return lResult;
- }
-
- void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- if (pThreadState->m_pWndInit == pWnd)
- return;
-
- if (pThreadState->m_hHookOldCbtFilter == NULL)
- {
- pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
- _AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
- if (pThreadState->m_hHookOldCbtFilter == NULL)
- AfxThrowMemoryException();
- }
- ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);
- ASSERT(pWnd != NULL);
- ASSERT(pWnd->m_hWnd == NULL); // only do once
-
- ASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progress
- pThreadState->m_pWndInit = pWnd;
- }
-
- BOOL AFXAPI AfxUnhookWindowCreate()
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- #ifndef _AFXDLL
- if (afxContextIsDLL && pThreadState->m_hHookOldCbtFilter != NULL)
- {
- ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
- pThreadState->m_hHookOldCbtFilter = NULL;
- }
- #endif
- if (pThreadState->m_pWndInit != NULL)
- {
- pThreadState->m_pWndInit = NULL;
- return FALSE; // was not successfully hooked
- }
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CWnd creation
-
- BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- const RECT& rect, CWnd* pParentWnd, UINT nID,
- LPVOID lpParam /* = NULL */)
- {
- return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
- rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
- pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);
- }
-
- BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- int x, int y, int nWidth, int nHeight,
- HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
- {
- // allow modification of several common create parameters
- CREATESTRUCT cs;
- cs.dwExStyle = dwExStyle;
- cs.lpszClass = lpszClassName;
- cs.lpszName = lpszWindowName;
- cs.style = dwStyle;
- cs.x = x;
- cs.y = y;
- cs.cx = nWidth;
- cs.cy = nHeight;
- cs.hwndParent = hWndParent;
- cs.hMenu = nIDorHMenu;
- cs.hInstance = AfxGetInstanceHandle();
- cs.lpCreateParams = lpParam;
-
- if (!PreCreateWindow(cs))
- {
- PostNcDestroy();
- return FALSE;
- }
-
- AfxHookWindowCreate(this);
- HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
- cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
- cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
-
- #ifdef _DEBUG
- if (hWnd == NULL)
- {
- TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
- GetLastError());
- }
- #endif
-
- if (!AfxUnhookWindowCreate())
- PostNcDestroy(); // cleanup if CreateWindowEx fails too soon
-
- if (hWnd == NULL)
- return FALSE;
- ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
- return TRUE;
- }
-
- // for child windows
- BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs)
- {
- if (cs.lpszClass == NULL)
- {
- // make sure the default window class is registered
- VERIFY(AfxDeferRegisterClass(AFX_WND_REG));
-
- // no WNDCLASS provided - use child window default
- ASSERT(cs.style & WS_CHILD);
- cs.lpszClass = _afxWnd;
- }
- return TRUE;
- }
-
- BOOL CWnd::Create(LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- const RECT& rect,
- CWnd* pParentWnd, UINT nID,
- CCreateContext* pContext)
- {
- // can't use for desktop or pop-up windows (use CreateEx instead)
- ASSERT(pParentWnd != NULL);
- ASSERT((dwStyle & WS_POPUP) == 0);
-
- return CreateEx(0, lpszClassName, lpszWindowName,
- dwStyle | WS_CHILD,
- rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top,
- pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext);
- }
-
- CWnd::~CWnd()
- {
- if (m_hWnd != NULL &&
- this != (CWnd*)&wndTop && this != (CWnd*)&wndBottom &&
- this != (CWnd*)&wndTopMost && this != (CWnd*)&wndNoTopMost)
- {
- TRACE(_T("Warning: calling DestroyWindow in CWnd::~CWnd; ")
- _T("OnDestroy or PostNcDestroy in derived class will not be called.\n"));
- DestroyWindow();
- }
-
- #ifndef _AFX_NO_OCC_SUPPORT
- // cleanup control container,
- // including destroying controls
-
- delete m_pCtrlCont;
-
- // cleanup control site
- if (m_pCtrlSite != NULL && m_pCtrlSite->m_pWndCtrl == this)
- m_pCtrlSite->m_pWndCtrl = NULL;
- #endif
- }
-
- void CWnd::OnDestroy()
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // cleanup control container
- delete m_pCtrlCont;
- m_pCtrlCont = NULL;
- #endif
- Default();
- }
-
- // WM_NCDESTROY is the absolute LAST message sent.
- void CWnd::OnNcDestroy()
- {
- // cleanup main and active windows
- CWinThread* pThread = AfxGetThread();
- if (pThread != NULL)
- {
- if (pThread->m_pMainWnd == this)
- {
- if (!afxContextIsDLL)
- {
- // shut down current thread if possible
- if (pThread != AfxGetApp() || AfxOleCanExitApp())
- AfxPostQuitMessage(0);
- }
- pThread->m_pMainWnd = NULL;
- }
- if (pThread->m_pActiveWnd == this)
- pThread->m_pActiveWnd = NULL;
- }
-
- #ifndef _AFX_NO_OLE_SUPPORT
- // cleanup OLE drop target interface
- if (m_pDropTarget != NULL)
- {
- m_pDropTarget->Revoke();
- m_pDropTarget = NULL;
- }
- #endif
-
- #ifndef _AFX_NO_OCC_SUPPORT
- // cleanup control container
- delete m_pCtrlCont;
- m_pCtrlCont = NULL;
- #endif
-
- // cleanup tooltip support
- if (m_nFlags & WF_TOOLTIPS)
- {
- CToolTipCtrl* pToolTip = AfxGetThreadState()->m_pToolTip;
- if (pToolTip->GetSafeHwnd() != NULL)
- {
- TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
- ti.cbSize = sizeof(AFX_OLDTOOLINFO);
- ti.uFlags = TTF_IDISHWND;
- ti.hwnd = m_hWnd;
- ti.uId = (UINT)m_hWnd;
- pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti);
- }
- }
-
- // call default, unsubclass, and detach from the map
- LONG pfnWndProc = GetWindowLong(m_hWnd, GWL_WNDPROC);
- Default();
- if (GetWindowLong(m_hWnd, GWL_WNDPROC) == pfnWndProc)
- {
- WNDPROC pfnSuper = *GetSuperWndProcAddr();
- if (pfnSuper != NULL)
- SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)pfnSuper);
- }
- Detach();
- ASSERT(m_hWnd == NULL);
-
- // call special post-cleanup routine
- PostNcDestroy();
- }
-
- void CWnd::PostNcDestroy()
- {
- // default to nothing
- }
-
- void CWnd::OnFinalRelease()
- {
- if (m_hWnd != NULL)
- DestroyWindow(); // will call PostNcDestroy
- else
- PostNcDestroy();
- }
-
- #ifdef _DEBUG
- void CWnd::AssertValid() const
- {
- if (m_hWnd == NULL)
- return; // null (unattached) windows are valid
-
- // check for special wnd??? values
- ASSERT(HWND_TOP == NULL); // same as desktop
- if (m_hWnd == HWND_BOTTOM)
- ASSERT(this == &CWnd::wndBottom);
- else if (m_hWnd == HWND_TOPMOST)
- ASSERT(this == &CWnd::wndTopMost);
- else if (m_hWnd == HWND_NOTOPMOST)
- ASSERT(this == &CWnd::wndNoTopMost);
- else
- {
- // should be a normal window
- ASSERT(::IsWindow(m_hWnd));
-
- // should also be in the permanent or temporary handle map
- CHandleMap* pMap = afxMapHWND();
- ASSERT(pMap != NULL);
-
- CObject* p;
- ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
- (p = pMap->LookupTemporary(m_hWnd)) != NULL);
- ASSERT((CWnd*)p == this); // must be us
-
- // Note: if either of the above asserts fire and you are
- // writing a multithreaded application, it is likely that
- // you have passed a C++ object from one thread to another
- // and have used that object in a way that was not intended.
- // (only simple inline wrapper functions should be used)
- //
- // In general, CWnd objects should be passed by HWND from
- // one thread to another. The receiving thread can wrap
- // the HWND with a CWnd object by using CWnd::FromHandle.
- //
- // It is dangerous to pass C++ objects from one thread to
- // another, unless the objects are designed to be used in
- // such a manner.
- }
- }
-
- void CWnd::Dump(CDumpContext& dc) const
- {
- CObject::Dump(dc);
-
- dc << "\nm_hWnd = " << (UINT)m_hWnd;
-
- if (m_hWnd == NULL || m_hWnd == HWND_BOTTOM ||
- m_hWnd == HWND_TOPMOST || m_hWnd == HWND_NOTOPMOST)
- {
- // not a normal window - nothing more to dump
- return;
- }
-
- if (!::IsWindow(m_hWnd))
- {
- // not a valid window
- dc << " (illegal HWND)";
- return; // don't do anything more
- }
-
- CWnd* pWnd = CWnd::FromHandlePermanent(m_hWnd);
- if (pWnd != this)
- dc << " (Detached or temporary window)";
- else
- dc << " (permanent window)";
-
- // dump out window specific statistics
- TCHAR szBuf [64];
- if (!::SendMessage(m_hWnd, WM_QUERYAFXWNDPROC, 0, 0) && pWnd == this)
- GetWindowText(szBuf, _countof(szBuf));
- else
- ::DefWindowProc(m_hWnd, WM_GETTEXT, _countof(szBuf), (LPARAM)&szBuf[0]);
- dc << "\ncaption = \"" << szBuf << "\"";
-
- ::GetClassName(m_hWnd, szBuf, _countof(szBuf));
- dc << "\nclass name = \"" << szBuf << "\"";
-
- CRect rect;
- GetWindowRect(&rect);
- dc << "\nrect = " << rect;
- dc << "\nparent CWnd* = " << (void*)GetParent();
-
- dc << "\nstyle = " << (void*)::GetWindowLong(m_hWnd, GWL_STYLE);
- if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_CHILD)
- dc << "\nid = " << _AfxGetDlgCtrlID(m_hWnd);
-
- dc << "\n";
- }
- #endif
-
- BOOL CWnd::DestroyWindow()
- {
- if (m_hWnd == NULL)
- return FALSE;
-
- CHandleMap* pMap = afxMapHWND();
- ASSERT(pMap != NULL);
- CWnd* pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
- #ifdef _DEBUG
- HWND hWndOrig = m_hWnd;
- #endif
-
- #ifdef _AFX_NO_OCC_SUPPORT
- BOOL bResult = ::DestroyWindow(m_hWnd);
- #else //_AFX_NO_OCC_SUPPORT
- BOOL bResult;
- if (m_pCtrlSite == NULL)
- bResult = ::DestroyWindow(m_hWnd);
- else
- bResult = m_pCtrlSite->DestroyControl();
- #endif //_AFX_NO_OCC_SUPPORT
-
- // Note that 'this' may have been deleted at this point,
- // (but only if pWnd != NULL)
- if (pWnd != NULL)
- {
- // Should have been detached by OnNcDestroy
- #ifdef _DEBUG
- ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);
- #endif
- }
- else
- {
- #ifdef _DEBUG
- ASSERT(m_hWnd == hWndOrig);
- #endif
- // Detach after DestroyWindow called just in case
- Detach();
- }
- return bResult;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Default CWnd implementation
-
- LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- if (m_pfnSuper != NULL)
- return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);
-
- WNDPROC pfnWndProc;
- if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)
- return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
- else
- return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
- }
-
- WNDPROC* CWnd::GetSuperWndProcAddr()
- {
- // Note: it is no longer necessary to override GetSuperWndProcAddr
- // for each control class with a different WNDCLASS.
- // This implementation now uses instance data, such that the previous
- // WNDPROC can be anything.
-
- return &m_pfnSuper;
- }
-
- BOOL CWnd::PreTranslateMessage(MSG* pMsg)
- {
- // handle tooltip messages (some messages cancel, some may cause it to popup)
- AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
- if (pModuleState->m_pfnFilterToolTipMessage != NULL)
- (*pModuleState->m_pfnFilterToolTipMessage)(pMsg, this);
-
- // no default processing
- return FALSE;
- }
-
- void PASCAL CWnd::CancelToolTips(BOOL bKeys)
- {
- // check for active tooltip
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
- if (pToolTip->GetSafeHwnd() != NULL)
- pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
-
- // check for active control bar fly-by status
- CControlBar* pLastStatus = pThreadState->m_pLastStatus;
- if (bKeys && pLastStatus != NULL && GetKeyState(VK_LBUTTON) >= 0)
- pLastStatus->SetStatusText(-1);
- }
-
- int CWnd::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
- {
- // find child window which hits the point
- // (don't use WindowFromPoint, because it ignores disabled windows)
- HWND hWndChild = _AfxChildWindowFromPoint(m_hWnd, point);
- if (hWndChild != NULL)
- {
- // return positive hit if control ID isn't -1
- int nHit = _AfxGetDlgCtrlID(hWndChild);
-
- // hits against child windows always center the tip
- if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))
- {
- // setup the TOOLINFO structure
- pTI->hwnd = m_hWnd;
- pTI->uId = (UINT)hWndChild;
- pTI->uFlags |= TTF_IDISHWND;
- pTI->lpszText = LPSTR_TEXTCALLBACK;
-
- // set TTF_NOTBUTTON and TTF_CENTERTIP if it isn't a button
- if (!(::SendMessage(hWndChild, WM_GETDLGCODE, 0, 0) & DLGC_BUTTON))
- pTI->uFlags |= TTF_NOTBUTTON|TTF_CENTERTIP;
- }
- return nHit;
- }
- return -1; // not found
- }
-
- void CWnd::GetWindowText(CString& rString) const
- {
- ASSERT(::IsWindow(m_hWnd));
-
- #ifndef _AFX_NO_OCC_SUPPORT
- if (m_pCtrlSite == NULL)
- {
- #endif
- int nLen = ::GetWindowTextLength(m_hWnd);
- ::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen), nLen+1);
- rString.ReleaseBuffer();
-
- #ifndef _AFX_NO_OCC_SUPPORT
- }
- else
- {
- m_pCtrlSite->GetWindowText(rString);
- }
- #endif
- }
-
- int CWnd::GetDlgItemText(int nID, CString& rString) const
- {
- ASSERT(::IsWindow(m_hWnd));
- rString = &afxChNil; // empty without deallocating
-
- #ifndef _AFX_NO_OCC_SUPPORT
- if (m_pCtrlCont == NULL)
- {
- #endif
- HWND hWnd = ::GetDlgItem(m_hWnd, nID);
- if (hWnd != NULL)
- {
- int nLen = ::GetWindowTextLength(hWnd);
- ::GetWindowText(hWnd, rString.GetBufferSetLength(nLen), nLen+1);
- rString.ReleaseBuffer();
- }
-
- #ifndef _AFX_NO_OCC_SUPPORT
- }
- else
- {
- CWnd* pWnd = GetDlgItem(nID);
- if (pWnd != NULL)
- pWnd->GetWindowText(rString);
- }
- #endif
-
- return rString.GetLength();
- }
-
- BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT* lpwndpl) const
- {
- ASSERT(::IsWindow(m_hWnd));
- lpwndpl->length = sizeof(WINDOWPLACEMENT);
- return ::GetWindowPlacement(m_hWnd, lpwndpl);
- }
-
- BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl)
- {
- ASSERT(::IsWindow(m_hWnd));
- ((WINDOWPLACEMENT*)lpwndpl)->length = sizeof(WINDOWPLACEMENT);
- return ::SetWindowPlacement(m_hWnd, lpwndpl);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CWnd will delegate owner draw messages to self drawing controls
-
- // Drawing: for all 4 control types
- void CWnd::OnDrawItem(int /*nIDCtl*/, LPDRAWITEMSTRUCT lpDrawItemStruct)
- {
- if (lpDrawItemStruct->CtlType == ODT_MENU)
- {
- CMenu* pMenu = CMenu::FromHandlePermanent(
- (HMENU)lpDrawItemStruct->hwndItem);
- if (pMenu != NULL)
- {
- pMenu->DrawItem(lpDrawItemStruct);
- return; // eat it
- }
- }
- else
- {
- // reflect notification to child window control
- if (ReflectLastMsg(lpDrawItemStruct->hwndItem))
- return; // eat it
- }
- // not handled - do default
- Default();
- }
-
- // Drawing: for all 4 control types
- int CWnd::OnCompareItem(int /*nIDCtl*/, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
- {
- // reflect notification to child window control
- LRESULT lResult;
- if (ReflectLastMsg(lpCompareItemStruct->hwndItem, &lResult))
- return (int)lResult; // eat it
-
- // not handled - do default
- return (int)Default();
- }
-
- void CWnd::OnDeleteItem(int /*nIDCtl*/, LPDELETEITEMSTRUCT lpDeleteItemStruct)
- {
- // reflect notification to child window control
- if (ReflectLastMsg(lpDeleteItemStruct->hwndItem))
- return; // eat it
- // not handled - do default
- Default();
- }
-
- int CWnd::OnCharToItem(UINT, CListBox* pWnd, UINT)
- {
- if (pWnd != NULL)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (int)lResult; // eat it
- }
- // not handled - do default
- return (int)Default();
- }
-
- int CWnd::OnVKeyToItem(UINT, CListBox* pWnd, UINT)
- {
- if (pWnd != NULL)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (int)lResult; // eat it
- }
- // not handled - do default
- return (int)Default();
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Self drawing menus are a little trickier
-
- BOOL CMenu::TrackPopupMenu(UINT nFlags, int x, int y,
- CWnd* pWnd, LPCRECT lpRect)
- {
- ASSERT(m_hMenu != NULL);
-
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- HWND hWndOld = pThreadState->m_hTrackingWindow;
- HMENU hMenuOld = pThreadState->m_hTrackingMenu;
- pThreadState->m_hTrackingWindow = pWnd->GetSafeHwnd();
- pThreadState->m_hTrackingMenu = m_hMenu;
- BOOL bOK = ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0,
- pThreadState->m_hTrackingWindow, lpRect);
- pThreadState->m_hTrackingWindow = hWndOld;
- pThreadState->m_hTrackingMenu = hMenuOld;
-
- return bOK;
- }
-
- AFX_STATIC CMenu* AFXAPI _AfxFindPopupMenuFromID(CMenu* pMenu, UINT nID)
- {
- ASSERT_VALID(pMenu);
- // walk through all items, looking for ID match
- UINT nItems = pMenu->GetMenuItemCount();
- for (int iItem = 0; iItem < (int)nItems; iItem++)
- {
- CMenu* pPopup = pMenu->GetSubMenu(iItem);
- if (pPopup != NULL)
- {
- // recurse to child popup
- pPopup = _AfxFindPopupMenuFromID(pPopup, nID);
- // check popups on this popup
- if (pPopup != NULL)
- return pPopup;
- }
- else if (pMenu->GetMenuItemID(iItem) == nID)
- {
- // it is a normal item inside our popup
- pMenu = CMenu::FromHandlePermanent(pMenu->m_hMenu);
- return pMenu;
- }
- }
- // not found
- return NULL;
- }
-
- // Measure item implementation relies on unique control/menu IDs
- void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
- {
- if (lpMeasureItemStruct->CtlType == ODT_MENU)
- {
- ASSERT(lpMeasureItemStruct->CtlID == 0);
- CMenu* pMenu;
-
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- if (pThreadState->m_hTrackingWindow == m_hWnd)
- {
- // start from popup
- pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu);
- }
- else
- {
- // start from menubar
- pMenu = GetMenu();
- }
-
- pMenu = _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID);
- if (pMenu != NULL)
- pMenu->MeasureItem(lpMeasureItemStruct);
- else
- TRACE1("Warning: unknown WM_MEASUREITEM for menu item 0x%04X.\n",
- lpMeasureItemStruct->itemID);
- }
- else
- {
- CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
- if (pChild != NULL && pChild->SendChildNotifyLastMsg())
- return; // eaten by child
- }
- // not handled - do default
- Default();
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Additional helpers for WNDCLASS init
-
- // like RegisterClass, except will automatically call UnregisterClass
- BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
- {
- WNDCLASS wndcls;
- if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
- &wndcls))
- {
- // class already registered
- return TRUE;
- }
-
- if (!::RegisterClass(lpWndClass))
- {
- TRACE1("Can't register window class named %s\n",
- lpWndClass->lpszClassName);
- return FALSE;
- }
-
- if (afxContextIsDLL)
- {
- AfxLockGlobals(CRIT_REGCLASSLIST);
- TRY
- {
- // class registered successfully, add to registered list
- AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
- LPTSTR lpszUnregisterList = pModuleState->m_szUnregisterList;
- // the buffer is of fixed size -- ensure that it does not overflow
- ASSERT(lstrlen(lpszUnregisterList) + 1 +
- lstrlen(lpWndClass->lpszClassName) + 1 <
- _countof(pModuleState->m_szUnregisterList));
- // append classname + newline to m_szUnregisterList
- lstrcat(lpszUnregisterList, lpWndClass->lpszClassName);
- TCHAR szTemp[2];
- szTemp[0] = '\n';
- szTemp[1] = '\0';
- lstrcat(lpszUnregisterList, szTemp);
- }
- CATCH_ALL(e)
- {
- AfxUnlockGlobals(CRIT_REGCLASSLIST);
- THROW_LAST();
- // Note: DELETE_EXCEPTION not required.
- }
- END_CATCH_ALL
- AfxUnlockGlobals(CRIT_REGCLASSLIST);
- }
-
- return TRUE;
- }
-
- LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,
- HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)
- {
- // Returns a temporary string name for the class
- // Save in a CString if you want to use it for a long time
- LPTSTR lpszName = AfxGetThreadState()->m_szTempClassName;
-
- // generate a synthetic name for this class
- HINSTANCE hInst = AfxGetInstanceHandle();
- if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
- wsprintf(lpszName, _T("Afx:%x:%x"), (UINT)hInst, nClassStyle);
- else
- wsprintf(lpszName, _T("Afx:%x:%x:%x:%x:%x"), (UINT)hInst, nClassStyle,
- (UINT)hCursor, (UINT)hbrBackground, (UINT)hIcon);
-
- // see if the class already exists
- WNDCLASS wndcls;
- if (::GetClassInfo(hInst, lpszName, &wndcls))
- {
- // already registered, assert everything is good
- ASSERT(wndcls.style == nClassStyle);
-
- // NOTE: We have to trust that the hIcon, hbrBackground, and the
- // hCursor are semantically the same, because sometimes Windows does
- // some internal translation or copying of those handles before
- // storing them in the internal WNDCLASS retrieved by GetClassInfo.
- return lpszName;
- }
-
- // otherwise we need to register a new class
- wndcls.style = nClassStyle;
- wndcls.lpfnWndProc = DefWindowProc;
- wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
- wndcls.hInstance = hInst;
- wndcls.hIcon = hIcon;
- wndcls.hCursor = hCursor;
- wndcls.hbrBackground = hbrBackground;
- wndcls.lpszMenuName = NULL;
- wndcls.lpszClassName = lpszName;
- if (!AfxRegisterClass(&wndcls))
- AfxThrowResourceException();
-
- // return thread-local pointer
- return lpszName;
- }
-
- struct AFX_CTLCOLOR
- {
- HWND hWnd;
- HDC hDC;
- UINT nCtlType;
- };
-
- LRESULT CWnd::OnNTCtlColor(WPARAM wParam, LPARAM lParam)
- {
- // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
- AFX_CTLCOLOR ctl;
- ctl.hDC = (HDC)wParam;
- ctl.hWnd = (HWND)lParam;
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- ctl.nCtlType = pThreadState->m_lastSentMsg.message - WM_CTLCOLORMSGBOX;
- ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
- ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
-
- // Note: We call the virtual WindowProc for this window directly,
- // instead of calling AfxCallWindowProc, so that Default()
- // will still work (it will call the Default window proc with
- // the original Win32 WM_CTLCOLOR message).
- return WindowProc(WM_CTLCOLOR, 0, (LPARAM)&ctl);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CWnd extensions for help support
-
- void CWnd::WinHelp(DWORD dwData, UINT nCmd)
- {
- CWinApp* pApp = AfxGetApp();
- ASSERT_VALID(pApp);
- ASSERT(pApp->m_pszHelpFilePath != NULL);
-
- CWaitCursor wait;
- if (IsFrameWnd())
- {
- // CFrameWnd windows should be allowed to exit help mode first
- CFrameWnd* pFrameWnd = (CFrameWnd*)this;
- pFrameWnd->ExitHelpMode();
- }
-
- // cancel any tracking modes
- SendMessage(WM_CANCELMODE);
- SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
-
- // need to use top level parent (for the case where m_hWnd is in DLL)
- CWnd* pWnd = GetTopLevelParent();
- pWnd->SendMessage(WM_CANCELMODE);
- pWnd->SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
-
- // attempt to cancel capture
- HWND hWndCapture = ::GetCapture();
- if (hWndCapture != NULL)
- ::SendMessage(hWndCapture, WM_CANCELMODE, 0, 0);
-
- TRACE3("WinHelp: pszHelpFile = '%s', dwData: $%lx, fuCommand: %d.\n",
- pApp->m_pszHelpFilePath, dwData, nCmd);
-
- // finally, run the Windows Help engine
- if (!::WinHelp(pWnd->m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
- AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Message table implementation
-
- BEGIN_MESSAGE_MAP(CWnd, CCmdTarget)
- ON_MESSAGE(WM_CTLCOLORSTATIC, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLOREDIT, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORBTN, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORLISTBOX, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORDLG, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORMSGBOX, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORSCROLLBAR, OnNTCtlColor)
- //{{AFX_MSG_MAP(CWnd)
- ON_WM_DRAWITEM()
- ON_WM_MEASUREITEM()
- ON_WM_CTLCOLOR()
- ON_WM_COMPAREITEM()
- ON_WM_ENTERIDLE()
- ON_WM_HSCROLL()
- ON_WM_VSCROLL()
- ON_WM_DELETEITEM()
- ON_WM_CHARTOITEM()
- ON_WM_VKEYTOITEM()
- ON_WM_NCDESTROY()
- ON_WM_PARENTNOTIFY()
- ON_WM_SYSCOLORCHANGE()
- ON_WM_DEVMODECHANGE()
- ON_WM_HELPINFO()
- ON_WM_SETTINGCHANGE()
- //}}AFX_MSG_MAP
- #ifndef _AFX_NO_OCC_SUPPORT
- ON_WM_DESTROY()
- #endif
- ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
- ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
- ON_REGISTERED_MESSAGE(CWnd::m_nMsgDragList, OnDragList)
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // Routines for fast search of message maps
-
- const AFX_MSGMAP_ENTRY* AFXAPI
- AfxFindMessageEntry(const AFX_MSGMAP_ENTRY* lpEntry,
- UINT nMsg, UINT nCode, UINT nID)
- {
- #if defined(_M_IX86) && !defined(_AFX_PORTABLE)
- // 32-bit Intel 386/486 version.
-
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nMessage) == 0);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nCode) == 4);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nID) == 8);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nLastID) == 12);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nSig) == 16);
-
- _asm
- {
- MOV EBX,lpEntry
- MOV EAX,nMsg
- MOV EDX,nCode
- MOV ECX,nID
- __loop:
- CMP DWORD PTR [EBX+16],0 ; nSig (0 => end)
- JZ __failed
- CMP EAX,DWORD PTR [EBX] ; nMessage
- JE __found_message
- __next:
- ADD EBX,SIZE AFX_MSGMAP_ENTRY
- JMP short __loop
- __found_message:
- CMP EDX,DWORD PTR [EBX+4] ; nCode
- JNE __next
- // message and code good so far
- // check the ID
- CMP ECX,DWORD PTR [EBX+8] ; nID
- JB __next
- CMP ECX,DWORD PTR [EBX+12] ; nLastID
- JA __next
- // found a match
- MOV lpEntry,EBX ; return EBX
- JMP short __end
- __failed:
- XOR EAX,EAX ; return NULL
- MOV lpEntry,EAX
- __end:
- }
- return lpEntry;
- #else // _AFX_PORTABLE
- // C version of search routine
- while (lpEntry->nSig != AfxSig_end)
- {
- if (lpEntry->nMessage == nMsg && lpEntry->nCode == nCode &&
- nID >= lpEntry->nID && nID <= lpEntry->nLastID)
- {
- return lpEntry;
- }
- lpEntry++;
- }
- return NULL; // not found
- #endif // _AFX_PORTABLE
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Cache of most recently sent messages
-
- #ifndef iHashMax
- // iHashMax must be a power of two
- #define iHashMax 512
- #endif
-
- struct AFX_MSG_CACHE
- {
- UINT nMsg;
- const AFX_MSGMAP_ENTRY* lpEntry;
- const AFX_MSGMAP* pMessageMap;
- };
-
- AFX_MSG_CACHE _afxMsgCache[iHashMax];
-
- void AFXAPI AfxResetMsgCache()
- {
- memset(_afxMsgCache, 0, sizeof(_afxMsgCache));
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // main WindowProc implementation
-
- LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- // OnWndMsg does most of the work, except for DefWindowProc call
- LRESULT lResult = 0;
- if (!OnWndMsg(message, wParam, lParam, &lResult))
- lResult = DefWindowProc(message, wParam, lParam);
- return lResult;
- }
-
- BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- LRESULT lResult = 0;
-
- // special case for commands
- if (message == WM_COMMAND)
- {
- if (OnCommand(wParam, lParam))
- {
- lResult = 1;
- goto LReturnTrue;
- }
- return FALSE;
- }
-
- // special case for notifies
- if (message == WM_NOTIFY)
- {
- NMHDR* pNMHDR = (NMHDR*)lParam;
- if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
- goto LReturnTrue;
- return FALSE;
- }
-
- // special case for activation
- if (message == WM_ACTIVATE)
- _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
-
- // special case for set cursor HTERROR
- if (message == WM_SETCURSOR &&
- _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
- {
- lResult = 1;
- goto LReturnTrue;
- }
-
- const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
- UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax-1);
- AfxLockGlobals(CRIT_WINMSGCACHE);
- AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
- const AFX_MSGMAP_ENTRY* lpEntry;
- if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
- {
- // cache hit
- lpEntry = pMsgCache->lpEntry;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- if (lpEntry == NULL)
- return FALSE;
-
- // cache hit, and it needs to be handled
- if (message < 0xC000)
- goto LDispatch;
- else
- goto LDispatchRegistered;
- }
- else
- {
- // not in cache, look for it
- pMsgCache->nMsg = message;
- pMsgCache->pMessageMap = pMessageMap;
-
- #ifdef _AFXDLL
- for (/* pMessageMap already init'ed */; pMessageMap != NULL;
- pMessageMap = (*pMessageMap->pfnGetBaseMap)())
- #else
- for (/* pMessageMap already init'ed */; pMessageMap != NULL;
- pMessageMap = pMessageMap->pBaseMap)
- #endif
- {
- // Note: catch not so common but fatal mistake!!
- // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
- #ifdef _AFXDLL
- ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
- #else
- ASSERT(pMessageMap != pMessageMap->pBaseMap);
- #endif
-
- if (message < 0xC000)
- {
- // constant window message
- if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
- message, 0, 0)) != NULL)
- {
- pMsgCache->lpEntry = lpEntry;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- goto LDispatch;
- }
- }
- else
- {
- // registered windows message
- lpEntry = pMessageMap->lpEntries;
- while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
- {
- UINT* pnID = (UINT*)(lpEntry->nSig);
- ASSERT(*pnID >= 0xC000 || *pnID == 0);
- // must be successfully registered
- if (*pnID == message)
- {
- pMsgCache->lpEntry = lpEntry;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- goto LDispatchRegistered;
- }
- lpEntry++; // keep looking past this one
- }
- }
- }
-
- pMsgCache->lpEntry = NULL;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- return FALSE;
- }
- ASSERT(FALSE); // not reached
-
- LDispatch:
- ASSERT(message < 0xC000);
- union MessageMapFunctions mmf;
- mmf.pfn = lpEntry->pfn;
-
- // if we've got WM_SETTINGCHANGE / WM_WININICHANGE, we need to
- // decide if we're going to call OnWinIniChange() or OnSettingChange()
-
- int nSig;
- nSig = lpEntry->nSig;
- if (lpEntry->nID == WM_SETTINGCHANGE)
- {
- DWORD dwVersion = GetVersion();
- if (LOBYTE(LOWORD(dwVersion)) >= 4)
- nSig = AfxSig_vws;
- else
- nSig = AfxSig_vs;
- }
-
- switch (nSig)
- {
- default:
- ASSERT(FALSE);
- break;
-
- case AfxSig_bD:
- lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));
- break;
-
- case AfxSig_bb: // AfxSig_bb, AfxSig_bw, AfxSig_bh
- lResult = (this->*mmf.pfn_bb)((BOOL)wParam);
- break;
-
- case AfxSig_bWww: // really AfxSig_bWiw
- lResult = (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam),
- (short)LOWORD(lParam), HIWORD(lParam));
- break;
-
- case AfxSig_bWCDS:
- lResult = (this->*mmf.pfn_bWCDS)(CWnd::FromHandle((HWND)wParam),
- (COPYDATASTRUCT*)lParam);
- break;
-
- case AfxSig_bHELPINFO:
- lResult = (this->*mmf.pfn_bHELPINFO)((HELPINFO*)lParam);
- break;
-
- case AfxSig_hDWw:
- {
- // special case for OnCtlColor to avoid too many temporary objects
- ASSERT(message == WM_CTLCOLOR);
- AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
- CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
- CWnd wndTemp; wndTemp.m_hWnd = pCtl->hWnd;
- UINT nCtlType = pCtl->nCtlType;
- // if not coming from a permanent window, use stack temporary
- CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
- if (pWnd == NULL)
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // determine the site of the OLE control if it is one
- COleControlSite* pSite;
- if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
- m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
- {
- wndTemp.m_pCtrlSite = pSite;
- }
- #endif
- pWnd = &wndTemp;
- }
- HBRUSH hbr = (this->*mmf.pfn_hDWw)(&dcTemp, pWnd, nCtlType);
- // fast detach of temporary objects
- dcTemp.m_hDC = NULL;
- wndTemp.m_hWnd = NULL;
- lResult = (LRESULT)hbr;
- }
- break;
-
- case AfxSig_hDw:
- {
- // special case for CtlColor to avoid too many temporary objects
- ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
- AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
- CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
- UINT nCtlType = pCtl->nCtlType;
- HBRUSH hbr = (this->*mmf.pfn_hDw)(&dcTemp, nCtlType);
- // fast detach of temporary objects
- dcTemp.m_hDC = NULL;
- lResult = (LRESULT)hbr;
- }
- break;
-
- case AfxSig_iwWw:
- lResult = (this->*mmf.pfn_iwWw)(LOWORD(wParam),
- CWnd::FromHandle((HWND)lParam), HIWORD(wParam));
- break;
-
- case AfxSig_iww:
- lResult = (this->*mmf.pfn_iww)(LOWORD(wParam), HIWORD(wParam));
- break;
-
- case AfxSig_iWww: // really AfxSig_iWiw
- lResult = (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam),
- (short)LOWORD(lParam), HIWORD(lParam));
- break;
-
- case AfxSig_is:
- lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);
- break;
-
- case AfxSig_lwl:
- lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
- break;
-
- case AfxSig_lwwM:
- lResult = (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam),
- (UINT)HIWORD(wParam), (CMenu*)CMenu::FromHandle((HMENU)lParam));
- break;
-
- case AfxSig_vv:
- (this->*mmf.pfn_vv)();
- break;
-
- case AfxSig_vw: // AfxSig_vb, AfxSig_vh
- (this->*mmf.pfn_vw)(wParam);
- break;
-
- case AfxSig_vww:
- (this->*mmf.pfn_vww)((UINT)wParam, (UINT)lParam);
- break;
-
- case AfxSig_vvii:
- (this->*mmf.pfn_vvii)((short)LOWORD(lParam), (short)HIWORD(lParam));
- break;
-
- case AfxSig_vwww:
- (this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam));
- break;
-
- case AfxSig_vwii:
- (this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam));
- break;
-
- case AfxSig_vwl:
- (this->*mmf.pfn_vwl)(wParam, lParam);
- break;
-
- case AfxSig_vbWW:
- (this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam,
- CWnd::FromHandle((HWND)lParam),
- CWnd::FromHandle((HWND)wParam));
- break;
-
- case AfxSig_vD:
- (this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam));
- break;
-
- case AfxSig_vM:
- (this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam));
- break;
-
- case AfxSig_vMwb:
- (this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam),
- LOWORD(lParam), (BOOL)HIWORD(lParam));
- break;
-
- case AfxSig_vW:
- (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam));
- break;
-
- case AfxSig_vW2:
- (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)lParam));
- break;
-
- case AfxSig_vWww:
- (this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam),
- HIWORD(lParam));
- break;
-
- case AfxSig_vWp:
- {
- CPoint point((DWORD)lParam);
- (this->*mmf.pfn_vWp)(CWnd::FromHandle((HWND)wParam), point);
- }
- break;
-
- case AfxSig_vWh:
- (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
- (HANDLE)lParam);
- break;
-
- case AfxSig_vwW:
- (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam));
- break;
-
- case AfxSig_vwWb:
- (this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)),
- CWnd::FromHandle((HWND)lParam), (BOOL)HIWORD(wParam));
- break;
-
- case AfxSig_vwwW:
- case AfxSig_vwwx:
- {
- // special case for WM_VSCROLL and WM_HSCROLL
- ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
- message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
- int nScrollCode = (short)LOWORD(wParam);
- int nPos = (short)HIWORD(wParam);
- if (lpEntry->nSig == AfxSig_vwwW)
- (this->*mmf.pfn_vwwW)(nScrollCode, nPos,
- CWnd::FromHandle((HWND)lParam));
- else
- (this->*mmf.pfn_vwwx)(nScrollCode, nPos);
- }
- break;
-
- case AfxSig_vs:
- (this->*mmf.pfn_vs)((LPTSTR)lParam);
- break;
-
- case AfxSig_vws:
- (this->*mmf.pfn_vws)((UINT) wParam, (LPCTSTR)lParam);
- break;
-
- case AfxSig_vOWNER:
- (this->*mmf.pfn_vOWNER)((int)wParam, (LPTSTR)lParam);
- lResult = TRUE;
- break;
-
- case AfxSig_iis:
- lResult = (this->*mmf.pfn_iis)((int)wParam, (LPTSTR)lParam);
- break;
-
- case AfxSig_wp:
- {
- CPoint point((DWORD)lParam);
- lResult = (this->*mmf.pfn_wp)(point);
- }
- break;
-
- case AfxSig_wv: // AfxSig_bv, AfxSig_wv
- lResult = (this->*mmf.pfn_wv)();
- break;
-
- case AfxSig_vCALC:
- (this->*mmf.pfn_vCALC)((BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam);
- break;
-
- case AfxSig_vPOS:
- (this->*mmf.pfn_vPOS)((WINDOWPOS*)lParam);
- break;
-
- case AfxSig_vwwh:
- (this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam);
- break;
-
- case AfxSig_vwp:
- {
- CPoint point((DWORD)lParam);
- (this->*mmf.pfn_vwp)(wParam, point);
- break;
- }
- case AfxSig_vwSIZING:
- (this->*mmf.pfn_vwl)(wParam, lParam);
- lResult = TRUE;
- break;
-
- case AfxSig_bwsp:
- lResult = (this->*mmf.pfn_bwsp)(LOWORD(wParam), (short) HIWORD(wParam),
- CPoint(LOWORD(lParam), HIWORD(lParam)));
- if (!lResult)
- return FALSE;
- }
- goto LReturnTrue;
-
- LDispatchRegistered: // for registered windows messages
- ASSERT(message >= 0xC000);
- mmf.pfn = lpEntry->pfn;
- lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
-
- LReturnTrue:
- if (pResult != NULL)
- *pResult = lResult;
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CTestCmdUI - used to test for disabled commands before dispatching
-
- class CTestCmdUI : public CCmdUI
- {
- public:
- CTestCmdUI();
-
- public: // re-implementations only
- virtual void Enable(BOOL bOn);
- virtual void SetCheck(int nCheck);
- virtual void SetRadio(BOOL bOn);
- virtual void SetText(LPCTSTR);
-
- BOOL m_bEnabled;
- };
-
- CTestCmdUI::CTestCmdUI()
- {
- m_bEnabled = TRUE; // assume it is enabled
- }
-
- void CTestCmdUI::Enable(BOOL bOn)
- {
- m_bEnabled = bOn;
- m_bEnableChanged = TRUE;
- }
-
- void CTestCmdUI::SetCheck(int)
- {
- // do nothing -- just want to know about calls to Enable
- }
-
- void CTestCmdUI::SetRadio(BOOL)
- {
- // do nothing -- just want to know about calls to Enable
- }
-
- void CTestCmdUI::SetText(LPCTSTR)
- {
- // do nothing -- just want to know about calls to Enable
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CWnd command handling
-
- BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
- // return TRUE if command invocation was attempted
- {
- UINT nID = LOWORD(wParam);
- HWND hWndCtrl = (HWND)lParam;
- int nCode = HIWORD(wParam);
-
- // default routing for command messages (through closure table)
-
- if (hWndCtrl == NULL)
- {
- // zero IDs for normal commands are not allowed
- if (nID == 0)
- return FALSE;
-
- // make sure command has not become disabled before routing
- CTestCmdUI state;
- state.m_nID = nID;
- OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
- if (!state.m_bEnabled)
- {
- TRACE1("Warning: not executing disabled command %d\n", nID);
- return TRUE;
- }
-
- // menu or accelerator
- nCode = CN_COMMAND;
- }
- else
- {
- // control notification
- ASSERT(nID == 0 || ::IsWindow(hWndCtrl));
-
- if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
- return TRUE; // locked out - ignore control notification
-
- // reflect notification to child window control
- if (ReflectLastMsg(hWndCtrl))
- return TRUE; // eaten by child
-
- // zero IDs for normal commands are not allowed
- if (nID == 0)
- return FALSE;
- }
-
- #ifdef _DEBUG
- if (nCode < 0 && nCode != (int)0x8000)
- TRACE1("Implementation Warning: control notification = $%X.\n",
- nCode);
- #endif
-
- return OnCmdMsg(nID, nCode, NULL, NULL);
- }
-
- BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult)
- {
- ASSERT(pResult != NULL);
- NMHDR* pNMHDR = (NMHDR*)lParam;
- HWND hWndCtrl = pNMHDR->hwndFrom;
-
- // get the child ID from the window itself
- UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
- int nCode = pNMHDR->code;
-
- ASSERT(hWndCtrl != NULL);
- ASSERT(::IsWindow(hWndCtrl));
-
- if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
- return TRUE; // locked out - ignore control notification
-
- // reflect notification to child window control
- if (ReflectLastMsg(hWndCtrl, pResult))
- return TRUE; // eaten by child
-
- AFX_NOTIFY notify;
- notify.pResult = pResult;
- notify.pNMHDR = pNMHDR;
- return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CWnd extensions
-
- CFrameWnd* CWnd::GetParentFrame() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
-
- ASSERT_VALID(this);
-
- CWnd* pParentWnd = GetParent(); // start with one parent up
- while (pParentWnd != NULL)
- {
- if (pParentWnd->IsFrameWnd())
- return (CFrameWnd*)pParentWnd;
- pParentWnd = pParentWnd->GetParent();
- }
- return NULL;
- }
-
- HWND AFXAPI AfxGetParentOwner(HWND hWnd)
- {
- // check for permanent-owned window first
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
- if (pWnd != NULL)
- return pWnd->GetOwner()->GetSafeHwnd();
-
- // otherwise, return parent in the Windows sense
- return (::GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
- ::GetParent(hWnd) : ::GetWindow(hWnd, GW_OWNER);
- }
-
- CWnd* CWnd::GetTopLevelParent() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
-
- ASSERT_VALID(this);
-
- HWND hWndParent = m_hWnd;
- HWND hWndT;
- while ((hWndT = AfxGetParentOwner(hWndParent)) != NULL)
- hWndParent = hWndT;
-
- return CWnd::FromHandle(hWndParent);
- }
-
- CWnd* CWnd::GetTopLevelOwner() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
-
- ASSERT_VALID(this);
-
- HWND hWndOwner = m_hWnd;
- HWND hWndT;
- while ((hWndT = ::GetWindow(hWndOwner, GW_OWNER)) != NULL)
- hWndOwner = hWndT;
-
- return CWnd::FromHandle(hWndOwner);
- }
-
- CWnd* CWnd::GetParentOwner() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
-
- ASSERT_VALID(this);
-
- HWND hWndParent = m_hWnd;
- HWND hWndT;
- while ((::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) &&
- (hWndT = ::GetParent(hWndParent)) != NULL)
- {
- hWndParent = hWndT;
- }
-
- return CWnd::FromHandle(hWndParent);
- }
-
- BOOL CWnd::IsTopParentActive() const
- {
- ASSERT(m_hWnd != NULL);
- ASSERT_VALID(this);
-
- return CWnd::GetForegroundWindow() ==
- GetTopLevelParent()->GetLastActivePopup();
- }
-
- void CWnd::ActivateTopParent()
- {
- // special activate logic for floating toolbars and palettes
- CWnd* pTopLevel = GetTopLevelParent();
- CWnd* pActiveWnd = GetForegroundWindow();
- if (pActiveWnd == NULL ||
- !(pActiveWnd->m_hWnd == m_hWnd || ::IsChild(pActiveWnd->m_hWnd, m_hWnd)))
- {
- // clicking on floating frame when it does not have
- // focus itself -- activate the toplevel frame instead.
- pTopLevel->SetForegroundWindow();
- }
- }
-
- CFrameWnd* CWnd::GetTopLevelFrame() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
-
- ASSERT_VALID(this);
-
- CFrameWnd* pFrameWnd = (CFrameWnd*)this;
- if (!IsFrameWnd())
- pFrameWnd = GetParentFrame();
-
- if (pFrameWnd != NULL)
- {
- CFrameWnd* pTemp;
- while ((pTemp = pFrameWnd->GetParentFrame()) != NULL)
- pFrameWnd = pTemp;
- }
- return pFrameWnd;
- }
-
- CWnd* PASCAL CWnd::GetSafeOwner(CWnd* pParent, HWND* pWndTop)
- {
- HWND hWnd = GetSafeOwner_(pParent->GetSafeHwnd(), pWndTop);
- return CWnd::FromHandle(hWnd);
- }
-
- int CWnd::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType)
- {
- if (lpszCaption == NULL)
- lpszCaption = AfxGetAppName();
- int nResult = ::MessageBox(GetSafeHwnd(), lpszText, lpszCaption, nType);
- return nResult;
- }
-
- CWnd* PASCAL CWnd::GetDescendantWindow(HWND hWnd, int nID, BOOL bOnlyPerm)
- {
- // GetDlgItem recursive (return first found)
- // breadth-first for 1 level, then depth-first for next level
-
- // use GetDlgItem since it is a fast USER function
- HWND hWndChild;
- CWnd* pWndChild;
- if ((hWndChild = ::GetDlgItem(hWnd, nID)) != NULL)
- {
- if (::GetTopWindow(hWndChild) != NULL)
- {
- // children with the same ID as their parent have priority
- pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
- if (pWndChild != NULL)
- return pWndChild;
- }
- // return temporary handle if allowed
- if (!bOnlyPerm)
- return CWnd::FromHandle(hWndChild);
-
- // return only permanent handle
- pWndChild = CWnd::FromHandlePermanent(hWndChild);
- if (pWndChild != NULL)
- return pWndChild;
- }
-
- // walk each child
- for (hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
- if (pWndChild != NULL)
- return pWndChild;
- }
- return NULL; // not found
- }
-
- void PASCAL CWnd::SendMessageToDescendants(HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam, BOOL bDeep, BOOL bOnlyPerm)
- {
- // walk through HWNDs to avoid creating temporary CWnd objects
- // unless we need to call this function recursively
- for (HWND hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- // if bOnlyPerm is TRUE, don't send to non-permanent windows
- if (bOnlyPerm)
- {
- CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
- if (pWnd != NULL)
- {
- // call window proc directly since it is a C++ window
- AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam);
- }
- }
- else
- {
- // send message with Windows SendMessage API
- ::SendMessage(hWndChild, message, wParam, lParam);
- }
- if (bDeep && ::GetTopWindow(hWndChild) != NULL)
- {
- // send to child windows after parent
- SendMessageToDescendants(hWndChild, message, wParam, lParam,
- bDeep, bOnlyPerm);
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Scroll bar helpers
- // hook for CWnd functions
- // only works for derived class (eg: CView) that override 'GetScrollBarCtrl'
- // if the window doesn't have a _visible_ windows scrollbar - then
- // look for a sibling with the appropriate ID
-
- CScrollBar* CWnd::GetScrollBarCtrl(int) const
- {
- return NULL; // no special scrollers supported
- }
-
- int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw)
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- return pScrollBar->SetScrollPos(nPos, bRedraw);
- else
- return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
- }
-
- int CWnd::GetScrollPos(int nBar) const
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- return pScrollBar->GetScrollPos();
- else
- return ::GetScrollPos(m_hWnd, nBar);
- }
-
- void CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw)
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- pScrollBar->SetScrollRange(nMinPos, nMaxPos, bRedraw);
- else
- ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
- }
-
- void CWnd::GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- pScrollBar->GetScrollRange(lpMinPos, lpMaxPos);
- else
- ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
- }
-
- // Turn on/off non-control scrollbars
- // for WS_?SCROLL scrollbars - show/hide them
- // for control scrollbar - enable/disable them
- void CWnd::EnableScrollBarCtrl(int nBar, BOOL bEnable)
- {
- CScrollBar* pScrollBar;
- if (nBar == SB_BOTH)
- {
- EnableScrollBarCtrl(SB_HORZ, bEnable);
- EnableScrollBarCtrl(SB_VERT, bEnable);
- }
- else if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- {
- // control scrollbar - enable or disable
- pScrollBar->EnableWindow(bEnable);
- }
- else
- {
- // WS_?SCROLL scrollbar - show or hide
- ShowScrollBar(nBar, bEnable);
- }
- }
-
- BOOL CWnd::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw)
- {
- ASSERT(lpScrollInfo != NULL);
- if (afxData.nWinVer < 0x333)
- return FALSE;
-
- HWND hWnd = m_hWnd;
- CScrollBar* pScrollBar;
- if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- {
- hWnd = pScrollBar->m_hWnd;
- nBar = SB_CTL;
- }
- lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
- ::SetScrollInfo(hWnd, nBar, lpScrollInfo, bRedraw);
- return TRUE;
- }
-
- BOOL CWnd::GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask)
- {
- ASSERT(lpScrollInfo != NULL);
- if (afxData.nWinVer < 0x333)
- return FALSE;
-
- HWND hWnd = m_hWnd;
- CScrollBar* pScrollBar;
- if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- {
- hWnd = pScrollBar->m_hWnd;
- nBar = SB_CTL;
- }
- lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
- lpScrollInfo->fMask = nMask;
- return ::GetScrollInfo(hWnd, nBar, lpScrollInfo);
- }
-
- int CWnd::GetScrollLimit(int nBar)
- {
- int nMin, nMax;
- GetScrollRange(nBar, &nMin, &nMax);
- SCROLLINFO info;
- if (GetScrollInfo(nBar, &info, SIF_PAGE))
- {
- nMax -= __max(info.nPage-1,0);
- }
- return nMax;
- }
-
- void CWnd::ScrollWindow(int xAmount, int yAmount,
- LPCRECT lpRect, LPCRECT lpClipRect)
- {
- ASSERT(::IsWindow(m_hWnd));
-
- if (IsWindowVisible() || lpRect != NULL || lpClipRect != NULL)
- {
- // When visible, let Windows do the scrolling
- ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
- }
- else
- {
- // Windows does not perform any scrolling if the window is
- // not visible. This leaves child windows unscrolled.
- // To account for this oversight, the child windows are moved
- // directly instead.
- HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD);
- if (hWndChild != NULL)
- {
- for (; hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- CRect rect;
- ::GetWindowRect(hWndChild, &rect);
- ScreenToClient(&rect);
- ::SetWindowPos(hWndChild, NULL,
- rect.left+xAmount, rect.top+yAmount, 0, 0,
- SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
- }
- }
- }
-
- #ifndef _AFX_NO_OCC_SUPPORT
-
- if ((m_pCtrlCont == NULL) || (lpRect != NULL))
- return;
-
- // the following code is for OLE control containers only
-
- m_pCtrlCont->ScrollChildren(xAmount, yAmount);
-
- #endif // !_AFX_NO_OCC_SUPPORT
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // minimal layout support
-
- void CWnd::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver,
- UINT nFlags, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch)
- {
- ASSERT(nFlags == 0 || nFlags == reposQuery || nFlags == reposExtra);
-
- // walk kids in order, control bars get the resize notification
- // which allow them to shrink the client area
- // remaining size goes to the 'nIDLeftOver' pane
- // NOTE: nIDFirst->nIDLast are usually 0->0xffff
-
- AFX_SIZEPARENTPARAMS layout;
- HWND hWndLeftOver = NULL;
-
- layout.bStretch = bStretch;
- layout.sizeTotal.cx = layout.sizeTotal.cy = 0;
- if (lpRectClient != NULL)
- layout.rect = *lpRectClient; // starting rect comes from parameter
- else
- GetClientRect(&layout.rect); // starting rect comes from client rect
-
- if (nFlags != reposQuery)
- layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess
- else
- layout.hDWP = NULL; // not actually doing layout
-
- for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- UINT nIDC = _AfxGetDlgCtrlID(hWndChild);
- CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
- if (nIDC == nIDLeftOver)
- hWndLeftOver = hWndChild;
- else if (nIDC >= nIDFirst && nIDC <= nIDLast && pWnd != NULL)
- ::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);
- }
-
- // if just getting the available rectangle, return it now...
- if (nFlags == reposQuery)
- {
- ASSERT(lpRectParam != NULL);
- if (bStretch)
- ::CopyRect(lpRectParam, &layout.rect);
- else
- {
- lpRectParam->left = lpRectParam->top = 0;
- lpRectParam->right = layout.sizeTotal.cx;
- lpRectParam->bottom = layout.sizeTotal.cy;
- }
- return;
- }
-
- // the rest is the client size of the left-over pane
- if (nIDLeftOver != 0 && hWndLeftOver != NULL)
- {
- CWnd* pLeftOver = CWnd::FromHandle(hWndLeftOver);
- // allow extra space as specified by lpRectBorder
- if (nFlags == reposExtra)
- {
- ASSERT(lpRectParam != NULL);
- layout.rect.left += lpRectParam->left;
- layout.rect.top += lpRectParam->top;
- layout.rect.right -= lpRectParam->right;
- layout.rect.bottom -= lpRectParam->bottom;
- }
- // reposition the window
- pLeftOver->CalcWindowRect(&layout.rect);
- AfxRepositionWindow(&layout, hWndLeftOver, &layout.rect);
- }
-
- // move and resize all the windows at once!
- if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
- TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
- }
-
- void AFXAPI AfxRepositionWindow(AFX_SIZEPARENTPARAMS* lpLayout,
- HWND hWnd, LPCRECT lpRect)
- {
- ASSERT(hWnd != NULL);
- ASSERT(lpRect != NULL);
- HWND hWndParent = ::GetParent(hWnd);
- ASSERT(hWndParent != NULL);
-
- if (lpLayout != NULL && lpLayout->hDWP == NULL)
- return;
-
- // first check if the new rectangle is the same as the current
- CRect rectOld;
- ::GetWindowRect(hWnd, rectOld);
- ::ScreenToClient(hWndParent, &rectOld.TopLeft());
- ::ScreenToClient(hWndParent, &rectOld.BottomRight());
- if (::EqualRect(rectOld, lpRect))
- return; // nothing to do
-
- // try to use DeferWindowPos for speed, otherwise use SetWindowPos
- if (lpLayout != NULL)
- {
- lpLayout->hDWP = ::DeferWindowPos(lpLayout->hDWP, hWnd, NULL,
- lpRect->left, lpRect->top, lpRect->right - lpRect->left,
- lpRect->bottom - lpRect->top, SWP_NOACTIVATE|SWP_NOZORDER);
- }
- else
- {
- ::SetWindowPos(hWnd, NULL, lpRect->left, lpRect->top,
- lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
- SWP_NOACTIVATE|SWP_NOZORDER);
- }
- }
-
- void CWnd::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
- {
- DWORD dwExStyle = GetExStyle();
- if (nAdjustType == 0)
- dwExStyle &= ~WS_EX_CLIENTEDGE;
- ::AdjustWindowRectEx(lpClientRect, GetStyle(), FALSE, dwExStyle);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Special keyboard/system command processing
-
- BOOL CWnd::HandleFloatingSysCommand(UINT nID, LPARAM lParam)
- {
- CWnd* pParent = GetTopLevelParent();
- switch (nID & 0xfff0)
- {
- case SC_PREVWINDOW:
- case SC_NEXTWINDOW:
- if (LOWORD(lParam) == VK_F6 && pParent != NULL)
- {
- pParent->SetFocus();
- return TRUE;
- }
- break;
-
- case SC_CLOSE:
- case SC_KEYMENU:
- // Check lParam. If it is 0L, then the user may have done
- // an Alt+Tab, so just ignore it. This breaks the ability to
- // just press the Alt-key and have the first menu selected,
- // but this is minor compared to what happens in the Alt+Tab
- // case.
- if ((nID & 0xfff0) == SC_CLOSE || lParam != 0L)
- {
- if (pParent != NULL)
- {
- // Sending the above WM_SYSCOMMAND may destroy the app,
- // so we have to be careful about restoring activation
- // and focus after sending it.
- HWND hWndSave = m_hWnd;
- HWND hWndFocus = ::GetFocus();
- pParent->SetActiveWindow();
- pParent->SendMessage(WM_SYSCOMMAND, nID, lParam);
-
- // be very careful here...
- if (::IsWindow(hWndSave))
- ::SetActiveWindow(hWndSave);
- if (::IsWindow(hWndFocus))
- ::SetFocus(hWndFocus);
- }
- }
- return TRUE;
- }
- return FALSE;
- }
-
- BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
- {
- ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
- ASSERT(pMsg != NULL);
-
- // walk from the target window up to the hWndStop window checking
- // if any window wants to translate this message
-
- for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
- {
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
- if (pWnd != NULL)
- {
- // target window is a C++ window
- if (pWnd->PreTranslateMessage(pMsg))
- return TRUE; // trapped by target window (eg: accelerators)
- }
-
- // got to hWndStop window without interest
- if (hWnd == hWndStop)
- break;
- }
- return FALSE; // no special processing
- }
-
- BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- return OnChildNotify(pThreadState->m_lastSentMsg.message,
- pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);
- }
-
- BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult)
- {
- // get the map, and if no map, then this message does not need reflection
- CHandleMap* pMap = afxMapHWND();
- if (pMap == NULL)
- return FALSE;
-
- // check if in permanent map, if it is reflect it (could be OLE control)
- CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild);
- ASSERT(pWnd == NULL || pWnd->m_hWnd == hWndChild);
- if (pWnd == NULL)
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // check if the window is an OLE control
- CWnd* pWndParent = (CWnd*)pMap->LookupPermanent(::GetParent(hWndChild));
- if (pWndParent != NULL && pWndParent->m_pCtrlCont != NULL)
- {
- // If a matching control site exists, it's an OLE control
- COleControlSite* pSite = (COleControlSite*)pWndParent->
- m_pCtrlCont->m_siteMap.GetValueAt(hWndChild);
- if (pSite != NULL)
- {
- CWnd wndTemp(hWndChild);
- wndTemp.m_pCtrlSite = pSite;
- LRESULT lResult = wndTemp.SendChildNotifyLastMsg(pResult);
- wndTemp.m_hWnd = NULL;
- return lResult;
- }
- }
- #endif //!_AFX_NO_OCC_SUPPORT
- return FALSE;
- }
-
- // only OLE controls and permanent windows will get reflected msgs
- ASSERT(pWnd != NULL);
- return pWnd->SendChildNotifyLastMsg(pResult);
- }
-
- BOOL CWnd::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- if (m_pCtrlSite != NULL)
- {
- // first forward raw OCM_ messages to OLE control sources
- LRESULT lResult = SendMessage(OCM__BASE+uMsg, wParam, lParam);
- if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC &&
- (HBRUSH)lResult == NULL)
- {
- // for WM_CTLCOLOR msgs, returning NULL implies continue routing
- return FALSE;
- }
- if (pResult != NULL)
- *pResult = lResult;
- return TRUE;
- }
- #endif
-
- return ReflectChildNotify(uMsg, wParam, lParam, pResult);
- }
-
- BOOL CWnd::ReflectChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- // Note: reflected messages are send directly to CWnd::OnWndMsg
- // and CWnd::OnCmdMsg for speed and because these messages are not
- // routed by normal OnCmdMsg routing (they are only dispatched)
-
- switch (uMsg)
- {
- // normal messages (just wParam, lParam through OnWndMsg)
- case WM_HSCROLL:
- case WM_VSCROLL:
- case WM_PARENTNOTIFY:
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- case WM_DELETEITEM:
- case WM_VKEYTOITEM:
- case WM_CHARTOITEM:
- case WM_COMPAREITEM:
- // reflect the message through the message map as WM_REFLECT_BASE+uMsg
- return CWnd::OnWndMsg(WM_REFLECT_BASE+uMsg, wParam, lParam, pResult);
-
- // special case for WM_COMMAND
- case WM_COMMAND:
- {
- // reflect the message through the message map as OCM_COMMAND
- int nCode = HIWORD(wParam);
- if (CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_COMMAND), NULL, NULL))
- {
- if (pResult != NULL)
- *pResult = 1;
- return TRUE;
- }
- }
- break;
-
- // special case for WM_NOTIFY
- case WM_NOTIFY:
- {
- // reflect the message through the message map as OCM_NOTIFY
- NMHDR* pNMHDR = (NMHDR*)lParam;
- int nCode = pNMHDR->code;
- AFX_NOTIFY notify;
- notify.pResult = pResult;
- notify.pNMHDR = pNMHDR;
- return CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), ¬ify, NULL);
- }
-
- // other special cases (WM_CTLCOLOR family)
- default:
- if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC)
- {
- // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
- AFX_CTLCOLOR ctl;
- ctl.hDC = (HDC)wParam;
- ctl.nCtlType = uMsg - WM_CTLCOLORMSGBOX;
- ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
- ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
-
- // reflect the message through the message map as OCM_CTLCOLOR
- BOOL bResult = CWnd::OnWndMsg(WM_REFLECT_BASE+WM_CTLCOLOR, 0, (LPARAM)&ctl, pResult);
- if ((HBRUSH)*pResult == NULL)
- bResult = FALSE;
- return bResult;
- }
- break;
- }
-
- return FALSE; // let the parent handle it
- }
-
- void CWnd::OnParentNotify(UINT message, LPARAM lParam)
- {
- if ((LOWORD(message) == WM_CREATE || LOWORD(message) == WM_DESTROY))
- {
- if (ReflectLastMsg((HWND)lParam))
- return; // eat it
- }
- // not handled - do default
- Default();
- }
-
- LRESULT CWnd::OnActivateTopLevel(WPARAM wParam, LPARAM)
- {
- if (LOWORD(wParam) == WA_INACTIVE)
- {
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- if (!(pThreadState->m_lastInfo.uFlags & TTF_ALWAYSTIP))
- CancelToolTips(TRUE);
- }
-
- return 0;
- }
-
- void CWnd::OnSysColorChange()
- {
- CWinApp* pApp = AfxGetApp();
- if (pApp != NULL && pApp->m_pMainWnd == this)
- {
- // recolor global brushes used by control bars
- afxData.UpdateSysColors();
- }
-
- #ifndef _AFX_NO_CTL3D_SUPPORT
- if (!afxContextIsDLL)
- {
- if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this)
- {
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- // allow CTL3D32.DLL to be notified of color change
- if (pCtl3dState->m_pfnColorChange != NULL)
- (*pCtl3dState->m_pfnColorChange)();
- }
- }
- #endif
-
- // forward this message to all other child windows
- if (!(GetStyle() & WS_CHILD))
- SendMessageToDescendants(WM_SYSCOLORCHANGE, 0, 0L, TRUE, TRUE);
-
- Default();
- }
-
- BOOL _afxGotScrollLines;
-
- void CWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
- {
- UNUSED_ALWAYS(uFlags);
- UNUSED_ALWAYS(lpszSection);
-
- #ifndef _AFX_NO_CTL3D_SUPPORT
- if (!afxContextIsDLL)
- {
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- // allow CTL3D32.DLL to update from WIN.INI settings
- if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
- pCtl3dState->m_pfnWinIniChange != NULL)
- {
- (*pCtl3dState->m_pfnWinIniChange)();
- }
- }
- #endif
- // force refresh of settings that we cache
- _afxGotScrollLines = FALSE;
-
- CWnd::OnDisplayChange(0, 0); // to update system metrics, etc.
- }
-
- void CWnd::OnWinIniChange(LPCTSTR lpszSection)
- {
- UNUSED_ALWAYS(lpszSection);
-
- // this function is provided for backward compatibility only
- // it is called only in Windows NT 3.51; in Windows 95 and
- // Windows NT, OnSettingChange is called
-
- #ifndef _AFX_NO_CTL3D_SUPPORT
- if (!afxContextIsDLL)
- {
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- // allow CTL3D32.DLL to update from WIN.INI settings
- if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
- pCtl3dState->m_pfnWinIniChange != NULL)
- {
- (*pCtl3dState->m_pfnWinIniChange)();
- }
- }
- #endif
-
- CWnd::OnDisplayChange(0, 0); // to update system metrics, etc.
- }
-
- void CWnd::OnDevModeChange(LPTSTR lpDeviceName)
- {
- CWinApp* pApp = AfxGetApp();
- if (pApp != NULL && pApp->m_pMainWnd == this)
- pApp->DevModeChange(lpDeviceName);
-
- // forward this message to all other child windows
- if (!(GetStyle() & WS_CHILD))
- {
- const MSG* pMsg = GetCurrentMessage();
- SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
- TRUE, TRUE);
- }
- }
-
- BOOL CWnd::OnHelpInfo(HELPINFO* /*pHelpInfo*/)
- {
- if (!(GetStyle() & WS_CHILD))
- {
- CWnd* pMainWnd = AfxGetMainWnd();
- if (pMainWnd != NULL &&
- GetKeyState(VK_SHIFT) >= 0 &&
- GetKeyState(VK_CONTROL) >= 0 &&
- GetKeyState(VK_MENU) >= 0)
- {
- pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
- return TRUE;
- }
- }
- return Default();
- }
-
- LRESULT CWnd::OnDisplayChange(WPARAM, LPARAM)
- {
- // update metrics if this window is the main window
- if (AfxGetMainWnd() == this)
- {
- // update any system metrics cache
- afxData.UpdateSysMetrics();
- }
-
- // forward this message to all other child windows
- if (!(GetStyle() & WS_CHILD))
- {
- const MSG* pMsg = GetCurrentMessage();
- SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
- TRUE, TRUE);
- }
-
- return Default();
- }
-
- LRESULT CWnd::OnDragList(WPARAM, LPARAM lParam)
- {
- LPDRAGLISTINFO lpInfo = (LPDRAGLISTINFO)lParam;
- ASSERT(lpInfo != NULL);
-
- LRESULT lResult;
- if (ReflectLastMsg(lpInfo->hWnd, &lResult))
- return (int)lResult; // eat it
-
- // not handled - do default
- return (int)Default();
- }
-
- void CWnd::OnHScroll(UINT, UINT, CScrollBar* pScrollBar)
- {
- if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
- return; // eat it
-
- Default();
- }
-
- void CWnd::OnVScroll(UINT, UINT, CScrollBar* pScrollBar)
- {
- if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
- return; // eat it
-
- Default();
- }
-
- void CWnd::OnEnterIdle(UINT /*nWhy*/, CWnd* /*pWho*/)
- {
- // WINBUG: In some OLE inplace active scenarios, OLE will post a
- // message instead of sending it. This causes so many WM_ENTERIDLE
- // messages to be sent that tasks running in the background stop
- // running. By dispatching the pending WM_ENTERIDLE messages
- // when the first one is received, we trick Windows into thinking
- // that only one was really sent and dispatched.
- {
- MSG msg;
- while (PeekMessage(&msg, NULL, WM_ENTERIDLE, WM_ENTERIDLE, PM_REMOVE))
- DispatchMessage(&msg);
- }
-
- Default();
- }
-
- HBRUSH CWnd::OnCtlColor(CDC*, CWnd* pWnd, UINT)
- {
- ASSERT(pWnd != NULL && pWnd->m_hWnd != NULL);
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (HBRUSH)lResult; // eat it
- return (HBRUSH)Default();
- }
-
- #ifndef _AFX_NO_GRAYDLG_SUPPORT
- // special helper for Gray OnCtlColor routines
- HBRUSH CWnd::OnGrayCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (HBRUSH)lResult; // eat it
-
- _AFX_WIN_STATE* pWinState = _afxWinState;
- if (!GrayCtlColor(pDC->m_hDC, pWnd->GetSafeHwnd(), nCtlColor,
- pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
- return (HBRUSH)Default();
- return pWinState->m_hDlgBkBrush;
- }
- #endif //!_AFX_NO_GRAYDLG_SUPPORT
-
- // implementation of OnCtlColor for default gray backgrounds
- // (works for any window containing controls)
- // return value of FALSE means caller must call DefWindowProc's default
- // TRUE means that 'hbrGray' will be used and the appropriate text
- // ('clrText') and background colors are set.
- BOOL PASCAL CWnd::GrayCtlColor(HDC hDC, HWND hWnd, UINT nCtlColor,
- HBRUSH hbrGray, COLORREF clrText)
- {
- if (hDC == NULL)
- {
- // sometimes Win32 passes a NULL hDC in the WM_CTLCOLOR message.
- TRACE0("Warning: hDC is NULL in CWnd::GrayCtlColor; WM_CTLCOLOR not processed.\n");
- return FALSE;
- }
-
- if (hbrGray == NULL ||
- nCtlColor == CTLCOLOR_EDIT || nCtlColor == CTLCOLOR_MSGBOX ||
- nCtlColor == CTLCOLOR_SCROLLBAR)
- {
- return FALSE;
- }
-
- if (nCtlColor == CTLCOLOR_LISTBOX)
- {
- // only handle requests to draw the space between edit and drop button
- // in a drop-down combo (not a drop-down list)
- if (!_AfxIsComboBoxControl(hWnd, (UINT)CBS_DROPDOWN))
- return FALSE;
- }
-
- // set background color and return handle to brush
- LOGBRUSH logbrush;
- VERIFY(::GetObject(hbrGray, sizeof(LOGBRUSH), (LPVOID)&logbrush));
- ::SetBkColor(hDC, logbrush.lbColor);
- if (clrText == (COLORREF)-1)
- clrText = ::GetSysColor(COLOR_WINDOWTEXT); // normal text
- ::SetTextColor(hDC, clrText);
- return TRUE;
- }
-
- #ifndef _AFX_NO_CTL3D_SUPPORT
- LRESULT CWnd::OnQuery3dControls(WPARAM, LPARAM)
- {
- // This is message handler is not in CWnd's message map.
- // It is placed in various derived classes' message maps to enable
- // 3D controls for specific window types only.
-
- return 0xFFFF; // CTL3D_ALL
- }
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // 'dialog data' support
-
- BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
- {
- ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?
-
- CDataExchange dx(this, bSaveAndValidate);
-
- // prevent control notifications from being dispatched during UpdateData
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow;
- ASSERT(hWndOldLockout != m_hWnd); // must not recurse
- pThreadState->m_hLockoutNotifyWindow = m_hWnd;
-
- BOOL bOK = FALSE; // assume failure
- TRY
- {
- DoDataExchange(&dx);
- bOK = TRUE; // it worked
- }
- CATCH(CUserException, e)
- {
- // validation failed - user already alerted, fall through
- ASSERT(!bOK);
- // Note: DELETE_EXCEPTION_(e) not required
- }
- AND_CATCH_ALL(e)
- {
- // validation failed due to OOM or other resource failure
- e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE);
- ASSERT(!bOK);
- DELETE_EXCEPTION(e);
- }
- END_CATCH_ALL
-
- pThreadState->m_hLockoutNotifyWindow = hWndOldLockout;
- return bOK;
- }
-
- CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
- {
- ASSERT_VALID(pDlgWnd);
- m_bSaveAndValidate = bSaveAndValidate;
- m_pDlgWnd = pDlgWnd;
- m_hWndLastControl = NULL;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Centering dialog support (works for any non-child window)
-
- void CWnd::CenterWindow(CWnd* pAlternateOwner)
- {
- ASSERT(::IsWindow(m_hWnd));
-
- // determine owner window to center against
- DWORD dwStyle = GetStyle();
- HWND hWndCenter = pAlternateOwner->GetSafeHwnd();
- if (pAlternateOwner == NULL)
- {
- if (dwStyle & WS_CHILD)
- hWndCenter = ::GetParent(m_hWnd);
- else
- hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
- if (hWndCenter != NULL)
- {
- // let parent determine alternate center window
- HWND hWndTemp =
- (HWND)::SendMessage(hWndCenter, WM_QUERYCENTERWND, 0, 0);
- if (hWndTemp != NULL)
- hWndCenter = hWndTemp;
- }
- }
-
- // get coordinates of the window relative to its parent
- CRect rcDlg;
- GetWindowRect(&rcDlg);
- CRect rcArea;
- CRect rcCenter;
- HWND hWndParent;
- if (!(dwStyle & WS_CHILD))
- {
- // don't center against invisible or minimized windows
- if (hWndCenter != NULL)
- {
- DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
- if (!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
- hWndCenter = NULL;
- }
-
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
-
- // center within appropriate monitor coordinates
- if (hWndCenter == NULL)
- {
- HWND hwDefault = AfxGetMainWnd()->GetSafeHwnd();
-
- GetMonitorInfo(
- MonitorFromWindow(hwDefault, MONITOR_DEFAULTTOPRIMARY), &mi);
- rcCenter = mi.rcWork;
- rcArea = mi.rcWork;
- }
- else
- {
- ::GetWindowRect(hWndCenter, &rcCenter);
- GetMonitorInfo(
- MonitorFromWindow(hWndCenter, MONITOR_DEFAULTTONEAREST), &mi);
- rcArea = mi.rcWork;
- }
- }
- else
- {
- // center within parent client coordinates
- hWndParent = ::GetParent(m_hWnd);
- ASSERT(::IsWindow(hWndParent));
-
- ::GetClientRect(hWndParent, &rcArea);
- ASSERT(::IsWindow(hWndCenter));
- ::GetClientRect(hWndCenter, &rcCenter);
- ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
- }
-
- // find dialog's upper left based on rcCenter
- int xLeft = (rcCenter.left + rcCenter.right) / 2 - rcDlg.Width() / 2;
- int yTop = (rcCenter.top + rcCenter.bottom) / 2 - rcDlg.Height() / 2;
-
- // if the dialog is outside the screen, move it inside
- if (xLeft < rcArea.left)
- xLeft = rcArea.left;
- else if (xLeft + rcDlg.Width() > rcArea.right)
- xLeft = rcArea.right - rcDlg.Width();
-
- if (yTop < rcArea.top)
- yTop = rcArea.top;
- else if (yTop + rcDlg.Height() > rcArea.bottom)
- yTop = rcArea.bottom - rcDlg.Height();
-
- // map screen coordinates to child coordinates
- SetWindowPos(NULL, xLeft, yTop, -1, -1,
- SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
- }
-
- BOOL CWnd::CheckAutoCenter()
- {
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Dialog initialization support
-
- BOOL CWnd::ExecuteDlgInit(LPCTSTR lpszResourceName)
- {
- // find resource handle
- LPVOID lpResource = NULL;
- HGLOBAL hResource = NULL;
- if (lpszResourceName != NULL)
- {
- HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DLGINIT);
- HRSRC hDlgInit = ::FindResource(hInst, lpszResourceName, RT_DLGINIT);
- if (hDlgInit != NULL)
- {
- // load it
- hResource = LoadResource(hInst, hDlgInit);
- if (hResource == NULL)
- return FALSE;
- // lock it
- lpResource = LockResource(hResource);
- ASSERT(lpResource != NULL);
- }
- }
-
- // execute it
- BOOL bResult = ExecuteDlgInit(lpResource);
-
- // cleanup
- if (lpResource != NULL && hResource != NULL)
- {
- UnlockResource(hResource);
- FreeResource(hResource);
- }
- return bResult;
- }
-
- BOOL CWnd::ExecuteDlgInit(LPVOID lpResource)
- {
- BOOL bSuccess = TRUE;
- if (lpResource != NULL)
- {
- UNALIGNED WORD* lpnRes = (WORD*)lpResource;
- while (bSuccess && *lpnRes != 0)
- {
- WORD nIDC = *lpnRes++;
- WORD nMsg = *lpnRes++;
- DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
-
- // In Win32 the WM_ messages have changed. They have
- // to be translated from the 32-bit values to 16-bit
- // values here.
-
- #define WIN16_LB_ADDSTRING 0x0401
- #define WIN16_CB_ADDSTRING 0x0403
- #define AFX_CB_ADDSTRING 0x1234
-
- // unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
- if (nMsg == AFX_CB_ADDSTRING)
- nMsg = CBEM_INSERTITEM;
- else if (nMsg == WIN16_LB_ADDSTRING)
- nMsg = LB_ADDSTRING;
- else if (nMsg == WIN16_CB_ADDSTRING)
- nMsg = CB_ADDSTRING;
-
- // check for invalid/unknown message types
- #ifdef _AFX_NO_OCC_SUPPORT
- ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
- nMsg == CBEM_INSERTITEM);
- #else
- ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
- nMsg == CBEM_INSERTITEM ||
- nMsg == WM_OCC_LOADFROMSTREAM ||
- nMsg == WM_OCC_LOADFROMSTREAM_EX ||
- nMsg == WM_OCC_LOADFROMSTORAGE ||
- nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
- nMsg == WM_OCC_INITNEW);
- #endif
-
- #ifdef _DEBUG
- // For AddStrings, the count must exactly delimit the
- // string, including the NULL termination. This check
- // will not catch all mal-formed ADDSTRINGs, but will
- // catch some.
- if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING || nMsg == CBEM_INSERTITEM)
- ASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
- #endif
-
- if (nMsg == CBEM_INSERTITEM)
- {
- USES_CONVERSION;
- COMBOBOXEXITEM item;
- item.mask = CBEIF_TEXT;
- item.iItem = -1;
- item.pszText = A2T(LPSTR(lpnRes));
-
- if (::SendDlgItemMessage(m_hWnd, nIDC, nMsg, 0, (LPARAM) &item) == -1)
- bSuccess = FALSE;
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
- #endif // !_AFX_NO_OCC_SUPPORT
- {
- // List/Combobox returns -1 for error
- if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LPARAM) lpnRes) == -1)
- bSuccess = FALSE;
- }
-
-
- // skip past data
- lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
- }
- }
-
- // send update message to all controls after all other siblings loaded
- if (bSuccess)
- SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
-
- return bSuccess;
- }
-
- void CWnd::UpdateDialogControls(CCmdTarget* pTarget, BOOL bDisableIfNoHndler)
- {
- CCmdUI state;
- CWnd wndTemp; // very temporary window just for CmdUI update
-
- // walk all the kids - assume the IDs are for buttons
- for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- // send to buttons
- wndTemp.m_hWnd = hWndChild; // quick and dirty attach
- state.m_nID = _AfxGetDlgCtrlID(hWndChild);
- state.m_pOther = &wndTemp;
-
- // check for reflect handlers in the child window
- CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
- if (pWnd != NULL)
- {
- // call it directly to disable any routing
- if (pWnd->CWnd::OnCmdMsg(0, MAKELONG(-1,
- WM_COMMAND+WM_REFLECT_BASE), &state, NULL))
- continue;
- }
-
- // check for handlers in the parent window
- if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
- continue;
-
- // determine whether to disable when no handler exists
- BOOL bDisableTemp = bDisableIfNoHndler;
- if (bDisableTemp)
- {
- if ((wndTemp.SendMessage(WM_GETDLGCODE) & DLGC_BUTTON) == 0)
- {
- // non-button controls don't get automagically disabled
- bDisableTemp = FALSE;
- }
- else
- {
- // only certain button controls get automagically disabled
- UINT nStyle = (UINT)(wndTemp.GetStyle() & 0x0F);
- if (nStyle == (UINT)BS_AUTOCHECKBOX ||
- nStyle == (UINT)BS_AUTO3STATE ||
- nStyle == (UINT)BS_GROUPBOX ||
- nStyle == (UINT)BS_AUTORADIOBUTTON)
- {
- bDisableTemp = FALSE;
- }
- }
- }
- // check for handlers in the target (owner)
- state.DoUpdate(pTarget, bDisableTemp);
- }
- wndTemp.m_hWnd = NULL; // quick and dirty detach
- }
-
- BOOL CWnd::PreTranslateInput(LPMSG lpMsg)
- {
- ASSERT(::IsWindow(m_hWnd));
-
- // don't translate non-input events
- if ((lpMsg->message < WM_KEYFIRST || lpMsg->message > WM_KEYLAST) &&
- (lpMsg->message < WM_MOUSEFIRST || lpMsg->message > WM_MOUSELAST))
- return FALSE;
-
- return IsDialogMessage(lpMsg);
- }
-
- int CWnd::RunModalLoop(DWORD dwFlags)
- {
- ASSERT(::IsWindow(m_hWnd)); // window must be created
- ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
-
- // for tracking the idle time state
- BOOL bIdle = TRUE;
- LONG lIdleCount = 0;
- BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
- HWND hWndParent = ::GetParent(m_hWnd);
- m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
- MSG* pMsg = &AfxGetThread()->m_msgCur;
-
- // acquire and dispatch messages until the modal state is done
- for (;;)
- {
- ASSERT(ContinueModal());
-
- // phase1: check to see if we can do idle work
- while (bIdle &&
- !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
- {
- ASSERT(ContinueModal());
-
- // show the dialog when the message queue goes idle
- if (bShowIdle)
- {
- ShowWindow(SW_SHOWNORMAL);
- UpdateWindow();
- bShowIdle = FALSE;
- }
-
- // call OnIdle while in bIdle state
- if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
- {
- // send WM_ENTERIDLE to the parent
- ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
- }
- if ((dwFlags & MLF_NOKICKIDLE) ||
- !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
- {
- // stop idle processing next time
- bIdle = FALSE;
- }
- }
-
- // phase2: pump messages while available
- do
- {
- ASSERT(ContinueModal());
-
- // pump message, but quit on WM_QUIT
- if (!AfxGetThread()->PumpMessage())
- {
- AfxPostQuitMessage(0);
- return -1;
- }
-
- // show the window when certain special messages rec'd
- if (bShowIdle &&
- (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
- {
- ShowWindow(SW_SHOWNORMAL);
- UpdateWindow();
- bShowIdle = FALSE;
- }
-
- if (!ContinueModal())
- goto ExitModal;
-
- // reset "no idle" state after pumping "normal" message
- if (AfxGetThread()->IsIdleMessage(pMsg))
- {
- bIdle = TRUE;
- lIdleCount = 0;
- }
-
- } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
- }
-
- ExitModal:
- m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
- return m_nModalResult;
- }
-
- BOOL CWnd::ContinueModal()
- {
- return m_nFlags & WF_CONTINUEMODAL;
- }
-
- void CWnd::EndModalLoop(int nResult)
- {
- ASSERT(::IsWindow(m_hWnd));
-
- // this result will be returned from CWnd::RunModalLoop
- m_nModalResult = nResult;
-
- // make sure a message goes through to exit the modal loop
- if (m_nFlags & WF_CONTINUEMODAL)
- {
- m_nFlags &= ~WF_CONTINUEMODAL;
- PostMessage(WM_NULL);
- }
- }
-
- #ifndef _AFX_NO_OCC_SUPPORT
-
- BOOL CWnd::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO*)
- {
- ASSERT(FALSE); // this class doesn't support dialog creation
- return FALSE;
- }
-
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // Standard init called by WinMain
-
- AFX_STATIC BOOL AFXAPI _AfxRegisterWithIcon(WNDCLASS* pWndCls,
- LPCTSTR lpszClassName, UINT nIDIcon)
- {
- pWndCls->lpszClassName = lpszClassName;
- HINSTANCE hInst = AfxFindResourceHandle(
- MAKEINTRESOURCE(nIDIcon), RT_GROUP_ICON);
- if ((pWndCls->hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDIcon))) == NULL)
- {
- // use default icon
- pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
- }
- return AfxRegisterClass(pWndCls);
- }
-
- LONG AFXAPI _AfxInitCommonControls(LPINITCOMMONCONTROLSEX lpInitCtrls, LONG fToRegister)
- {
- ASSERT(fToRegister != 0);
-
- #ifndef _AFXDLL
- HINSTANCE hInstBefore = ::GetModuleHandleA("COMCTL32.DLL");
- #endif
-
- // load the COMCTL32.DLL library because it may not be loaded yet (delayload)
- HINSTANCE hInst = ::LoadLibraryA("COMCTL32.DLL");
- if (hInst == NULL)
- return 0;
-
- LONG lResult = 0;
- // attempt to get/call InitCommonControlsEx
- BOOL (STDAPICALLTYPE* pfnInit)(LPINITCOMMONCONTROLSEX lpInitCtrls) = NULL;
- (FARPROC&)pfnInit = ::GetProcAddress(hInst, "InitCommonControlsEx");
- if (pfnInit == NULL)
- {
- // not there, so call InitCommonControls if possible
- if ((fToRegister & AFX_WIN95CTLS_MASK) == fToRegister)
- {
- InitCommonControls();
- lResult = AFX_WIN95CTLS_MASK;
- }
- }
- #ifdef _AFXDLL
- else if (InitCommonControlsEx(lpInitCtrls))
- #else
- else if ((*pfnInit)(lpInitCtrls))
- #endif
- {
- // InitCommonControlsEx was successful so return the full mask
- lResult = fToRegister;
- #ifndef _AFXDLL
- if (hInstBefore == NULL)
- {
- // In the case that we are statically linked and COMCTL32.DLL
- // was not loaded before we loaded it with LoadLibrary in this
- // function, that indicates that the calling module is linked
- // with /delayload:comctl32.dll, and in this case we have to do
- // something to cause COMCTL32.DLL to stay loaded. The only thing
- // we can do is to call a COMCTL32.DLL API which will cause the
- // CRT's delay load helpers to get called and will cause the DLL
- // to get loaded. We choose to call InitCommonControls because
- // it exists in the original COMCTL32.DLL and it doesn't really
- // do any harm to call it, except for the time it takes to
- // register the set of original Windows 95 classes.
- // If this isn't done our FreeLibrary call below will cause
- // COMCTL32.DLL to go away, undoing the registration.
- InitCommonControls();
- lResult |= AFX_WIN95CTLS_MASK;
- }
- #endif
- }
-
- // free the library reference and return the result
- FreeLibrary(hInst);
- return lResult;
- }
-
- BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
- {
- // mask off all classes that are already registered
- AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
- fToRegister &= ~pModuleState->m_fRegisteredClasses;
- if (fToRegister == 0)
- return TRUE;
-
- LONG fRegisteredClasses = 0;
-
- // common initialization
- WNDCLASS wndcls;
- memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
- wndcls.lpfnWndProc = DefWindowProc;
- wndcls.hInstance = AfxGetInstanceHandle();
- wndcls.hCursor = afxData.hcurArrow;
-
- INITCOMMONCONTROLSEX init;
- init.dwSize = sizeof(init);
-
- // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
- if (fToRegister & AFX_WND_REG)
- {
- // Child windows - no brush, no icon, safest default class styles
- wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.lpszClassName = _afxWnd;
- if (AfxRegisterClass(&wndcls))
- fRegisteredClasses |= AFX_WND_REG;
- }
- if (fToRegister & AFX_WNDOLECONTROL_REG)
- {
- // OLE Control windows - use parent DC for speed
- wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.lpszClassName = _afxWndOleControl;
- if (AfxRegisterClass(&wndcls))
- fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
- }
- if (fToRegister & AFX_WNDCONTROLBAR_REG)
- {
- // Control bar windows
- wndcls.style = 0; // control bars don't handle double click
- wndcls.lpszClassName = _afxWndControlBar;
- wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- if (AfxRegisterClass(&wndcls))
- fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
- }
- if (fToRegister & AFX_WNDMDIFRAME_REG)
- {
- // MDI Frame window (also used for splitter window)
- wndcls.style = CS_DBLCLKS;
- wndcls.hbrBackground = NULL;
- if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
- fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
- }
- if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
- {
- // SDI Frame or MDI Child windows or views - normal colors
- wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
- if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
- fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
- }
- if (fToRegister & AFX_WNDCOMMCTLS_REG)
- {
- // this flag is compatible with the old InitCommonControls() API
- init.dwICC = ICC_WIN95_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
- fToRegister &= ~AFX_WIN95CTLS_MASK;
- }
- if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)
- {
- init.dwICC = ICC_UPDOWN_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)
- {
- init.dwICC = ICC_TREEVIEW_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)
- {
- init.dwICC = ICC_TAB_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TAB_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)
- {
- init.dwICC = ICC_PROGRESS_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)
- {
- init.dwICC = ICC_LISTVIEW_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)
- {
- init.dwICC = ICC_HOTKEY_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)
- {
- init.dwICC = ICC_BAR_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)
- {
- init.dwICC = ICC_ANIMATE_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ANIMATE_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)
- {
- init.dwICC = ICC_INTERNET_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)
- {
- init.dwICC = ICC_COOL_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)
- {
- init.dwICC = ICC_USEREX_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)
- {
- init.dwICC = ICC_DATE_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);
- }
-
- // save new state of registered controls
- pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
-
- // special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG
- if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)
- {
- pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
- fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
- }
-
- // must have registered at least as mamy classes as requested
- return (fToRegister & fRegisteredClasses) == fToRegister;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CFrameWnd (here for library granularity)
-
- BOOL CWnd::IsFrameWnd() const
- {
- return FALSE;
- }
-
- BOOL CFrameWnd::IsFrameWnd() const
- {
- return TRUE;
- }
-
- BOOL CFrameWnd::IsTracking() const
- {
- return m_nIDTracking != 0 &&
- m_nIDTracking != AFX_IDS_HELPMODEMESSAGE &&
- m_nIDTracking != AFX_IDS_IDLEMESSAGE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CTL3D support
-
- #ifndef _AFX_NO_CTL3D_SUPPORT
-
- // Use SubclassCtl3d to add CTL3D support to an already subclassed control
- // Usually only necessary if the control does not have one of the standard
- // Windows class names.
- BOOL CWnd::SubclassCtl3d(int nControlType)
- {
- ASSERT(!afxContextIsDLL); // Should only be called by apps
-
- if (afxContextIsDLL)
- return FALSE;
-
- ASSERT(m_hWnd != NULL);
-
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- if (nControlType == -1)
- {
- if (pCtl3dState->m_pfnSubclassCtl != NULL)
- return (*pCtl3dState->m_pfnSubclassCtl)(m_hWnd);
- }
- else
- {
- if (pCtl3dState->m_pfnSubclassCtlEx != NULL)
- return (*pCtl3dState->m_pfnSubclassCtlEx)(m_hWnd, nControlType);
- }
- return FALSE;
- }
-
- // Use SubclassDlg3d to add CTL3D support to an entire window.
- // Any windows created on the window will be automatically subclassed.
- BOOL CWnd::SubclassDlg3d(DWORD dwMask)
- {
- ASSERT(!afxContextIsDLL); // Should only be called by apps
-
- if (afxContextIsDLL)
- return FALSE;
-
- ASSERT(m_hWnd != NULL);
-
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- if (pCtl3dState->m_pfnSubclassDlgEx != NULL)
- return pCtl3dState->m_pfnSubclassDlgEx(m_hWnd, dwMask);
- return FALSE;
- }
-
- #endif //!_AFX_NO_CTL3D_SUPPORT
-
- //this function can't be inlined because of _afxShell
- void CWnd::DragAcceptFiles(BOOL bAccept)
- {
- ASSERT(::IsWindow(m_hWnd));
- ::DragAcceptFiles(m_hWnd, bAccept);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Extra CWnd support for dynamic subclassing of controls
-
- BOOL CWnd::SubclassWindow(HWND hWnd)
- {
- if (!Attach(hWnd))
- return FALSE;
-
- // allow any other subclassing to occur
- PreSubclassWindow();
-
- // now hook into the AFX WndProc
- WNDPROC* lplpfn = GetSuperWndProcAddr();
- WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)AfxGetAfxWndProc());
- ASSERT(oldWndProc != (WNDPROC)AfxGetAfxWndProc());
-
- if (*lplpfn == NULL)
- *lplpfn = oldWndProc; // the first control of that type created
- #ifdef _DEBUG
- else if (*lplpfn != oldWndProc)
- {
- TRACE0("Error: Trying to use SubclassWindow with incorrect CWnd\n");
- TRACE0("\tderived class.\n");
- TRACE3("\thWnd = $%04X (nIDC=$%04X) is not a %hs.\n", (UINT)hWnd,
- _AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);
- ASSERT(FALSE);
- // undo the subclassing if continuing after assert
- ::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
- }
- #endif
-
- return TRUE;
- }
-
- BOOL CWnd::SubclassDlgItem(UINT nID, CWnd* pParent)
- {
- ASSERT(pParent != NULL);
- ASSERT(::IsWindow(pParent->m_hWnd));
-
- // check for normal dialog control first
- HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID);
- if (hWndControl != NULL)
- return SubclassWindow(hWndControl);
-
- #ifndef _AFX_NO_OCC_SUPPORT
- if (pParent->m_pCtrlCont != NULL)
- {
- // normal dialog control not found
- COleControlSite* pSite = pParent->m_pCtrlCont->FindItem(nID);
- if (pSite != NULL)
- {
- ASSERT(pSite->m_hWnd != NULL);
- VERIFY(SubclassWindow(pSite->m_hWnd));
-
- #ifndef _AFX_NO_OCC_SUPPORT
- // If the control has reparented itself (e.g., invisible control),
- // make sure that the CWnd gets properly wired to its control site.
- if (pParent->m_hWnd != ::GetParent(pSite->m_hWnd))
- AttachControlSite(pParent);
- #endif //!_AFX_NO_OCC_SUPPORT
-
- return TRUE;
- }
- }
- #endif
-
- return FALSE; // control not found
- }
-
- HWND CWnd::UnsubclassWindow()
- {
- ASSERT(::IsWindow(m_hWnd));
-
- // set WNDPROC back to original value
- WNDPROC* lplpfn = GetSuperWndProcAddr();
- SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)*lplpfn);
- *lplpfn = NULL;
-
- // and Detach the HWND from the CWnd object
- return Detach();
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // out-of-line inlines for binary compatibility
-
- #ifdef _AFXDLL
- #ifndef _DEBUG
-
- CPoint::CPoint(POINT initPt)
- { *(POINT*)this = initPt; }
-
- #endif
- #endif
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- IMPLEMENT_DYNCREATE(CWnd, CCmdTarget)
-
- IMPLEMENT_DYNCREATE(CTempWnd, CWnd);
-
- #pragma warning(disable: 4074)
- #pragma init_seg(compiler)
- IMPLEMENT_FIXED_ALLOC(CTempWnd, 64);
-
- /////////////////////////////////////////////////////////////////////////////
-