📄 winfrm.cpp
字号:
CWnd* pParentWnd,
LPCTSTR lpszMenuName,
DWORD dwExStyle,
CCreateContext* pContext)
{
HMENU hMenu = NULL;
if (lpszMenuName != NULL)
{
// load in a menu that will get destroyed when window gets destroyed
HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);
if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
{
TRACE0("Warning: failed to load menu for CFrameWnd.\n");
PostNcDestroy(); // perhaps delete the C++ object
return FALSE;
}
}
m_strTitle = lpszWindowName; // save title for later
if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
{
TRACE0("Warning: failed to create CFrameWnd.\n");
if (hMenu != NULL)
DestroyMenu(hMenu);
return FALSE;
}
return TRUE;
}
CWnd* CFrameWnd::CreateView(CCreateContext* pContext, UINT nID)
{
ASSERT(m_hWnd != NULL);
ASSERT(::IsWindow(m_hWnd));
ASSERT(pContext != NULL);
ASSERT(pContext->m_pNewViewClass != NULL);
// Note: can be a CWnd with PostNcDestroy self cleanup
CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
if (pView == NULL)
{
TRACE1("Warning: Dynamic create of view type %hs failed.\n",
pContext->m_pNewViewClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CWnd, pView);
// views are always created with a border!
if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0,0,0,0), this, nID, pContext))
{
TRACE0("Warning: could not create view for frame.\n");
return NULL; // can't continue without a view
}
if (afxData.bWin4 && (pView->GetExStyle() & WS_EX_CLIENTEDGE))
{
// remove the 3d style from the frame, since the view is
// providing it.
// make sure to recalc the non-client area
ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
}
return pView;
}
BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
{
// default create client will create a view if asked for it
if (pContext != NULL && pContext->m_pNewViewClass != NULL)
{
if (CreateView(pContext, AFX_IDW_PANE_FIRST) == NULL)
return FALSE;
}
return TRUE;
}
int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs)
{
CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;
return OnCreateHelper(lpcs, pContext);
}
int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
if (CWnd::OnCreate(lpcs) == -1)
return -1;
// create special children first
if (!OnCreateClient(lpcs, pContext))
{
TRACE0("Failed to create client pane/view for frame.\n");
return -1;
}
// post message for initial message string
PostMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);
// make sure the child windows have been properly sized
RecalcLayout();
return 0; // create ok
}
LPCTSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle, UINT nIDResource)
{
ASSERT_VALID_IDR(nIDResource);
HINSTANCE hInst = AfxFindResourceHandle(
MAKEINTRESOURCE(nIDResource), RT_GROUP_ICON);
HICON hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource));
if (hIcon != NULL)
{
CREATESTRUCT cs;
memset(&cs, 0, sizeof(CREATESTRUCT));
cs.style = dwDefaultStyle;
PreCreateWindow(cs);
// will fill lpszClassName with default WNDCLASS name
// ignore instance handle from PreCreateWindow.
WNDCLASS wndcls;
if (cs.lpszClass != NULL &&
GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndcls) &&
wndcls.hIcon != hIcon)
{
// register a very similar WNDCLASS
return AfxRegisterWndClass(wndcls.style,
wndcls.hCursor, wndcls.hbrBackground, hIcon);
}
}
return NULL; // just use the default
}
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
{
// only do this once
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
CString strFullString;
if (strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
// attempt to create the window
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
LPCTSTR lpszTitle = m_strTitle;
if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
{
return FALSE; // will self destruct on failure normally
}
// save the default menu handle
ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd);
// load accelerator resource
LoadAccelTable(MAKEINTRESOURCE(nIDResource));
if (pContext == NULL) // send initial update
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
return TRUE;
}
void CFrameWnd::OnUpdateFrameMenu(HMENU hMenuAlt)
{
if (hMenuAlt == NULL)
{
// attempt to get default menu from document
CDocument* pDoc = GetActiveDocument();
if (pDoc != NULL)
hMenuAlt = pDoc->GetDefaultMenu();
// use default menu stored in frame if none from document
if (hMenuAlt == NULL)
hMenuAlt = m_hMenuDefault;
}
// finally, set the menu
::SetMenu(m_hWnd, hMenuAlt);
}
void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible)
{
// if the frame does not have an active view, set to first pane
CView* pView = NULL;
if (GetActiveView() == NULL)
{
CWnd* pWnd = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))
{
pView = (CView*)pWnd;
SetActiveView(pView, FALSE);
}
}
if (bMakeVisible)
{
// send initial update to all views (and other controls) in the frame
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
// give view a chance to save the focus (CFormView needs this)
if (pView != NULL)
pView->OnActivateFrame(WA_INACTIVE, this);
// finally, activate the frame
// (send the default show command unless the main desktop window)
int nCmdShow = -1; // default
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
nCmdShow = pApp->m_nCmdShow; // use the parameter from WinMain
pApp->m_nCmdShow = -1; // set to default after first time
}
ActivateFrame(nCmdShow);
if (pView != NULL)
pView->OnActivateView(TRUE, pView, pView);
}
// update frame counts and frame title (may already have been visible)
if (pDoc != NULL)
pDoc->UpdateFrameCounts();
OnUpdateFrameTitle(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd closing down
void CFrameWnd::OnClose()
{
if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
return;
// Note: only queries the active document
CDocument* pDocument = GetActiveDocument();
if (pDocument != NULL && !pDocument->CanCloseFrame(this))
{
// document can't close right now -- don't close it
return;
}
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
// attempt to save all documents
if (pDocument == NULL && !pApp->SaveAllModified())
return; // don't close it
// hide the application's windows before closing all the documents
pApp->HideApplication();
// close all documents first
pApp->CloseAllDocuments(FALSE);
// don't exit if there are outstanding component objects
if (!AfxOleCanExitApp())
{
// take user out of control of the app
AfxOleSetUserCtrl(FALSE);
// don't destroy the main window and close down just yet
// (there are outstanding component (OLE) objects)
return;
}
// there are cases where destroying the documents may destroy the
// main window of the application.
if (!afxContextIsDLL && pApp->m_pMainWnd == NULL)
{
AfxPostQuitMessage(0);
return;
}
}
// detect the case that this is the last frame on the document and
// shut down with OnCloseDocument instead.
if (pDocument != NULL && pDocument->m_bAutoDelete)
{
BOOL bOtherFrame = FALSE;
POSITION pos = pDocument->GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = pDocument->GetNextView(pos);
ASSERT_VALID(pView);
if (pView->GetParentFrame() != this)
{
bOtherFrame = TRUE;
break;
}
}
if (!bOtherFrame)
{
pDocument->OnCloseDocument();
return;
}
// allow the document to cleanup before the window is destroyed
pDocument->PreCloseFrame(this);
}
// then destroy the window
DestroyWindow();
}
void CFrameWnd::OnDestroy()
{
DestroyDockBars();
// reset menu to default before final shutdown
if (m_hMenuDefault != NULL && ::GetMenu(m_hWnd) != m_hMenuDefault)
{
::SetMenu(m_hWnd, m_hMenuDefault);
ASSERT(::GetMenu(m_hWnd) == m_hMenuDefault);
}
// Automatically quit when the main window is destroyed.
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
// closing the main application window
::WinHelp(m_hWnd, NULL, HELP_QUIT, 0L);
// will call PostQuitMessage in CWnd::OnNcDestroy
}
CWnd::OnDestroy();
}
void CFrameWnd::RemoveControlBar(CControlBar *pBar)
{
POSITION pos = m_listControlBars.Find(pBar);
if (pos != NULL)
m_listControlBars.RemoveAt(pos);
}
/////////////////////////////////////////////////////////////////////////////
// CFrameWnd command/message routing
BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
CPushRoutingFrame push(this);
// pump through current view FIRST
CView* pView = GetActiveView();
if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
// then pump through frame
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
// last but not least, pump through app
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
return FALSE;
}
// Delegate scroll messages to active view as well
void CFrameWnd::OnHScroll(UINT, UINT, CScrollBar*)
{
CWnd* pActiveView = GetActiveView();
if (pActiveView != NULL)
{
const MSG* pMsg = GetCurrentMessage();
pActiveView->SendMessage(WM_HSCROLL, pMsg->wParam, pMsg->lParam);
}
}
void CFrameWnd::OnVScroll(UINT, UINT, CScrollBar*)
{
CWnd* pActiveView = GetActiveView();
if (pActiveView != NULL)
{
const MSG* pMsg = GetCurrentMessage();
pActiveView->SendMessage(WM_VSCROLL, pMsg->wParam, pMsg->lParam);
}
}
LRESULT CFrameWnd::OnActivateTopLevel(WPARAM wParam, LPARAM lParam)
{
CWnd::OnActivateTopLevel(wParam, lParam);
// exit Shift+F1 help mode on activation changes
ExitHelpMode();
#ifndef _AFX_NO_OLE_SUPPORT
// allow OnFrameWindowActivate to be sent to in-place items
if (m_pNotifyHook != NULL)
{
// activate when active and when not minimized
m_pNotifyHook->OnActivate(
LOWORD(wParam) != WA_INACTIVE && !HIWORD(wParam));
}
#endif
// deactivate current active view
if (AfxGetThread()->m_pMainWnd == this)
{
CView* pActiveView = GetActiveView();
if (pActiveView == NULL)
pActiveView = GetActiveFrame()->GetActiveView();
if (pActiveView != NULL)
pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
}
// force idle processing to update any key state indicators
PostMessage(WM_KICKIDLE);
return 0;
}
void CFrameWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CWnd::OnActivate(nState, pWndOther, bMinimized);
// get top level frame unless this is a child window
// determine if window should be active or not
CFrameWnd* pTopLevel = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
ASSERT(pTopLevel != NULL);
CWnd* pActive = (nState == WA_INACTIVE ? pWndOther : this);
BOOL bStayActive =
(pTopLevel == pActive ||
(pTopLevel == pActive->GetTopLevelFrame() &&
(pActive == pTopLevel ||
pActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE) != 0)));
pTopLevel->m_nFlags &= ~WF_STAYACTIVE;
if (bStayActive)
pTopLevel->m_nFlags |= WF_STAYACTIVE;
// sync floating windows to the new state
NotifyFloatingWindows(bStayActive ? FS_ACTIVATE : FS_DEACTIVATE);
// get active view (use active frame if no active view)
CView* pActiveView = GetActiveView();
if (pActiveView == NULL)
pActiveView = GetActiveFrame()->GetActiveView();
// when frame gets activated, re-activate current view
if (pActiveView != NULL)
{
if (nState != WA_INACTIVE && !bMinimized)
pActiveView->OnActivateView(TRUE, pActiveView, pActiveView);
// always notify the view of frame activations
pActiveView->OnActivateFrame(nState, this);
}
}
BOOL CFrameWnd::OnNcActivate(BOOL bActive)
{
// stay active if WF_STAYACTIVE bit is on
if (m_nFlags & WF_STAYACTIVE)
bActive = TRUE;
// but do not stay active if the window is disabled
if (!IsWindowEnabled())
bActive = FALSE;
// do not call the base class because it will call Default()
// and we may have changed bActive.
return (BOOL)DefWindowProc(WM_NCACTIVATE, bActive, 0L);
}
void CFrameWnd::OnSysCommand(UINT nID, LONG lParam)
{
CFrameWnd* pFrameWnd = GetTopLevelFrame();
ASSERT_VALID(pFrameWnd);
// set status bar as appropriate
UINT nItemID = (nID & 0xFFF0);
// don't interfere with system commands if not in help mode
if (pFrameWnd->m_bHelpMode)
{
switch (nItemID)
{
case SC_SIZE:
case SC_MOVE:
case SC_MINIMIZE:
case SC_MAXIMIZE:
case SC_NEXTWINDOW:
case SC_PREVWINDOW:
case SC_CLOSE:
case SC_RESTORE:
case SC_TASKLIST:
if (!SendMessage(WM_COMMANDHELP, 0,
HID_BASE_COMMAND+ID_COMMAND_FROM_SC(nItemID)))
SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
return;
}
}
// call default functionality
CWnd::OnSysCommand(nID, lParam);
}
/////////////////////////////////////////////////////////////////////////////
// default frame processing
// default drop processing will attempt to open the file
void CFrameWnd::OnDropFiles(HDROP hDropInfo)
{
SetActiveWindow(); // activate us first !
UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
CWinApp* pApp = AfxGetApp();
ASSERT(pApp != NULL);
for (UINT iFile = 0; iFile < nFiles; iFile++)
{
TCHAR szFileName[_MAX_PATH];
::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
pApp->OpenDocumentFile(szFileName);
}
::DragFinish(hDropInfo);
}
// query end session for main frame will attempt to close it all down
BOOL CFrameWnd::OnQueryEndSession()
{
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
return pApp->SaveAllModified();
return TRUE;
}
// when Windows session ends, close all documents
void CFrameWnd::OnEndSession(BOOL bEnding)
{
if (!bEnding)
return;
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
AfxOleSetUserCtrl(TRUE); // keeps from randomly shutting down
pApp->CloseAllDocuments(TRUE);
// allow application to save settings, etc.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -