📄 wincore.cpp
字号:
#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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -