📄 wincore.cpp
字号:
// 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)
{
CWinThread* pWinThread = AfxGetThread();
if ( pWinThread != NULL )
{
lResult = pWinThread->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
lResult);
}
else
{
TRACE0("Warning: Uncaught exception in WindowProc.\n");
lResult = 0;
}
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);
if (pWnd == NULL || pWnd->m_hWnd != hWnd)
return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -