📄 tabbedmdi.h
字号:
*/
bHandled = TRUE;
}
else
{
bHandled = FALSE;
}
return 0;
}
LRESULT OnMDIDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// NOTE: For symmetry, we could try to handle WM_MDICREATE
// for tab creation. There are 2 reasons we don't:
// 1. With WTL, the implementation doesn't use WM_MDICREATE,
// so it wouldn't be reliable to rely on it
// 2. We don't need to. Handling the change in child
// activation to display the tab, if its not there,
// creates, DisplayTab will create the corresponding tab.
// Remove the tab for the child being destroyed.
// Before removing the tab, we want the default happen,
// so that the MDI Client figures out who to activate next.
// If we removed the tab first, the "DeleteItem" on
// the tab wouldn't know the next best tab to select,
// and so if it's removing the tab that's currently selected,
// it changes the selection to 0.
// But by having the MDI client activate the child
// "next in line" (Z-Order), that child will be activated,
// and its tab will be selected, so that by the time we remove
// the tab for this child, the tab won't be selected.
LRESULT lRet = this->DefWindowProc(uMsg, wParam, lParam);
bHandled = TRUE;
if(wParam != NULL)
{
m_MdiTabOwner.RemoveTab((HWND)wParam);
}
return lRet;
}
LRESULT OnChildActivationChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// NOTE: We'd like to just handle WM_MDIACTIVATE when sent to
// the MDI client to know when the active MDI child has changed.
// Unfortunately, you don't HAVE to send WM_MDIACTIVATE to the
// MDI Client to change the active child (such as clicking
// a different MDI child to activate it).
// However, the MDI *child* will *always* receive WM_MDIACTIVATE.
// In fact, the child losing focus gets WM_MDIACTIVATE,
// and then the child gaining focus gets WM_MDIACTIVATE
// (the "deactivating" and "activating" windows are sent as
// the WPARAM and LPARAM both times).
// So we'll make the "activating" child window responsible for
// sending us a message (UWM_MDICHILDACTIVATIONCHANGE)
// when it gets a WM_MDIACTIVATE message. We'll use this
// to display the tab (switching the selected tab to the
// corresponding tab, or creating a tab for the child and
// setting it as selected)
if(wParam != NULL)
{
m_MdiTabOwner.DisplayTab((HWND)wParam, TRUE, m_bUseMDIChildIcon);
}
return 0;
}
LRESULT OnChildTabTextChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
// NOTE: Our direct children are Frame windows.
// We make the MDI child responsible for sending us a
// message (UWM_MDICHILDTABTEXTCHANGE) if they want to
// update the text of the corresponding tab.
if(wParam != NULL)
{
m_MdiTabOwner.UpdateTabText((HWND)wParam, (LPCTSTR)lParam);
}
return 0;
}
LRESULT OnChildTabToolTipChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
// We make the MDI child responsible for sending us a
// message (UWM_MDICHILDTABTOOLTIPCHANGE) with the tooltip
// if that tooltip is something different than the tab text.
if(wParam != NULL)
{
m_MdiTabOwner.UpdateTabToolTip((HWND)wParam, (LPCTSTR)lParam);
}
return 0;
}
LRESULT OnChildMaximized(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_bHideMDITabsWhenMDIChildNotMaximized)
{
HWND hWndMaximized = (HWND)wParam;
HWND hWndActiveChild = (HWND)this->SendMessage(WM_MDIGETACTIVE, 0, 0);
if(hWndMaximized == hWndActiveChild)
{
m_MdiTabOwner.KeepTabsHidden(false);
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnChildUnMaximized(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_bHideMDITabsWhenMDIChildNotMaximized)
{
HWND hWndUnMaximized = (HWND)wParam;
HWND hWndActiveChild = (HWND)this->SendMessage(WM_MDIGETACTIVE, 0, 0);
if(hWndUnMaximized == hWndActiveChild)
{
m_MdiTabOwner.KeepTabsHidden(true);
}
}
bHandled = FALSE;
return 0;
}
};
template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CTabbedMDICommandBarCtrlImpl : public CMDICommandBarCtrlImpl<T, TBase, TWinTraits>
{
protected:
typedef CTabbedMDICommandBarCtrlImpl thisClass;
typedef CMDICommandBarCtrlImpl<T, TBase, TWinTraits> baseClass;
typedef CCommandBarCtrlImpl<T, TBase, TWinTraits> grandparentClass;
// Extended data
protected:
bool m_bUseMaxChildDocIconAndFrameCaptionButtons:1;
// Constructors
public:
CTabbedMDICommandBarCtrlImpl() :
m_bUseMaxChildDocIconAndFrameCaptionButtons(true)
{
}
// Public methods
public:
void UseMaxChildDocIconAndFrameCaptionButtons(bool bUseMaxChildDocIconAndFrameCaptionButtons = true)
{
m_bUseMaxChildDocIconAndFrameCaptionButtons = bUseMaxChildDocIconAndFrameCaptionButtons;
}
// Overrides
public:
void GetSystemSettings()
{
baseClass::GetSystemSettings();
m_cxLeft += 4;
}
// Message Handling
public:
BEGIN_MSG_MAP(thisClass)
if(m_bUseMaxChildDocIconAndFrameCaptionButtons)
{
CHAIN_MSG_MAP(baseClass)
}
else
{
CHAIN_MSG_MAP(grandparentClass)
}
ALT_MSG_MAP(1) // Parent window messages
if(m_bUseMaxChildDocIconAndFrameCaptionButtons)
{
CHAIN_MSG_MAP_ALT(baseClass, 1)
}
else
{
CHAIN_MSG_MAP_ALT(grandparentClass, 1)
}
ALT_MSG_MAP(2) // MDI client window messages
MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
if(m_bUseMaxChildDocIconAndFrameCaptionButtons)
{
MESSAGE_HANDLER(WM_MDIDESTROY, OnMDIDestroy)
MESSAGE_HANDLER(UWM_MDICHILDMAXIMIZED, OnChildMaximized)
MESSAGE_HANDLER(UWM_MDICHILDUNMAXIMIZED, OnChildUnMaximized)
}
// NOTE: If future implementations of CMDICommandBarCtrlImpl
// add MDI client related handlers for ALT_MSG_MAP(2),
// either add them here or chain to the base
ALT_MSG_MAP(3) // Message hook messages
// NOTE: We don't want to depend on the command bar's
// hooked messages for telling us about maximization
// changes. We can do the job with the normal
// MDI messages and our special MDI messages
//MESSAGE_RANGE_HANDLER(0, 0xFFFF, OnAllHookMessages)
CHAIN_MSG_MAP_ALT(grandparentClass, 3)
END_MSG_MAP()
// MDI client window message handlers
LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
m_wndMDIClient.DefWindowProc(uMsg, NULL, lParam);
HMENU hOldMenu = GetMenu();
BOOL bRet = AttachMenu((HMENU)wParam);
bRet; // avoid level 4 warning
ATLASSERT(bRet);
#if (_WTL_VER >= 0x0710) && (_WIN32_IE >= 0x0400)
T* pT = static_cast<T*>(this);
pT->UpdateRebarBandIdealSize();
#endif //(_WTL_VER >= 0x0710) && (_WIN32_IE >= 0x0400)
return (LRESULT)hOldMenu;
}
LRESULT OnMDIDestroy(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
HWND hWndChild = (HWND)wParam;
if(m_hWndChildMaximized == hWndChild)
{
bool bMaxOld = m_bChildMaximized;
HICON hIconOld = m_hIconChildMaximized;
m_bChildMaximized = false;
m_hWndChildMaximized = NULL;
m_hIconChildMaximized = NULL;
T* pT = static_cast<T*>(this);
pT->RefreshMaximizedState((bMaxOld != m_bChildMaximized), (hIconOld != m_hIconChildMaximized));
}
bHandled = FALSE;
return 0;
}
LRESULT OnChildMaximized(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
HWND hWndChild = (HWND)wParam;
bool bMaxOld = m_bChildMaximized;
HICON hIconOld = m_hIconChildMaximized;
m_bChildMaximized = true;
if(m_hWndChildMaximized != hWndChild)
{
CWindow wnd = m_hWndChildMaximized = hWndChild;
m_hIconChildMaximized = wnd.GetIcon(FALSE);
if(m_hIconChildMaximized == NULL) // no icon set with WM_SETICON, get the class one
{
m_hIconChildMaximized = (HICON) LongToHandle(::GetClassLong(wnd, GCL_HICONSM));
if(m_hIconChildMaximized == NULL)
{
m_hIconChildMaximized = (HICON) LongToHandle(::GetClassLong(wnd, GCL_HICON));
}
}
}
T* pT = static_cast<T*>(this);
pT->RefreshMaximizedState((bMaxOld != m_bChildMaximized), (hIconOld != m_hIconChildMaximized));
bHandled = FALSE;
return 0;
}
LRESULT OnChildUnMaximized(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
HWND hWndChild = (HWND)wParam;
if(m_hWndChildMaximized == hWndChild)
{
bool bMaxOld = m_bChildMaximized;
HICON hIconOld = m_hIconChildMaximized;
m_bChildMaximized = false;
m_hWndChildMaximized = NULL;
m_hIconChildMaximized = NULL;
T* pT = static_cast<T*>(this);
pT->RefreshMaximizedState((bMaxOld != m_bChildMaximized), (hIconOld != m_hIconChildMaximized));
}
bHandled = FALSE;
return 0;
}
void RefreshMaximizedState(bool bMaximizeChanged, bool bIconChanged)
{
// NOTE: This code comes out of CMDICommandBarCtrlImpl::OnAllHookMessages.
// If the base implementation changes, reflect those changes here.
if(bMaximizeChanged)
{
#ifdef _CMDBAR_EXTRA_TRACE
ATLTRACE2(atlTraceUI, 0, "MDI CmdBar - All messages hook change: m_bChildMaximized = %s\n", m_bChildMaximized ? "true" : "false");
#endif
// assuming we are in a rebar, change our size to accomodate new state
// we hope that if we are not in a rebar, nCount will be 0
int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L);
int cxDiff = (m_bChildMaximized ? 1 : -1) * (m_cxLeft + m_cxRight);
for(int i = 0; i < nCount; i++)
{
#if (_WIN32_IE >= 0x0500)
REBARBANDINFO rbi = { sizeof(REBARBANDINFO), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE };
::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
if(rbi.hwndChild == m_hWnd)
{
if((rbi.fStyle & RBBS_USECHEVRON) != 0)
{
rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
rbi.cxMinChild += cxDiff;
rbi.cxIdeal += cxDiff;
::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
}
break;
}
#elif (_WIN32_IE >= 0x0400)
REBARBANDINFO rbi = { sizeof(REBARBANDINFO), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE };
::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
if(rbi.hwndChild == m_hWnd)
{
rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
rbi.cxMinChild += cxDiff;
rbi.cxIdeal += cxDiff;
::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
break;
}
#else //(_WIN32_IE < 0x0400)
REBARBANDINFO rbi = { sizeof(REBARBANDINFO), RBBIM_CHILD | RBBIM_CHILDSIZE };
::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
if(rbi.hwndChild == m_hWnd)
{
rbi.fMask = RBBIM_CHILDSIZE;
rbi.cxMinChild += cxDiff;
::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
break;
}
#endif //!(_WIN32_IE >= 0x0500)
}
}
if(bMaximizeChanged || bIconChanged)
{
// force size change and redraw everything
RECT rect = { 0 };
GetWindowRect(&rect);
::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2);
SetRedraw(FALSE);
SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE);
SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
SetRedraw(TRUE);
RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
}
}
};
class CTabbedMDICommandBarCtrl : public CTabbedMDICommandBarCtrlImpl<CTabbedMDICommandBarCtrl>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_TabbedMDICommandBar"), GetWndClassName())
};
/*
class CAnotherTabbedMDICommandBarCtrl : public CTabbedMDICommandBarCtrlImpl<CAnotherTabbedMDICommandBarCtrl>
{
protected:
typedef CAnotherTabbedMDICommandBarCtrl thisClass;
typedef CTabbedMDICommandBarCtrlImpl<CAnotherTabbedMDICommandBarCtrl> baseClass;
public:
DECLARE_WND_SUPERCLASS(_T("WTL_AnotherTabbedMDICommandBar"), GetWndClassName())
BEGIN_MSG_MAP(thisClass)
CHAIN_MSG_MAP(baseClass)
ALT_MSG_MAP(1) // Parent window messages
CHAIN_MSG_MAP_ALT(baseClass, 1)
ALT_MSG_MAP(2) // MDI client window mes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -