📄 winfrm.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"
#include <dde.h> // for DDE execute shell requests
#ifdef AFX_CORE4_SEG
#pragma code_seg(AFX_CORE4_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// CRect for creating windows with the default position/size
const AFX_DATADEF CRect CFrameWnd::rectDefault(
CW_USEDEFAULT, CW_USEDEFAULT,
0 /* 2*CW_USEDEFAULT */, 0 /* 2*CW_USEDEFAULT */);
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd
// register for Windows 95 or Windows NT 3.51
AFX_STATIC UINT _afxMsgMouseWheel =
(((::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion()) == 4)) ||
(!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion()) == 3)))
? ::RegisterWindowMessage(MSH_MOUSEWHEEL) : 0;
BEGIN_MESSAGE_MAP(CFrameWnd, CWnd)
//{{AFX_MSG_MAP(CFrameWnd)
ON_WM_INITMENU()
ON_WM_INITMENUPOPUP()
ON_WM_MENUSELECT()
ON_MESSAGE(WM_POPMESSAGESTRING, OnPopMessageString)
ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
ON_MESSAGE(WM_HELPPROMPTADDR, OnHelpPromptAddr)
ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
ON_WM_ENTERIDLE()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_SETFOCUS()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_CLOSE()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_ACTIVATE()
ON_WM_NCACTIVATE()
ON_WM_SYSCOMMAND()
ON_WM_DROPFILES()
ON_WM_QUERYENDSESSION()
ON_WM_ENDSESSION()
ON_WM_SETCURSOR()
ON_WM_ENABLE()
// OLE palette support
ON_WM_QUERYNEWPALETTE()
ON_WM_PALETTECHANGED()
ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
// turning on and off standard frame gadgetry
ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)
ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateControlBarMenu)
ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
ON_UPDATE_COMMAND_UI(ID_VIEW_REBAR, OnUpdateControlBarMenu)
ON_COMMAND_EX(ID_VIEW_REBAR, OnBarCheck)
// turning on and off standard mode indicators
ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, OnUpdateKeyIndicator)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, OnUpdateKeyIndicator)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, OnUpdateKeyIndicator)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_KANA, OnUpdateKeyIndicator)
// standard help handling
ON_UPDATE_COMMAND_UI(ID_CONTEXT_HELP, OnUpdateContextHelp)
// toolbar "tooltip" notification
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
//}}AFX_MSG_MAP
// message handling for standard DDE commands
ON_MESSAGE(WM_DDE_INITIATE, OnDDEInitiate)
ON_MESSAGE(WM_DDE_EXECUTE, OnDDEExecute)
ON_MESSAGE(WM_DDE_TERMINATE, OnDDETerminate)
ON_REGISTERED_MESSAGE(_afxMsgMouseWheel, OnRegisteredMouseWheel)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd construction/destruction
CFrameWnd::CFrameWnd()
{
ASSERT(m_hWnd == NULL);
m_nWindow = -1; // unknown window ID
m_bAutoMenuEnable = TRUE; // auto enable on by default
m_lpfnCloseProc = NULL;
m_hMenuDefault = NULL;
m_hAccelTable = NULL;
m_nIDHelp = 0;
m_nIDTracking = 0;
m_nIDLastMessage = 0;
m_pViewActive = NULL;
m_cModalStack = 0; // initialize modality support
m_phWndDisable = NULL;
m_pNotifyHook = NULL;
m_hMenuAlt = NULL;
m_nIdleFlags = 0; // no idle work at start
m_rectBorder.SetRectEmpty();
m_bHelpMode = HELP_INACTIVE; // not in Shift+F1 help mode
m_dwPromptContext = 0;
m_pNextFrameWnd = NULL; // not in list yet
m_bInRecalcLayout = FALSE;
m_pFloatingFrameClass = NULL;
m_nShowDelay = -1; // no delay pending
AddFrameWnd();
}
CFrameWnd::~CFrameWnd()
{
RemoveFrameWnd();
if( AfxGetThreadState()->m_pRoutingFrame == this )
AfxGetThreadState()->m_pRoutingFrame = NULL;
if (m_phWndDisable != NULL)
delete[] (void*)m_phWndDisable;
}
void CFrameWnd::AddFrameWnd()
{
// hook it into the CFrameWnd list
AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
pState->m_frameList.AddHead(this);
}
void CFrameWnd::RemoveFrameWnd()
{
// remove this frame window from the list of frame windows
AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
pState->m_frameList.Remove(this);
}
/////////////////////////////////////////////////////////////////////////////
// Special processing etc
BOOL CFrameWnd::LoadAccelTable(LPCTSTR lpszResourceName)
{
ASSERT(m_hAccelTable == NULL); // only do once
ASSERT(lpszResourceName != NULL);
HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_ACCELERATOR);
m_hAccelTable = ::LoadAccelerators(hInst, lpszResourceName);
return (m_hAccelTable != NULL);
}
HACCEL CFrameWnd::GetDefaultAccelerator()
{
// use document specific accelerator table over m_hAccelTable
HACCEL hAccelTable = m_hAccelTable;
HACCEL hAccel;
CDocument* pDoc = GetActiveDocument();
if (pDoc != NULL && (hAccel = pDoc->GetDefaultAccelerator()) != NULL)
hAccelTable = hAccel;
return hAccelTable;
}
BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
{
// check for special cancel modes for combo boxes
if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
AfxCancelModes(pMsg->hwnd); // filter clicks
// allow tooltip messages to be filtered
if (CWnd::PreTranslateMessage(pMsg))
return TRUE;
#ifndef _AFX_NO_OLE_SUPPORT
// allow hook to consume message
if (m_pNotifyHook != NULL && m_pNotifyHook->OnPreTranslateMessage(pMsg))
return TRUE;
#endif
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
{
// finally, translate the message
HACCEL hAccel = GetDefaultAccelerator();
return hAccel != NULL && ::TranslateAccelerator(m_hWnd, hAccel, pMsg);
}
return FALSE;
}
void CFrameWnd::PostNcDestroy()
{
// default for frame windows is to allocate them on the heap
// the default post-cleanup is to 'delete this'.
// never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead
delete this;
}
void CFrameWnd::OnPaletteChanged(CWnd* pFocusWnd)
{
CWnd::OnPaletteChanged(pFocusWnd);
#ifndef _AFX_NO_OLE_SUPPORT
if (m_pNotifyHook != NULL)
m_pNotifyHook->OnPaletteChanged(pFocusWnd);
#endif
}
BOOL CFrameWnd::OnQueryNewPalette()
{
#ifndef _AFX_NO_OLE_SUPPORT
if (m_pNotifyHook != NULL && m_pNotifyHook->OnQueryNewPalette())
return TRUE;
#endif
return CWnd::OnQueryNewPalette();
}
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd support for context sensitive help.
void CFrameWnd::ExitHelpMode()
{
// if not in help mode currently, this is a no-op
if (!m_bHelpMode)
return;
// only post new WM_EXITHELPMODE message if one doesn't already exist
// in the queue.
MSG msg;
if (!::PeekMessage(&msg, m_hWnd, WM_EXITHELPMODE, WM_EXITHELPMODE,
PM_REMOVE|PM_NOYIELD))
{
VERIFY(::PostMessage(m_hWnd, WM_EXITHELPMODE, 0, 0));
}
// release capture if this window has it
if (::GetCapture() == m_hWnd)
ReleaseCapture();
CFrameWnd* pFrameWnd = GetTopLevelFrame();
ASSERT_VALID(pFrameWnd);
pFrameWnd->m_bHelpMode = m_bHelpMode = HELP_INACTIVE;
PostMessage(WM_KICKIDLE); // trigger idle update
}
BOOL CFrameWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
CFrameWnd* pFrameWnd = GetTopLevelFrame();
ASSERT_VALID(pFrameWnd);
if (pFrameWnd->m_bHelpMode)
{
SetCursor(afxData.hcurHelp);
return TRUE;
}
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
LRESULT CFrameWnd::OnCommandHelp(WPARAM, LPARAM lParam)
{
if (lParam == 0)
{
if (IsTracking())
lParam = HID_BASE_COMMAND+m_nIDTracking;
else
lParam = HID_BASE_RESOURCE+m_nIDHelp;
}
if (lParam != 0)
{
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
pApp->WinHelp(lParam);
return TRUE;
}
return FALSE;
}
LRESULT CFrameWnd::OnHelpHitTest(WPARAM, LPARAM)
{
if (m_nIDHelp != 0)
return HID_BASE_RESOURCE+m_nIDHelp;
else
return 0;
}
BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
// return TRUE if command invocation was attempted
{
HWND hWndCtrl = (HWND)lParam;
UINT nID = LOWORD(wParam);
CFrameWnd* pFrameWnd = GetTopLevelFrame();
ASSERT_VALID(pFrameWnd);
if (pFrameWnd->m_bHelpMode && hWndCtrl == NULL &&
nID != ID_HELP && nID != ID_DEFAULT_HELP && nID != ID_CONTEXT_HELP)
{
// route as help
if (!SendMessage(WM_COMMANDHELP, 0, HID_BASE_COMMAND+nID))
SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
return TRUE;
}
// route as normal command
return CWnd::OnCommand(wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd support for modality
BOOL AFXAPI AfxIsDescendant(HWND hWndParent, HWND hWndChild)
// helper for detecting whether child descendent of parent
// (works with owned popups as well)
{
ASSERT(::IsWindow(hWndParent));
ASSERT(::IsWindow(hWndChild));
do
{
if (hWndParent == hWndChild)
return TRUE;
hWndChild = AfxGetParentOwner(hWndChild);
} while (hWndChild != NULL);
return FALSE;
}
void CFrameWnd::BeginModalState()
{
ASSERT(m_hWnd != NULL);
ASSERT(::IsWindow(m_hWnd));
// allow stacking, but don't do anything
if (++m_cModalStack > 1)
return;
// determine top-level parent, since that is the true parent of any
// modeless windows anyway...
CWnd* pParent = GetTopLevelParent();
// first count all windows that need to be disabled
UINT nCount = 0;
HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (hWnd != NULL)
{
if (::IsWindowEnabled(hWnd) &&
CWnd::FromHandlePermanent(hWnd) != NULL &&
AfxIsDescendant(pParent->m_hWnd, hWnd) &&
::SendMessage(hWnd, WM_DISABLEMODAL, 0, 0) == 0)
{
++nCount;
}
hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
}
if (nCount == 0)
return;
m_phWndDisable = new HWND[nCount+1];
// disable all windows connected to this frame (and add them to the list)
UINT nIndex = 0;
hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (hWnd != NULL)
{
if (::IsWindowEnabled(hWnd) &&
CWnd::FromHandlePermanent(hWnd) != NULL &&
AfxIsDescendant(pParent->m_hWnd, hWnd) &&
::SendMessage(hWnd, WM_DISABLEMODAL, 0, 0) == 0)
{
::EnableWindow(hWnd, FALSE);
ASSERT(nIndex < nCount);
m_phWndDisable[nIndex] = hWnd;
++nIndex;
}
hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
}
// terminate the list with a NULL
ASSERT(nIndex < nCount+1);
m_phWndDisable[nIndex] = NULL;
}
void CFrameWnd::EndModalState()
{
// pop one off the stack (don't undo modalness unless stack is down to zero)
if (m_cModalStack == 0 || --m_cModalStack > 0 || m_phWndDisable == NULL)
return;
// enable all the windows disabled by BeginModalState
ASSERT(m_phWndDisable != NULL);
UINT nIndex = 0;
while (m_phWndDisable[nIndex] != NULL)
{
ASSERT(m_phWndDisable[nIndex] != NULL);
if (::IsWindow(m_phWndDisable[nIndex]))
::EnableWindow(m_phWndDisable[nIndex], TRUE);
++nIndex;
}
delete[] (void*)m_phWndDisable;
m_phWndDisable = NULL;
}
void CFrameWnd::ShowOwnedWindows(BOOL bShow)
{
// walk through all top-level windows
HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (hWnd != NULL)
{
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL && m_hWnd != hWnd && AfxIsDescendant(m_hWnd, hWnd))
{
DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
if (!bShow && (dwStyle & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
{
::ShowWindow(hWnd, SW_HIDE);
pWnd->m_nFlags |= WF_TEMPHIDE;
}
else if (bShow && (dwStyle & (WS_VISIBLE|WS_DISABLED)) == 0 &&
(pWnd->m_nFlags & WF_TEMPHIDE))
{
::ShowWindow(hWnd, SW_SHOWNOACTIVATE);
pWnd->m_nFlags &= ~WF_TEMPHIDE;
}
}
hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
}
}
void CFrameWnd::OnEnable(BOOL bEnable)
{
if (bEnable && (m_nFlags & WF_STAYDISABLED))
{
// Work around for MAPI support. This makes sure the main window
// remains disabled even when the mail system is booting.
EnableWindow(FALSE);
::SetFocus(NULL);
return;
}
// only for top-level (and non-owned) windows
if (GetParent() != NULL)
return;
// this causes modal dialogs to be "truly modal"
if (!bEnable && !InModalState())
{
ASSERT((m_nFlags & WF_MODALDISABLE) == 0);
m_nFlags |= WF_MODALDISABLE;
BeginModalState();
}
else if (bEnable && (m_nFlags & WF_MODALDISABLE))
{
m_nFlags &= ~WF_MODALDISABLE;
EndModalState();
// cause normal focus logic to kick in
if (::GetActiveWindow() == m_hWnd)
SendMessage(WM_ACTIVATE, WA_ACTIVE);
}
// force WM_NCACTIVATE because Windows may think it is unecessary
if (bEnable && (m_nFlags & WF_STAYACTIVE))
SendMessage(WM_NCACTIVATE, TRUE);
// force WM_NCACTIVATE for floating windows too
NotifyFloatingWindows(bEnable ? FS_ENABLE : FS_DISABLE);
}
void CFrameWnd::NotifyFloatingWindows(DWORD dwFlags)
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
// get top level parent frame window first unless this is a child window
CFrameWnd* pParent = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
ASSERT(pParent != NULL);
if (dwFlags & (FS_DEACTIVATE|FS_ACTIVATE))
{
// update parent window activation state
BOOL bActivate = !(dwFlags & FS_DEACTIVATE);
BOOL bEnabled = pParent->IsWindowEnabled();
if (bActivate && bEnabled && pParent != this)
{
// Excel will try to Activate itself when it receives a
// WM_NCACTIVATE so we need to keep it from doing that here.
m_nFlags |= WF_KEEPMINIACTIVE;
pParent->SendMessage(WM_NCACTIVATE, TRUE);
m_nFlags &= ~WF_KEEPMINIACTIVE;
}
else
{
pParent->SendMessage(WM_NCACTIVATE, FALSE);
}
}
// then update the state of all floating windows owned by the parent
HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (hWnd != NULL)
{
if (AfxIsDescendant(pParent->m_hWnd, hWnd))
::SendMessage(hWnd, WM_FLOATSTATUS, dwFlags, 0);
hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
}
}
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd second phase creation
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
}
if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
cs.style |= FWS_PREFIXTITLE;
if (afxData.bWin4)
cs.dwExStyle |= WS_EX_CLIENTEDGE;
return TRUE;
}
BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -