?? tabbedmdi.cpp
字號:
#include "stdafx.h"
#include "TabbedMDI.h"
#include <afxpriv.h>
using namespace WTL4MFC;
using namespace WTL::DockSplitTab;
IMPLEMENT_DYNCREATE(CTabbedMDIFrameWnd, CDockingMDIFrameWnd)
BEGIN_MESSAGE_MAP(CTabbedMDIFrameWnd, CDockingMDIFrameWnd)
ON_UPDATE_COMMAND_UI_RANGE(ID_WINDOW_ARRANGE, ID_WINDOW_TILE_VERT, & CTabbedMDIFrameWnd::OnUpdateMDIWindowCmd)
END_MESSAGE_MAP()
void CTabbedMDIFrameWnd::OnUpdateMDIWindowCmd(CCmdUI* pCmdUI)
{
// We don't want handling for MDI commands
pCmdUI->Enable(FALSE);
}
HMENU CTabbedMDIFrameWnd::GetWindowMenuPopup(HMENU hMenuBar)
{
int iCount = ::GetMenuItemCount(hMenuBar);
// In a standard MDI menu, "Window" & "Help" are the 2 last sub-menus
return (iCount >= 2)? ::GetSubMenu(hMenuBar, iCount-2) : NULL;
}
BOOL CTabbedMDIFrameWnd::PreTranslateMessage(MSG* pMsg)
{
if(WM_COMMAND == pMsg->message)
{
// menu or accelerator within range of MDI children
ASSERT(AFX_IDM_FIRST_MDICHILD == 0xFF00);
if( (pMsg->lParam == NULL) && ((LOWORD(pMsg->wParam) & 0xf000) == 0xf000) )
{
m_wndMDIClient.SetActiveChildByMenuId(LOWORD(pMsg->wParam));
return TRUE;
}
}
else if (WM_KEYDOWN == pMsg->message)
{
if(__super::PreTranslateMessage(pMsg))
{
// This message is handled by __super, should return immediately
return TRUE;
}
if( (pMsg->wParam == VK_F6) &&
(GetKeyState(VK_CONTROL) < 0) && // Ctrl-F6
(m_wndMDIClient.GetChildCount() > 1) && // More than one MDI child
(NULL == this->GetActiveView()) ) // Still in MDI mode
{
::SendMessage(m_hWndMDIClient, WM_MDINEXT, NULL, (GetKeyState(VK_SHIFT) < 0) );
return TRUE;
}
else if( (pMsg->wParam == VK_F4) &&
(GetKeyState(VK_CONTROL) < 0) && // Ctrl-F4
(m_wndMDIClient.GetChildCount() > 0) && // At least one
(NULL == this->GetActiveView()) ) // Still in MDI mode
{
CMDIChildWnd* pWnd = MDIGetActive();
ASSERT_KINDOF(CTabbedMDIChildWnd, pWnd);
pWnd->SendMessage(WM_CLOSE, 0, 0);
return TRUE;
}
return FALSE;
}
return __super::PreTranslateMessage(pMsg);
}
// virtual
BOOL CTabbedMDIFrameWnd::CreateClient(LPCREATESTRUCT lpCreateStruct, CMenu* pWindowMenu)
{
ASSERT(NULL == m_hWndMDIClient);
class CMDICreationHookWnd : public CWnd
{
CMDIClientHooker* m_pMDIClientWithSplitter;
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// This is the first message
ASSERT(WM_NCCREATE == message);
// Un-subclassing
HWND hWnd = this->UnsubclassWindow();
CWindow(hWnd).ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
m_pMDIClientWithSplitter->SubclassWindow(hWnd);
// Modify style and forward message to WTL library
return ::SendMessage(hWnd, message, wParam, lParam);
}
public:
CMDICreationHookWnd(CMDIClientHooker* pMDIClientWithSplitter)
: m_pMDIClientWithSplitter(pMDIClientWithSplitter)
{
}
};
CMDICreationHookWnd wndHooker(&this->m_wndMDIClient);
AfxHookWindowCreate(&wndHooker);
return __super::CreateClient(lpCreateStruct, pWindowMenu);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CTabbedMDIChildWnd, CMDIChildWnd)
BEGIN_MESSAGE_MAP(CTabbedMDIChildWnd, CMDIChildWnd)
ON_WM_WINDOWPOSCHANGING()
ON_WM_SIZE()
ON_WM_MOUSEACTIVATE()
ON_WM_DESTROY()
ON_WM_MDIACTIVATE()
ON_WM_NCCREATE()
ON_MESSAGE(WM_SETTEXT, OnSetText)
END_MESSAGE_MAP()
CTabbedMDIChildWnd::CTabbedMDIChildWnd()
: m_blInChangeParent(FALSE)
, m_hWndMDIClient(NULL)
{
}
HWND CTabbedMDIChildWnd::ChangeParent(HWND hWndNewParent)
{
m_blInChangeParent = TRUE;
HWND hWndOldParent = (HWND) ::SetWindowLongPtr(m_hWnd,
GWLP_HWNDPARENT, (LONG_PTR) hWndNewParent);
m_blInChangeParent = FALSE;
return hWndOldParent;
}
LRESULT CTabbedMDIChildWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
return (m_blInChangeParent)? 0 : __super::WindowProc(nMsg, wParam, lParam);
}
LRESULT CTabbedMDIChildWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
}
BOOL CTabbedMDIChildWnd::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
if (!__super::OnNcCreate(lpCreateStruct))
return FALSE;
// Keep the MDI client for later use
m_hWndMDIClient = ::GetParent(m_hWnd);
return TRUE;
}
void CTabbedMDIChildWnd::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
// Skip behavior of CMDIChildWnd class
::DefWindowProc(m_hWnd, WM_WINDOWPOSCHANGING, 0, (LPARAM) lpwndpos);
}
void CTabbedMDIChildWnd::OnSize(UINT nType, int cx, int cy)
{
// Trick: Change its parent temporarily
HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
__super::OnSize(nType, cx, cy);
ChangeParent(hWndOldParent);
}
void CTabbedMDIChildWnd::OnDestroy()
{
// Skip behavior of CMDIChildWnd class
// Otherwise, we will meet a lot of trouble :-(
CFrameWnd::OnDestroy();
}
CWnd* CTabbedMDIChildWnd::GetMessageBar()
{
CFrameWnd* pFrameWnd = (CFrameWnd*) CWnd::FromHandlePermanent(::GetParent((HWND)m_hWndMDIClient));
ASSERT_KINDOF(CFrameWnd, pFrameWnd);
return pFrameWnd->GetMessageBar();
}
void CTabbedMDIChildWnd::ActivateFrame(int nCmdShow)
{
// Trick: Change its parent temporarily
HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
__super::ActivateFrame(SW_NORMAL);
ChangeParent(hWndOldParent);
}
void CTabbedMDIChildWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
{
// Trick: Change its parent temporarily
HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
__super::OnUpdateFrameTitle(bAddToTitle);
ChangeParent(hWndOldParent);
}
void CTabbedMDIChildWnd::OnUpdateFrameMenu(BOOL bActive, CWnd* pActivateWnd, HMENU hMenuAlt)
{
// Trick: Change its parent temporarily
HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
__super::OnUpdateFrameMenu(bActive, pActivateWnd, hMenuAlt);
ChangeParent(hWndOldParent);
}
int CTabbedMDIChildWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
int nResult = CFrameWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
if( (nResult != MA_NOACTIVATE) && (nResult == MA_NOACTIVATEANDEAT) )
{
// frame want to activate so activate this window
::SendMessage((HWND) m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM) m_hWnd, 0);
}
return nResult;
}
void CTabbedMDIChildWnd::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
{
// Trick: Change its parent temporarily
HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
__super::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
ChangeParent(hWndOldParent);
}
BOOL CTabbedMDIChildWnd::DestroyWindow()
{
ChangeParent(m_hWndMDIClient);
return __super::DestroyWindow();
}
LRESULT CTabbedMDIChildWnd::OnSetText(WPARAM, LPARAM lParam)
{
LPCTSTR szWindowText = (LPCTSTR) lParam;
LRESULT lRes = Default();
::SendMessage((HWND) m_hWndMDIClient, WM_SETTEXT, (WPARAM) m_hWnd, lParam);
return lRes;
}
void CTabbedMDIFrameWnd::CMDIClientHooker::ClearMenu()
{
if(m_hSubMenu)
{
// Clear the menu
ASSERT(::IsMenu(m_hSubMenu));
for(int i = GetMenuItemCount(m_hSubMenu)-m_iOriginalMenuItemCount;
i > 0; --i)
{
VERIFY(DeleteMenu(m_hSubMenu, m_iOriginalMenuItemCount, MF_BYPOSITION));
}
}
}
void CTabbedMDIFrameWnd::CMDIClientHooker::RefreshMenu()
{
if(NULL == m_hSubMenu)
{
return;
}
ClearMenu();
CString strWindowText;
CString strMenuText;
CMenu menu;
menu.Attach(m_hSubMenu);
// Add or remove a separator if needed
if(m_iOriginalMenuItemCount > 0)
{
if (0 != menu.GetMenuItemID(m_iOriginalMenuItemCount - 1))
{
menu.AppendMenu(MF_SEPARATOR);
}
else if(m_iOriginalMenuItemCount == 1)
{
// Remove the separator
m_iOriginalMenuItemCount = 0;
menu.RemoveMenu(0, MF_BYPOSITION);
}
}
for(size_t i=0; i<m_ZOrder.size(); ++i)
{
HWND hWndChild = m_ZOrder[i];
ASSERT(::IsWindow(hWndChild));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -