?? tabbedmdi.h
字號:
public:
void SetTabOwnerParent(HWND hWndTabOwnerParent)
{
m_hWndTabOwnerParent = hWndTabOwnerParent;
}
HWND GetTabOwnerParent(void) const
{
return m_hWndTabOwnerParent;
}
TTabOwner& GetTabOwner(void)
{
return m_MdiTabOwner;
}
void UseMDIChildIcon(BOOL bUseMDIChildIcon = TRUE)
{
m_bUseMDIChildIcon = bUseMDIChildIcon;
}
void HideMDITabsWhenMDIChildNotMaximized(BOOL bHideMDITabsWhenMDIChildNotMaximized = TRUE)
{
m_bHideMDITabsWhenMDIChildNotMaximized = bHideMDITabsWhenMDIChildNotMaximized;
}
void SetDrawFlat(bool bDrawFlat = true)
{
if(m_bDrawFlat!=bDrawFlat)
{
//ATLASSERT((m_hWnd==NULL) && "Please call SetDrawFlat before CreateWindow or SubclassWindow");
m_bDrawFlat = bDrawFlat;
if(m_bDrawFlat)
{
m_MdiTabOwner.ModifyTabStyles(0,CTCS_FLATEDGE);
}
else
{
m_MdiTabOwner.ModifyTabStyles(CTCS_FLATEDGE,0);
}
}
}
bool GetDrawFlat(void) const
{
return m_bDrawFlat;
}
#ifdef __TabbedMDISave_h__
bool SaveAllModified(bool canPrompt, bool canCancel) const
{
if(canPrompt)
{
// Prompt using our "Save modified" dialog
CComPtr<ITabbedMDIChildModifiedList> modifiedItems;
this->FindModified(&modifiedItems);
if(modifiedItems)
{
long modifiedCount = 0;
modifiedItems->get_Count(&modifiedCount);
if(modifiedCount > 0)
{
CSaveModifiedItemsDialog dialog(modifiedItems, canCancel);
INT_PTR response = dialog.DoModal();
if(response == IDYES)
{
// The dialog will update the list and remove
// any items that the user unchecked
this->SaveModified(modifiedItems);
}
else if(response == IDCANCEL)
{
// Not safe to close
return false;
}
}
}
}
else
{
// Save all files, but don't ask permission.
HWND hWndChild = ::GetTopWindow(m_hWnd);
while(hWndChild != NULL)
{
::SendMessage(hWndChild, UWM_MDICHILDSAVEMODIFIED, 0, 0);
hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT);
}
}
// Safe to terminate the application if desired
return true;
}
HRESULT FindModified(ITabbedMDIChildModifiedList** modifiedItemsOut) const
{
CWaitCursor waitCursor;
if(modifiedItemsOut == NULL)
{
return E_POINTER;
}
*modifiedItemsOut = NULL;
long modifiedCount = 0;
HRESULT hr = S_OK;
// Build up a list of all the modified documents
CComPtr<ITabbedMDIChildModifiedList> modifiedItems;
::CreateTabbedMDIChildModifiedList(&modifiedItems);
if(modifiedItems)
{
HWND hWndChild = ::GetTopWindow(m_hWnd);
while(hWndChild != NULL)
{
CString windowText;
int cchWindowText = ::GetWindowTextLength(hWndChild);
LPTSTR pszText = windowText.GetBuffer(cchWindowText+1);
cchWindowText = ::GetWindowText(hWndChild, pszText, cchWindowText+1);
windowText.ReleaseBuffer(cchWindowText);
CComBSTR defaultName(windowText);
CComPtr<ITabbedMDIChildModifiedItem> modifiedItem;
::CreateTabbedMDIChildModifiedItem(hWndChild,
defaultName, defaultName, defaultName, 0, NULL, &modifiedItem);
BOOL bIsModified = (BOOL)::SendMessage(hWndChild, UWM_MDICHILDISMODIFIED, 0, (LPARAM)modifiedItem.p);
if(bIsModified)
{
++modifiedCount;
modifiedItems->Insert(-1, modifiedItem);
}
hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT);
}
if(modifiedCount > 0)
{
modifiedItems.CopyTo(modifiedItemsOut);
}
}
return hr;
}
HRESULT SaveModified(ITabbedMDIChildModifiedList* modifiedItems) const
{
if(modifiedItems == NULL)
{
return E_INVALIDARG;
}
CWaitCursor waitCursor;
HRESULT hr = S_OK;
long count = 0;
modifiedItems->get_Count(&count);
for(long i=0; i<count; ++i)
{
CComPtr<ITabbedMDIChildModifiedItem> modifiedItem;
modifiedItems->get_Item(i, &modifiedItem);
if(modifiedItem)
{
HWND hWnd = NULL;
modifiedItem->get_Window(&hWnd);
if(hWnd && ::IsWindow(hWnd))
{
::SendMessage(hWnd, UWM_MDICHILDSAVEMODIFIED, 0, (LPARAM)modifiedItem.p);
}
// Important! If an item has sub-items, the "top-level"
// item is responsible for ensuring that modifications
// are saved.
}
}
return hr;
}
#endif // __TabbedMDISave_h__
void CloseAll(bool bPreferNoPrompt = false) const
{
HWND hWndChild = ::GetTopWindow(m_hWnd);
while(hWndChild != NULL)
{
HWND hWndClose = hWndChild;
hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT);
if(bPreferNoPrompt)
{
::SendMessage(hWndClose, UWM_MDICHILDCLOSEWITHNOPROMPT, 0, 0L);
}
if(::IsWindow(hWndClose))
{
// The window doesn't support UWM_MDICHILDCLOSEWITHNOPROMPT
// or the caller didn't want to close with no prompt,
// so we'll send a close message it should understand.
::SendMessage(hWndClose, WM_SYSCOMMAND, SC_CLOSE, 0L);
}
}
}
BOOL SubclassWindow(HWND hWnd)
{
BOOL bSuccess = baseClass::SubclassWindow(hWnd);
m_bSubclassed = true;
this->InitTabs();
m_MdiTabOwner.CalcTabAreaHeight();
return bSuccess;
}
HWND UnsubclassWindow(BOOL bForce = FALSE)
{
m_bSubclassed = false;
return baseClass::UnsubclassWindow(bForce);
}
protected:
void InitTabs()
{
if( !m_MdiTabOwner.IsWindow() )
{
if(m_hWndTabOwnerParent == NULL)
{
// If the tab owner's parent is not specified,
// have the tabs as a sibling
m_hWndTabOwnerParent = this->GetParent();
}
m_MdiTabOwner.Create(
m_hWndTabOwnerParent,
rcDefault, NULL,
WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN // start out not visible
);
m_MdiTabOwner.SetMDIClient(m_hWnd);
}
}
// Message Handling
public:
DECLARE_WND_SUPERCLASS(_T("TabbedMDIClient"), _T("MDIClient"))
BEGIN_MSG_MAP(CTabbedMDIClient)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
//MESSAGE_HANDLER(WM_MDICREATE, OnMDICreate)
MESSAGE_HANDLER(WM_MDIDESTROY, OnMDIDestroy)
MESSAGE_HANDLER(UWM_MDICHILDACTIVATIONCHANGE, OnChildActivationChange)
MESSAGE_HANDLER(UWM_MDICHILDTABTEXTCHANGE, OnChildTabTextChange)
MESSAGE_HANDLER(UWM_MDICHILDTABTOOLTIPCHANGE, OnChildTabToolTipChange)
MESSAGE_HANDLER(UWM_MDICHILDMAXIMIZED, OnChildMaximized)
MESSAGE_HANDLER(UWM_MDICHILDUNMAXIMIZED, OnChildUnMaximized)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// "base::OnCreate()"
LRESULT lRet = this->DefWindowProc(uMsg, wParam, lParam);
bHandled = TRUE;
if(lRet == -1)
{
return -1;
}
this->InitTabs();
m_MdiTabOwner.CalcTabAreaHeight();
return lRet;
}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// Say that we didn't handle it so that anyone else
// interested gets to handle the message
bHandled = FALSE;
return 0;
}
LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// Be sure tab gets message before we recalculate the tab area height
// so that it can adjust its font metrics first.
// NOTE: This causes the tab to get the WM_SETTINGCHANGE message twice,
// but that's OK.
m_MdiTabOwner.GetTabCtrl().SendMessage(uMsg, wParam, lParam);
m_MdiTabOwner.CalcTabAreaHeight();
bHandled = FALSE;
return 0;
}
LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LPWINDOWPOS pWinPos = reinterpret_cast<LPWINDOWPOS>(lParam);
if(pWinPos)
{
if( m_MdiTabOwner.IsWindow() )
{
//ATLTRACE(_T("Resizing MDI tab and MDI client\n"));
int nTabAreaHeight = (m_MdiTabOwner.IsWindowVisible()) ? m_MdiTabOwner.GetTabAreaHeight() : 0;
TTabCtrl& TabCtrl = m_MdiTabOwner.GetTabCtrl();
DWORD dwStyle = TabCtrl.GetStyle();
if(CTCS_BOTTOM == (dwStyle & CTCS_BOTTOM))
{
m_MdiTabOwner.SetWindowPos(
NULL,
pWinPos->x, pWinPos->y + (pWinPos->cy - nTabAreaHeight),
pWinPos->cx, nTabAreaHeight,
(pWinPos->flags & SWP_NOMOVE) | (pWinPos->flags & SWP_NOSIZE) | SWP_NOZORDER | SWP_NOACTIVATE);
if((pWinPos->flags & SWP_NOSIZE) == 0)
{
pWinPos->cy -= nTabAreaHeight;
}
}
else
{
m_MdiTabOwner.SetWindowPos(
NULL,
pWinPos->x, pWinPos->y,
pWinPos->cx, nTabAreaHeight,
(pWinPos->flags & SWP_NOMOVE) | (pWinPos->flags & SWP_NOSIZE) | SWP_NOZORDER | SWP_NOACTIVATE);
if((pWinPos->flags & SWP_NOMOVE) == 0)
{
pWinPos->y += nTabAreaHeight;
}
if((pWinPos->flags & SWP_NOSIZE) == 0)
{
pWinPos->cy -= nTabAreaHeight;
}
}
}
}
// "base::OnWindowPosChanging()"
LRESULT lRet = this->DefWindowProc(uMsg, wParam, lParam);
bHandled = TRUE;
return lRet;
}
LRESULT OnNcPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_bDrawFlat &&
WS_EX_CLIENTEDGE == (this->GetExStyle() & WS_EX_CLIENTEDGE))
{
// When we have WS_EX_CLIENTEDGE and drawing "flat",
// we'll paint the non-client edges ourself with a more flat look.
// NOTE: If WS_EX_CLIENTEDGE ever takes up more than 2 pixels
// on each edge, update the drawing code.
CDC dc(this->GetWindowDC());
if(dc)
{
RECT rcWindow;
this->GetWindowRect(&rcWindow);
::OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
dc.DrawEdge(&rcWindow, EDGE_ETCHED, BF_FLAT|BF_RECT);
}
/*
// Note: The documentation says the flags should be
// DCX_WINDOW|DCX_INTERSECTRGN
// but that wasn't working.
// On http://freespace.virgin.net/james.brown7/tutorials/tips.htm
// they mention you also need to OR in the flag "0x10000".
CDC dc(this->GetDCEx((HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN | 0x10000));
if(dc)
{
RECT rcWindow;
this->GetWindowRect(&rcWindow);
::OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
dc.DrawEdge(&rcWindow, EDGE_ETCHED, BF_FLAT|BF_RECT);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -