home *** CD-ROM | disk | FTP | other *** search
- // 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 <malloc.h>
-
- #ifdef AFX_CORE3_SEG
- #pragma code_seg(AFX_CORE3_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // CControlBar
-
- // IMPLEMENT_DYNAMIC for CControlBar is in wincore.cpp for .OBJ granularity reasons
-
- BEGIN_MESSAGE_MAP(CControlBar, CWnd)
- //{{AFX_MSG_MAP(CControlBar)
- ON_WM_TIMER()
- ON_WM_PAINT()
- ON_WM_CTLCOLOR()
- ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
- ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
- ON_WM_WINDOWPOSCHANGING()
- ON_WM_SHOWWINDOW()
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONDBLCLK()
- ON_WM_MOUSEACTIVATE()
- ON_WM_CANCELMODE()
- ON_WM_CREATE()
- ON_WM_DESTROY()
- ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate)
- ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
- ON_WM_ERASEBKGND()
- //}}AFX_MSG_MAP
- #ifndef _AFX_NO_CTL3D_SUPPORT
- ON_MESSAGE(WM_QUERY3DCONTROLS, OnQuery3dControls)
- #endif
- END_MESSAGE_MAP()
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- CControlBar::CControlBar()
- {
- // no elements contained in the control bar yet
- m_nCount = 0;
- m_pData = NULL;
-
- // set up some default border spacings
- m_cxLeftBorder = m_cxRightBorder = 6;
- m_cxDefaultGap = 2;
- m_cyTopBorder = m_cyBottomBorder = 1;
- m_bAutoDelete = FALSE;
- m_hWndOwner = NULL;
- m_nStateFlags = 0;
- m_pDockSite = NULL;
- m_pDockBar = NULL;
- m_pDockContext = NULL;
- m_dwStyle = 0;
- m_dwDockStyle = 0;
- m_nMRUWidth = 32767;
- }
-
- void CControlBar::SetBorders(int cxLeft, int cyTop, int cxRight, int cyBottom)
- {
- ASSERT(cxLeft >= 0);
- ASSERT(cyTop >= 0);
- ASSERT(cxRight >= 0);
- ASSERT(cyBottom >= 0);
-
- m_cxLeftBorder = cxLeft;
- m_cyTopBorder = cyTop;
- m_cxRightBorder = cxRight;
- m_cyBottomBorder = cyBottom;
- }
-
- BOOL CControlBar::PreCreateWindow(CREATESTRUCT& cs)
- {
- if (!CWnd::PreCreateWindow(cs))
- return FALSE;
-
- // force clipsliblings (otherwise will cause repaint problems)
- cs.style |= WS_CLIPSIBLINGS;
-
- // default border style translation for Win4
- // (you can turn off this translation by setting CBRS_BORDER_3D)
- if (afxData.bWin4 && (m_dwStyle & CBRS_BORDER_3D) == 0)
- {
- DWORD dwNewStyle = 0;
- switch (m_dwStyle & (CBRS_BORDER_ANY|CBRS_ALIGN_ANY))
- {
- case CBRS_LEFT:
- dwNewStyle = CBRS_BORDER_TOP|CBRS_BORDER_BOTTOM;
- break;
- case CBRS_TOP:
- dwNewStyle = CBRS_BORDER_TOP;
- break;
- case CBRS_RIGHT:
- dwNewStyle = CBRS_BORDER_TOP|CBRS_BORDER_BOTTOM;
- break;
- case CBRS_BOTTOM:
- dwNewStyle = CBRS_BORDER_BOTTOM;
- break;
- }
-
- // set new style if it matched one of the predefined border types
- if (dwNewStyle != 0)
- {
- m_dwStyle &= ~(CBRS_BORDER_ANY);
- m_dwStyle |= (dwNewStyle | CBRS_BORDER_3D);
- }
- }
-
- return TRUE;
- }
-
- void CControlBar::SetBarStyle(DWORD dwStyle)
- {
- ASSERT((dwStyle & CBRS_ALL) == dwStyle);
-
- EnableToolTips(dwStyle & CBRS_TOOLTIPS);
-
- if (m_dwStyle != dwStyle)
- {
- DWORD dwOldStyle = m_dwStyle;
- m_dwStyle = dwStyle;
- OnBarStyleChange(dwOldStyle, dwStyle);
- }
- }
-
- void CControlBar::OnBarStyleChange(DWORD, DWORD)
- {
- // can be overridden in derived classes
- }
-
- BOOL CControlBar::AllocElements(int nElements, int cbElement)
- {
- ASSERT_VALID(this);
- ASSERT(nElements >= 0 && cbElement >= 0);
- ASSERT(m_pData != NULL || m_nCount == 0);
-
- // allocate new data if necessary
- void* pData = NULL;
- if (nElements > 0)
- {
- ASSERT(cbElement > 0);
- if ((pData = calloc(nElements, cbElement)) == NULL)
- return FALSE;
- }
- free(m_pData); // free old data
-
- // set new data and elements
- m_pData = pData;
- m_nCount = nElements;
-
- return TRUE;
- }
-
- #ifdef AFX_CORE3_SEG
- #pragma code_seg(AFX_CORE3_SEG)
- #endif
-
- CControlBar::~CControlBar()
- {
- ASSERT_VALID(this);
-
- DestroyWindow(); // avoid PostNcDestroy problems
-
- // also done in OnDestroy, but done here just in case
- if (m_pDockSite != NULL)
- m_pDockSite->RemoveControlBar(this);
-
- // free docking context
- CDockContext* pDockContext = m_pDockContext;
- m_pDockContext = NULL;
- delete pDockContext;
-
- // free array
- if (m_pData != NULL)
- {
- ASSERT(m_nCount != 0);
- free(m_pData);
- }
-
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- if (pThreadState->m_pLastStatus == this)
- {
- pThreadState->m_pLastStatus = NULL;
- pThreadState->m_nLastStatus = -1;
- }
- }
-
- void CControlBar::PostNcDestroy()
- {
- if (m_bAutoDelete) // Automatic cleanup?
- delete this;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Attributes
-
- CSize CControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
- {
- CSize size;
- size.cx = (bStretch && bHorz ? 32767 : 0);
- size.cy = (bStretch && !bHorz ? 32767 : 0);
- return size;
- }
-
- CSize CControlBar::CalcDynamicLayout(int, DWORD nMode)
- {
- return CalcFixedLayout(nMode & LM_STRETCH, nMode & LM_HORZ);
- }
-
- BOOL CControlBar::IsDockBar() const
- {
- return FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Fly-by status bar help
-
- #define ID_TIMER_WAIT 0xE000 // timer while waiting to show status
- #define ID_TIMER_CHECK 0xE001 // timer to check for removal of status
-
- void CControlBar::ResetTimer(UINT nEvent, UINT nTime)
- {
- KillTimer(ID_TIMER_WAIT);
- KillTimer(ID_TIMER_CHECK);
- VERIFY(SetTimer(nEvent, nTime, NULL));
- }
-
- void CControlBar::OnTimer(UINT nIDEvent)
- {
- if (GetKeyState(VK_LBUTTON) < 0)
- return;
-
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
-
- // get current mouse position for hit test
- CPoint point; GetCursorPos(&point);
- ScreenToClient(&point);
- int nHit = OnToolHitTest(point, NULL);
- if (nHit >= 0)
- {
- // determine if status bar help should go away
- CWnd* pParent = GetTopLevelParent();
- if (!IsTopParentActive() || !pParent->IsWindowEnabled())
- nHit = -1;
-
- // remove status help if capture is set
- HWND hWndTip = pThreadState->m_pToolTip->GetSafeHwnd();
- CWnd* pCapture = GetCapture();
- if (pCapture != this && pCapture->GetSafeHwnd() != hWndTip &&
- pCapture->GetTopLevelParent() == pParent)
- {
- nHit = -1;
- }
- }
- else
- {
- pThreadState->m_nLastStatus = -1;
- }
-
- // make sure it isn't over some other app's window
- if (nHit >= 0)
- {
- ClientToScreen(&point);
- HWND hWnd = ::WindowFromPoint(point);
- if (hWnd == NULL || (hWnd != m_hWnd && !::IsChild(m_hWnd, hWnd) &&
- pThreadState->m_pToolTip->GetSafeHwnd() != hWnd))
- {
- nHit = -1;
- pThreadState->m_nLastStatus = -1;
- }
- }
-
- // handle the result
- if (nHit < 0)
- {
- if (pThreadState->m_nLastStatus == -1)
- KillTimer(ID_TIMER_CHECK);
- SetStatusText(-1);
- }
-
- // set status text after initial timeout
- if (nIDEvent == ID_TIMER_WAIT)
- {
- KillTimer(ID_TIMER_WAIT);
- if (nHit >= 0)
- SetStatusText(nHit);
- }
- }
-
- BOOL CControlBar::SetStatusText(int nHit)
- {
- CWnd* pOwner = GetOwner();
-
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- if (nHit == -1)
- {
- // handle reset case
- pThreadState->m_pLastStatus = NULL;
- if (m_nStateFlags & statusSet)
- {
- pOwner->SendMessage(WM_POPMESSAGESTRING, AFX_IDS_IDLEMESSAGE);
- m_nStateFlags &= ~statusSet;
- return TRUE;
- }
- KillTimer(ID_TIMER_WAIT);
- }
- else
- {
- // handle setnew case
- if (!(m_nStateFlags & statusSet) || pThreadState->m_nLastStatus != nHit)
- {
- pThreadState->m_pLastStatus = this;
- pOwner->SendMessage(WM_SETMESSAGESTRING, nHit);
- m_nStateFlags |= statusSet;
- ResetTimer(ID_TIMER_CHECK, 200);
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Default control bar processing
-
- BOOL CControlBar::PreTranslateMessage(MSG* pMsg)
- {
- ASSERT_VALID(this);
- ASSERT(m_hWnd != NULL);
-
- // allow tooltip messages to be filtered
- if (CWnd::PreTranslateMessage(pMsg))
- return TRUE;
-
- UINT message = pMsg->message;
- CWnd* pOwner = GetOwner();
-
- // handle CBRS_FLYBY style (status bar flyby help)
- if (((m_dwStyle & CBRS_FLYBY) ||
- message == WM_LBUTTONDOWN || message == WM_LBUTTONUP) &&
- ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) ||
- (message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST)))
- {
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
-
- // gather information about current mouse position
- CPoint point = pMsg->pt;
- ScreenToClient(&point);
- TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
- ti.cbSize = sizeof(AFX_OLDTOOLINFO);
- int nHit = OnToolHitTest(point, &ti);
- if (ti.lpszText != LPSTR_TEXTCALLBACK)
- free(ti.lpszText);
- BOOL bNotButton =
- message == WM_LBUTTONDOWN && (ti.uFlags & TTF_NOTBUTTON);
- if (message != WM_LBUTTONDOWN && GetKeyState(VK_LBUTTON) < 0)
- nHit = pThreadState->m_nLastStatus;
-
- // update state of status bar
- if (nHit < 0 || bNotButton)
- {
- if (GetKeyState(VK_LBUTTON) >= 0 || bNotButton)
- {
- SetStatusText(-1);
- KillTimer(ID_TIMER_CHECK);
- }
- }
- else
- {
- if (message == WM_LBUTTONUP)
- {
- SetStatusText(-1);
- ResetTimer(ID_TIMER_CHECK, 200);
- }
- else
- {
- if ((m_nStateFlags & statusSet) || GetKeyState(VK_LBUTTON) < 0)
- SetStatusText(nHit);
- else if (nHit != pThreadState->m_nLastStatus)
- ResetTimer(ID_TIMER_WAIT, 300);
- }
- }
- pThreadState->m_nLastStatus = nHit;
- }
-
- // don't translate dialog messages when in Shift+F1 help mode
- CFrameWnd* pFrameWnd = GetTopLevelFrame();
- if (pFrameWnd != NULL && pFrameWnd->m_bHelpMode)
- return FALSE;
-
- // since 'IsDialogMessage' will eat frame window accelerators,
- // we call all frame windows' PreTranslateMessage first
- while (pOwner != NULL)
- {
- // allow owner & frames to translate before IsDialogMessage does
- if (pOwner->PreTranslateMessage(pMsg))
- return TRUE;
-
- // try parent frames until there are no parent frames
- pOwner = pOwner->GetParentFrame();
- }
-
- // filter both messages to dialog and from children
- return PreTranslateInput(pMsg);
- }
-
- LRESULT CControlBar::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- ASSERT_VALID(this);
-
- LRESULT lResult;
- switch (nMsg)
- {
- case WM_NOTIFY:
- case WM_COMMAND:
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- case WM_DELETEITEM:
- case WM_COMPAREITEM:
- case WM_VKEYTOITEM:
- case WM_CHARTOITEM:
- // send these messages to the owner if not handled
- if (OnWndMsg(nMsg, wParam, lParam, &lResult))
- return lResult;
- else
- {
- // try owner next
- lResult = GetOwner()->SendMessage(nMsg, wParam, lParam);
-
- // special case for TTN_NEEDTEXTA and TTN_NEEDTEXTW
- if(nMsg == WM_NOTIFY)
- {
- NMHDR* pNMHDR = (NMHDR*)lParam;
- if (pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW)
- {
- TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
- TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
- if ((pNMHDR->code == TTN_NEEDTEXTA && (!pTTTA->lpszText || !*pTTTA->lpszText)) ||
- (pNMHDR->code == TTN_NEEDTEXTW && (!pTTTW->lpszText || !*pTTTW->lpszText)))
- {
- // not handled by owner, so let bar itself handle it
- lResult = CWnd::WindowProc(nMsg, wParam, lParam);
- }
- }
- }
- return lResult;
- }
- }
-
- // otherwise, just handle in default way
- lResult = CWnd::WindowProc(nMsg, wParam, lParam);
- return lResult;
- }
-
- LRESULT CControlBar::OnHelpHitTest(WPARAM, LPARAM lParam)
- {
- ASSERT_VALID(this);
-
- int nID = OnToolHitTest((DWORD)lParam, NULL);
- if (nID != -1)
- return HID_BASE_COMMAND+nID;
-
- nID = _AfxGetDlgCtrlID(m_hWnd);
- return nID != 0 ? HID_BASE_CONTROL+nID : 0;
- }
-
- void CControlBar::OnWindowPosChanging(LPWINDOWPOS lpWndPos)
- {
- // WINBUG: We call DefWindowProc here instead of CWnd::OnWindowPosChanging
- // (which calls CWnd::Default, which calls through the super wndproc)
- // because certain control bars that are system implemented (such as
- // CToolBar with TBSTYLE_FLAT) do not implement WM_WINDOWPOSCHANGING
- // correctly, causing repaint problems. This code bypasses that whole
- // mess.
- ::DefWindowProc(m_hWnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)lpWndPos);
-
- if (lpWndPos->flags & SWP_NOSIZE)
- return;
-
- // invalidate borders on the right
- CRect rect;
- GetWindowRect(&rect);
- CSize sizePrev = rect.Size();
- int cx = lpWndPos->cx;
- int cy = lpWndPos->cy;
- if (cx != sizePrev.cx && (m_dwStyle & CBRS_BORDER_RIGHT))
- {
- rect.SetRect(cx-afxData.cxBorder2, 0, cx, cy);
- InvalidateRect(&rect);
- rect.SetRect(sizePrev.cx-afxData.cxBorder2, 0, sizePrev.cx, cy);
- InvalidateRect(&rect);
- }
-
- // invalidate borders on the bottom
- if (cy != sizePrev.cy && (m_dwStyle & CBRS_BORDER_BOTTOM))
- {
- rect.SetRect(0, cy-afxData.cyBorder2, cx, cy);
- InvalidateRect(&rect);
- rect.SetRect(0, sizePrev.cy-afxData.cyBorder2, cx, sizePrev.cy);
- InvalidateRect(&rect);
- }
- }
-
- int CControlBar::OnCreate(LPCREATESTRUCT lpcs)
- {
- if (CWnd::OnCreate(lpcs) == -1)
- return -1;
-
- if (m_dwStyle & CBRS_TOOLTIPS)
- EnableToolTips();
-
- CFrameWnd *pFrameWnd = (CFrameWnd*)GetParent();
- if (pFrameWnd->IsFrameWnd())
- {
- m_pDockSite = pFrameWnd;
- m_pDockSite->AddControlBar(this);
- }
- return 0;
- }
-
- void CControlBar::OnDestroy()
- {
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- if (pThreadState->m_pLastStatus == this)
- {
- SetStatusText(-1);
- ASSERT(pThreadState->m_pLastStatus == NULL);
- }
-
- if (m_pDockSite != NULL)
- {
- m_pDockSite->RemoveControlBar(this);
- m_pDockSite = NULL;
- }
-
- CWnd::OnDestroy();
- }
-
- BOOL CControlBar::DestroyWindow()
- {
- if (m_hWnd != NULL && IsFloating())
- return GetDockingFrame()->DestroyWindow();
- else
- return CWnd::DestroyWindow();
- }
-
- int CControlBar::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT nMsg)
- {
- // call default when toolbar is not floating
- if (!IsFloating())
- return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, nMsg);
-
- // special behavior when floating
- ActivateTopParent();
-
- return MA_NOACTIVATE; // activation already done
- }
-
- void CControlBar::OnPaint()
- {
- // background is already filled in gray
- CPaintDC dc(this);
-
- // erase background now
- if (IsVisible())
- DoPaint(&dc); // delegate to paint helper
- }
-
- void CControlBar::EraseNonClient()
- {
- // get window DC that is clipped to the non-client area
- CWindowDC dc(this);
- CRect rectClient;
- GetClientRect(rectClient);
- CRect rectWindow;
- GetWindowRect(rectWindow);
- ScreenToClient(rectWindow);
- rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
- dc.ExcludeClipRect(rectClient);
-
- // draw borders in non-client area
- rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
- DrawBorders(&dc, rectWindow);
-
- // erase parts not drawn
- dc.IntersectClipRect(rectWindow);
- SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
-
- // draw gripper in non-client area
- DrawGripper(&dc, rectWindow);
- }
-
- HBRUSH CControlBar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (HBRUSH)lResult; // eat it
-
- // force black text on gray background all the time
- if (!GrayCtlColor(pDC->m_hDC, pWnd->GetSafeHwnd(), nCtlColor,
- afxData.hbrBtnFace, afxData.clrBtnText))
- return (HBRUSH)Default();
- return afxData.hbrBtnFace;
- }
-
- void CControlBar::OnLButtonDown(UINT nFlags, CPoint pt)
- {
- // only start dragging if clicked in "void" space
- if (m_pDockBar != NULL && OnToolHitTest(pt, NULL) == -1)
- {
- // start the drag
- ASSERT(m_pDockContext != NULL);
- ClientToScreen(&pt);
- m_pDockContext->StartDrag(pt);
- }
- else
- {
- CWnd::OnLButtonDown(nFlags, pt);
- }
- }
-
- void CControlBar::OnLButtonDblClk(UINT nFlags, CPoint pt)
- {
- // only toggle docking if clicked in "void" space
- if (m_pDockBar != NULL && OnToolHitTest(pt, NULL) == -1)
- {
- // start the drag
- ASSERT(m_pDockContext != NULL);
- m_pDockContext->ToggleDocking();
- }
- else
- {
- CWnd::OnLButtonDblClk(nFlags, pt);
- }
- }
-
- LRESULT CControlBar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM)
- {
- // handle delay hide/show
- BOOL bVis = GetStyle() & WS_VISIBLE;
- UINT swpFlags = 0;
- if ((m_nStateFlags & delayHide) && bVis)
- swpFlags = SWP_HIDEWINDOW;
- else if ((m_nStateFlags & delayShow) && !bVis)
- swpFlags = SWP_SHOWWINDOW;
- m_nStateFlags &= ~(delayShow|delayHide);
- if (swpFlags != 0)
- {
- SetWindowPos(NULL, 0, 0, 0, 0, swpFlags|
- SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
- }
-
- // the style must be visible and if it is docked
- // the dockbar style must also be visible
- if ((GetStyle() & WS_VISIBLE) &&
- (m_pDockBar == NULL || (m_pDockBar->GetStyle() & WS_VISIBLE)))
- {
- CFrameWnd* pTarget = (CFrameWnd*)GetOwner();
- if (pTarget == NULL || !pTarget->IsFrameWnd())
- pTarget = GetParentFrame();
- if (pTarget != NULL)
- OnUpdateCmdUI(pTarget, (BOOL)wParam);
- }
- return 0L;
- }
-
- void CControlBar::OnInitialUpdate()
- {
- // update the indicators before becoming visible
- OnIdleUpdateCmdUI(TRUE, 0L);
- }
-
- DWORD CControlBar::RecalcDelayShow(AFX_SIZEPARENTPARAMS* lpLayout)
- {
- ASSERT(lpLayout != NULL);
-
- // resize and reposition this control bar based on styles
- DWORD dwStyle = (m_dwStyle & (CBRS_ALIGN_ANY|CBRS_BORDER_ANY)) |
- (GetStyle() & WS_VISIBLE);
-
- // handle delay hide/show
- if (m_nStateFlags & (delayHide|delayShow))
- {
- UINT swpFlags = 0;
- if (m_nStateFlags & delayHide)
- {
- ASSERT((m_nStateFlags & delayShow) == 0);
- if (dwStyle & WS_VISIBLE)
- swpFlags = SWP_HIDEWINDOW;
- }
- else
- {
- ASSERT(m_nStateFlags & delayShow);
- if ((dwStyle & WS_VISIBLE) == 0)
- swpFlags = SWP_SHOWWINDOW;
- }
- if (swpFlags != 0)
- {
- // make the window seem visible/hidden
- dwStyle ^= WS_VISIBLE;
- if (lpLayout->hDWP != NULL)
- {
- // clear delay flags
- m_nStateFlags &= ~(delayShow|delayHide);
- // hide/show the window if actually doing layout
- lpLayout->hDWP = ::DeferWindowPos(lpLayout->hDWP, m_hWnd, NULL,
- 0, 0, 0, 0, swpFlags|
- SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
- }
- }
- else
- {
- // clear delay flags -- window is already in correct state
- m_nStateFlags &= ~(delayShow|delayHide);
- }
- }
- return dwStyle; // return new style
- }
-
- LRESULT CControlBar::OnSizeParent(WPARAM, LPARAM lParam)
- {
- AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
- DWORD dwStyle = RecalcDelayShow(lpLayout);
-
- if ((dwStyle & WS_VISIBLE) && (dwStyle & CBRS_ALIGN_ANY) != 0)
- {
- // align the control bar
- CRect rect;
- rect.CopyRect(&lpLayout->rect);
-
- CSize sizeAvail = rect.Size(); // maximum size available
-
- // get maximum requested size
- DWORD dwMode = lpLayout->bStretch ? LM_STRETCH : 0;
- if ((m_dwStyle & CBRS_SIZE_DYNAMIC) && m_dwStyle & CBRS_FLOATING)
- dwMode |= LM_HORZ | LM_MRUWIDTH;
- else if (dwStyle & CBRS_ORIENT_HORZ)
- dwMode |= LM_HORZ | LM_HORZDOCK;
- else
- dwMode |= LM_VERTDOCK;
-
- CSize size = CalcDynamicLayout(-1, dwMode);
-
- size.cx = min(size.cx, sizeAvail.cx);
- size.cy = min(size.cy, sizeAvail.cy);
-
- if (dwStyle & CBRS_ORIENT_HORZ)
- {
- lpLayout->sizeTotal.cy += size.cy;
- lpLayout->sizeTotal.cx = max(lpLayout->sizeTotal.cx, size.cx);
- if (dwStyle & CBRS_ALIGN_TOP)
- lpLayout->rect.top += size.cy;
- else if (dwStyle & CBRS_ALIGN_BOTTOM)
- {
- rect.top = rect.bottom - size.cy;
- lpLayout->rect.bottom -= size.cy;
- }
- }
- else if (dwStyle & CBRS_ORIENT_VERT)
- {
- lpLayout->sizeTotal.cx += size.cx;
- lpLayout->sizeTotal.cy = max(lpLayout->sizeTotal.cy, size.cy);
- if (dwStyle & CBRS_ALIGN_LEFT)
- lpLayout->rect.left += size.cx;
- else if (dwStyle & CBRS_ALIGN_RIGHT)
- {
- rect.left = rect.right - size.cx;
- lpLayout->rect.right -= size.cx;
- }
- }
- else
- {
- ASSERT(FALSE); // can never happen
- }
-
- rect.right = rect.left + size.cx;
- rect.bottom = rect.top + size.cy;
-
- // only resize the window if doing layout and not just rect query
- if (lpLayout->hDWP != NULL)
- AfxRepositionWindow(lpLayout, m_hWnd, &rect);
- }
- return 0;
- }
-
- void CControlBar::DelayShow(BOOL bShow)
- {
- m_nStateFlags &= ~(delayHide|delayShow);
- if (bShow && (GetStyle() & WS_VISIBLE) == 0)
- m_nStateFlags |= delayShow;
- else if (!bShow && (GetStyle() & WS_VISIBLE) != 0)
- m_nStateFlags |= delayHide;
- }
-
- BOOL CControlBar::IsVisible() const
- {
- if (m_nStateFlags & delayHide)
- return FALSE;
-
- if ((m_nStateFlags & delayShow) || ((GetStyle() & WS_VISIBLE) != 0))
- return TRUE;
-
- return FALSE;
- }
-
- void CControlBar::DoPaint(CDC* pDC)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDC);
-
- // paint inside client area
- CRect rect;
- GetClientRect(rect);
- DrawBorders(pDC, rect);
- DrawGripper(pDC, rect);
- }
-
- void CControlBar::DrawBorders(CDC* pDC, CRect& rect)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDC);
-
- DWORD dwStyle = m_dwStyle;
- if (!(dwStyle & CBRS_BORDER_ANY))
- return;
-
- // prepare for dark lines
- ASSERT(rect.top == 0 && rect.left == 0);
- CRect rect1, rect2;
- rect1 = rect;
- rect2 = rect;
- COLORREF clr = afxData.bWin4 ? afxData.clrBtnShadow : afxData.clrWindowFrame;
-
- // draw dark line one pixel back/up
- if (dwStyle & CBRS_BORDER_3D)
- {
- rect1.right -= CX_BORDER;
- rect1.bottom -= CY_BORDER;
- }
- if (dwStyle & CBRS_BORDER_TOP)
- rect2.top += afxData.cyBorder2;
- if (dwStyle & CBRS_BORDER_BOTTOM)
- rect2.bottom -= afxData.cyBorder2;
-
- // draw left and top
- if (dwStyle & CBRS_BORDER_LEFT)
- pDC->FillSolidRect(0, rect2.top, CX_BORDER, rect2.Height(), clr);
- if (dwStyle & CBRS_BORDER_TOP)
- pDC->FillSolidRect(0, 0, rect.right, CY_BORDER, clr);
-
- // draw right and bottom
- if (dwStyle & CBRS_BORDER_RIGHT)
- pDC->FillSolidRect(rect1.right, rect2.top, -CX_BORDER, rect2.Height(), clr);
- if (dwStyle & CBRS_BORDER_BOTTOM)
- pDC->FillSolidRect(0, rect1.bottom, rect.right, -CY_BORDER, clr);
-
- if (dwStyle & CBRS_BORDER_3D)
- {
- // prepare for hilite lines
- clr = afxData.clrBtnHilite;
-
- // draw left and top
- if (dwStyle & CBRS_BORDER_LEFT)
- pDC->FillSolidRect(1, rect2.top, CX_BORDER, rect2.Height(), clr);
- if (dwStyle & CBRS_BORDER_TOP)
- pDC->FillSolidRect(0, 1, rect.right, CY_BORDER, clr);
-
- // draw right and bottom
- if (dwStyle & CBRS_BORDER_RIGHT)
- pDC->FillSolidRect(rect.right, rect2.top, -CX_BORDER, rect2.Height(), clr);
- if (dwStyle & CBRS_BORDER_BOTTOM)
- pDC->FillSolidRect(0, rect.bottom, rect.right, -CY_BORDER, clr);
- }
-
- if (dwStyle & CBRS_BORDER_LEFT)
- rect.left += afxData.cxBorder2;
- if (dwStyle & CBRS_BORDER_TOP)
- rect.top += afxData.cyBorder2;
- if (dwStyle & CBRS_BORDER_RIGHT)
- rect.right -= afxData.cxBorder2;
- if (dwStyle & CBRS_BORDER_BOTTOM)
- rect.bottom -= afxData.cyBorder2;
- }
-
- #define CX_GRIPPER 3
- #define CY_GRIPPER 3
- #define CX_BORDER_GRIPPER 2
- #define CY_BORDER_GRIPPER 2
-
- void CControlBar::DrawGripper(CDC* pDC, const CRect& rect)
- {
- // only draw the gripper if not floating and gripper is specified
- if ((m_dwStyle & (CBRS_GRIPPER|CBRS_FLOATING)) == CBRS_GRIPPER)
- {
- // draw the gripper in the border
- if (m_dwStyle & CBRS_ORIENT_HORZ)
- {
- pDC->Draw3dRect(rect.left+CX_BORDER_GRIPPER,
- rect.top+m_cyTopBorder,
- CX_GRIPPER, rect.Height()-m_cyTopBorder-m_cyBottomBorder,
- afxData.clrBtnHilite, afxData.clrBtnShadow);
- }
- else
- {
- pDC->Draw3dRect(rect.left+m_cyTopBorder,
- rect.top+CY_BORDER_GRIPPER,
- rect.Width()-m_cyTopBorder-m_cyBottomBorder, CY_GRIPPER,
- afxData.clrBtnHilite, afxData.clrBtnShadow);
- }
- }
- }
-
- // input CRect should be client rectangle size
- void CControlBar::CalcInsideRect(CRect& rect, BOOL bHorz) const
- {
- ASSERT_VALID(this);
- DWORD dwStyle = m_dwStyle;
-
- if (dwStyle & CBRS_BORDER_LEFT)
- rect.left += afxData.cxBorder2;
- if (dwStyle & CBRS_BORDER_TOP)
- rect.top += afxData.cyBorder2;
- if (dwStyle & CBRS_BORDER_RIGHT)
- rect.right -= afxData.cxBorder2;
- if (dwStyle & CBRS_BORDER_BOTTOM)
- rect.bottom -= afxData.cyBorder2;
-
- // inset the top and bottom.
- if (bHorz)
- {
- rect.left += m_cxLeftBorder;
- rect.top += m_cyTopBorder;
- rect.right -= m_cxRightBorder;
- rect.bottom -= m_cyBottomBorder;
- if ((m_dwStyle & (CBRS_GRIPPER|CBRS_FLOATING)) == CBRS_GRIPPER)
- rect.left += CX_BORDER_GRIPPER+CX_GRIPPER+CX_BORDER_GRIPPER;
- }
- else
- {
- rect.left += m_cyTopBorder;
- rect.top += m_cxLeftBorder;
- rect.right -= m_cyBottomBorder;
- rect.bottom -= m_cxRightBorder;
- if ((m_dwStyle & (CBRS_GRIPPER|CBRS_FLOATING)) == CBRS_GRIPPER)
- rect.top += CY_BORDER_GRIPPER+CY_GRIPPER+CY_BORDER_GRIPPER;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CControlBar diagnostics
-
- #ifdef _DEBUG
- void CControlBar::AssertValid() const
- {
- CWnd::AssertValid();
-
- ASSERT(m_nCount == 0 || m_pData != NULL);
- ASSERT((m_dwStyle & CBRS_ALL) == m_dwStyle);
- }
-
- void CControlBar::Dump(CDumpContext& dc) const
- {
- CWnd::Dump(dc);
-
- dc << "\nm_cxLeftBorder = " << m_cxLeftBorder;
- dc << "\nm_cxRightBorder = " << m_cxRightBorder;
- dc << "\nm_cyTopBorder = " << m_cyTopBorder;
- dc << "\nm_cyBottomBorder = " << m_cyBottomBorder;
- dc << "\nm_cxDefaultGap = " << m_cxDefaultGap;
- dc << "\nm_nCount = " << m_nCount;
- dc << "\nm_bAutoDelete = " << m_bAutoDelete;
-
- dc << "\n";
- }
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
-