home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and Microsoft
- // QuickHelp and/or WinHelp 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 BASED_CODE THIS_FILE[] = __FILE__;
- #define new DEBUG_NEW
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
-
- // the CBRS_ style is made up of an alignment style and a draw border style
- // the alignment styles are mutually exclusive
- // the draw border styles may be combined
- #define ALIGN_ANY 0xF000
- #define ALIGN_LEFT 0x1000
- #define ALIGN_TOP 0x2000
- #define ALIGN_RIGHT 0x4000
- #define ALIGN_BOTTOM 0x8000
- #define BORDER_ANY 0x0F00
- #define BORDER_LEFT 0x0100
- #define BORDER_TOP 0x0200
- #define BORDER_RIGHT 0x0400
- #define BORDER_BOTTOM 0x0800
-
- /////////////////////////////////////////////////////////////////////////////
- // CControlBar
-
- IMPLEMENT_DYNAMIC(CControlBar, CWnd)
-
- BEGIN_MESSAGE_MAP(CControlBar, CWnd)
- //{{AFX_MSG_MAP(CControlBar)
- ON_WM_PAINT()
- ON_WM_CTLCOLOR()
- ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
- ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate)
- ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
- ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- CControlBar::CControlBar()
- {
- m_sizeFixedLayout.cx = 32767; // fill available space
- m_sizeFixedLayout.cy = 32767; // fill available space
- m_nCount = 0;
- m_pData = NULL;
- // set up some default border spacings
- m_cxLeftBorder = 8;
- m_cxDefaultGap = 2;
- m_cyTopBorder = m_cyBottomBorder = 1;
- m_bAutoDelete = FALSE;
- }
-
- BOOL CControlBar::AllocElements(int nElements, int cbElement)
- {
- ASSERT_VALID(this);
- ASSERT(nElements > 0 && cbElement > 0);
- if (m_pData != NULL)
- {
- ASSERT(m_nCount != 0);
- free(m_pData); // free old data
- }
- else
- {
- // no initialized yet
- ASSERT(m_nCount == 0);
- }
-
- if ((m_pData = calloc(nElements, cbElement)) == NULL)
- return FALSE;
- 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
- // free array
- if (m_pData != NULL)
- {
- ASSERT(m_nCount != 0);
- free(m_pData);
- }
- }
-
- void CControlBar::PostNcDestroy()
- {
- if (m_bAutoDelete) // Automatic cleanup?
- delete this;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // Default control bar processing
-
- BOOL CControlBar::PreTranslateMessage(MSG* pMsg)
- {
- ASSERT_VALID(this);
- // act like a modeless dialog
- ASSERT(m_hWnd != NULL);
-
- // don't translate dialog messages when in Shift+F1 help mode
- if (AfxGetApp()->m_bHelpMode)
- return FALSE;
-
- // since 'IsDialogMessage' will eat frame window accelerators,
- // we call the frame window's PreTranslateMessage first
- CWnd* pFrame;
- if ((pFrame = GetParentFrame()) != NULL)
- {
- if (pFrame->PreTranslateMessage(pMsg))
- return TRUE; // eaten by frame accelerator
- // check for parent of the frame in case of MDI
- if ((pFrame = pFrame->GetParentFrame()) != NULL &&
- pFrame->PreTranslateMessage(pMsg))
- return TRUE; // eaten by frame accelerator
- }
-
- // filter both messages to dialog and from children
- return ::IsDialogMessage(m_hWnd, pMsg);
- }
-
- LRESULT CControlBar::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- ASSERT_VALID(this);
-
- // parent notification messages are just passed to parent of control bar
- switch (nMsg)
- {
- case WM_COMMAND:
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- case WM_DELETEITEM:
- case WM_COMPAREITEM:
- case WM_VKEYTOITEM:
- case WM_CHARTOITEM:
- case WM_VBXEVENT:
- return ::SendMessage(::GetParent(m_hWnd), nMsg, wParam, lParam);
- }
- return CWnd::WindowProc(nMsg, wParam, lParam);
- }
-
- LRESULT CControlBar::OnHelpHitTest(WPARAM, LPARAM)
- {
- ASSERT_VALID(this);
-
- UINT nID = _AfxGetDlgCtrlID(m_hWnd);
- if (nID != 0)
- return HID_BASE_CONTROL+nID;
- else
- return 0;
- }
-
-
- void CControlBar::OnPaint()
- {
- // background is already filled in grey
- CPaintDC dc(this);
- DoPaint(&dc); // delegate to paint helper
- }
-
- HBRUSH CControlBar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (HBRUSH)lResult; // eat it
-
- // force black text on grey background all the time
- if (!GrayCtlColor(pDC->m_hDC, pWnd->GetSafeHwnd(), nCtlColor,
- afxData.hbrBtnFace, afxData.clrBtnText))
- return (HBRUSH)Default();
- return afxData.hbrBtnFace;
- }
-
- LRESULT CControlBar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM)
- {
- if (GetStyle() & WS_VISIBLE) // ignore if child is invisible
- {
- CFrameWnd* pTarget = GetParentFrame();
- if (pTarget != NULL)
- OnUpdateCmdUI(pTarget, (BOOL)wParam);
- }
- return 0L;
- }
-
- void CControlBar::OnInitialUpdate()
- {
- // update the indicators before becoming visible
- OnIdleUpdateCmdUI((WPARAM)TRUE, 0L);
- }
-
- LRESULT CControlBar::OnSizeParent(WPARAM, LPARAM lParam)
- {
- AFX_SIZEPARENTPARAMS FAR* lpLayout = (AFX_SIZEPARENTPARAMS FAR*)lParam;
-
- ASSERT(CBRS_NOALIGN == 0);
- ASSERT(CBRS_LEFT == (ALIGN_LEFT | BORDER_RIGHT));
- ASSERT(CBRS_RIGHT == (ALIGN_RIGHT | BORDER_LEFT));
- ASSERT(CBRS_TOP == (ALIGN_TOP | BORDER_BOTTOM));
- ASSERT(CBRS_BOTTOM == (ALIGN_BOTTOM | BORDER_TOP));
-
- // resize and reposition this control bar based on styles
- DWORD dwStyle = GetStyle();
-
- if ((dwStyle & WS_VISIBLE) && (dwStyle & ALIGN_ANY) != 0)
- {
- // align the control bar
- CRect rect;
- rect.CopyRect(&lpLayout->rect);
-
- CSize sizeAvail = rect.Size(); // maximum size available
- CSize size; // maximum requested size
- size.cx = min(m_sizeFixedLayout.cx, sizeAvail.cx);
- size.cy = min(m_sizeFixedLayout.cy, sizeAvail.cy);
-
- if (dwStyle & ALIGN_LEFT)
- {
- // left align (stretch height)
- size.cy = sizeAvail.cy;
- lpLayout->rect.left += size.cx;
- }
- else if (dwStyle & ALIGN_TOP)
- {
- // top align (stretch width)
- size.cx = sizeAvail.cx;
- lpLayout->rect.top += size.cy;
- }
- else if (dwStyle & ALIGN_RIGHT)
- {
- // right align (stretch height)
- size.cy = sizeAvail.cy;
- rect.left = rect.right - size.cx;
- lpLayout->rect.right -= size.cx;
- }
- else if (dwStyle & ALIGN_BOTTOM)
- {
- // bottom align (stretch width)
- size.cx = sizeAvail.cx;
- rect.top = rect.bottom - size.cy;
- lpLayout->rect.bottom -= size.cy;
- }
- else
- {
- ASSERT(FALSE); // can never happen
- }
-
- rect.right = rect.left + size.cx;
- rect.bottom = rect.top + size.cy;
- _AfxRepositionWindow(lpLayout, m_hWnd, &rect);
- }
- return 0;
- }
-
- void CControlBar::DoPaint(CDC* pDC)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDC);
-
- DWORD dwStyle = GetStyle();
- if (dwStyle & BORDER_ANY)
- {
- // draw border line on sides
- CRect rect;
- GetClientRect(&rect);
- ASSERT(rect.top == 0 && rect.left == 0);
- HBRUSH hbrFrame = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME));
- if (hbrFrame != NULL)
- {
- HGDIOBJ hOldBrush = pDC->SelectObject(hbrFrame);
- if (hOldBrush != NULL)
- {
- if (dwStyle & BORDER_LEFT)
- pDC->PatBlt(0, 0, CX_BORDER, rect.bottom, PATCOPY);
- if (dwStyle & BORDER_TOP)
- pDC->PatBlt(0, 0, rect.right, CY_BORDER, PATCOPY);
- if (dwStyle & BORDER_RIGHT)
- pDC->PatBlt(rect.right, 0, -CX_BORDER, rect.bottom,
- PATCOPY);
- if (dwStyle & BORDER_BOTTOM)
- pDC->PatBlt(0, rect.bottom, rect.right, -CY_BORDER,
- PATCOPY);
- pDC->SelectObject(hOldBrush);
- }
- DeleteObject(hbrFrame);
- }
- }
- }
-
- // input CRect should be client rectangle size
- void CControlBar::CalcInsideRect(CRect& rect) const
- {
- ASSERT_VALID(this);
- DWORD dwStyle = GetStyle();
-
- // adjust for border size
- if (dwStyle & BORDER_LEFT)
- rect.left += CX_BORDER;
- if (dwStyle & BORDER_TOP)
- rect.top += CY_BORDER;
- if (dwStyle & BORDER_RIGHT)
- rect.right -= CX_BORDER;
- if (dwStyle & BORDER_BOTTOM)
- rect.bottom -= CY_BORDER;
-
- // inset the top and bottom.
- rect.left += m_cxLeftBorder;
- rect.top += m_cyTopBorder;
- rect.bottom -= m_cyBottomBorder;
- }
-
-
- #ifdef _DEBUG
- void CControlBar::AssertValid() const
- {
- CWnd::AssertValid();
- ASSERT(m_nCount == 0 || m_pData != NULL);
- }
-
- void CControlBar::Dump(CDumpContext& dc) const
- {
- CWnd::Dump(dc);
- AFX_DUMP1(dc, "\nborder offset = ", m_cxLeftBorder);
- AFX_DUMP1(dc, "\nm_cyTopBorder = ", m_cyTopBorder);
- AFX_DUMP1(dc, "\nm_cyBottomBorder = ", m_cyBottomBorder);
- AFX_DUMP1(dc, "\ndefault gap = ", m_cxDefaultGap);
- AFX_DUMP1(dc, "\nfixed layout size = ", m_sizeFixedLayout);
- AFX_DUMP1(dc, "\n# of non HWND elements = ", m_nCount);
- AFX_DUMP1(dc, "\nm_bAutoDelete = ", m_bAutoDelete);
- }
- #endif
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CStatusBar creation etc
-
- struct AFX_STATUSPANE
- {
- UINT nID; // IDC of indicator: 0 => normal text area
- UINT nStyle; // style flags (SBPS_*)
- int cxText; // width of string area in pixels
- // on both sides there is a 1 pixel gap and
- // a one pixel border, making a pane 4 pixels wider
- LPCSTR lpszText; // always far strings
- };
-
- inline AFX_STATUSPANE* CStatusBar::_GetPanePtr(int nIndex) const
- {
- ASSERT(nIndex >= 0 && nIndex < m_nCount);
- ASSERT(m_pData != NULL);
- return ((AFX_STATUSPANE*)m_pData) + nIndex;
- }
-
- IMPLEMENT_DYNAMIC(CStatusBar, CControlBar)
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- CStatusBar::CStatusBar()
- {
- m_hFont = NULL;
- m_cxRightBorder = m_cxDefaultGap;
-
- if (afxData.hStatusFont == NULL)
- {
- // load status bar font
- LOGFONT logfont;
- memset(&logfont, 0, sizeof(logfont));
-
- // 10 point height Sans Serif font
- logfont.lfHeight = -MulDiv(10, afxData.cyPixelsPerInch, 72);
- logfont.lfWeight = FW_NORMAL;
- logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
- static char BASED_CODE szFaceName[] = "MS Sans Serif";
- lstrcpy(logfont.lfFaceName, szFaceName);
- if ((afxData.hStatusFont = ::CreateFontIndirect(&logfont)) == NULL)
- {
- TRACE0("Warning: Using system font for status font\n");
- afxData.hStatusFont = (HFONT)::GetStockObject(SYSTEM_FONT);
- }
- }
- }
-
- CStatusBar::~CStatusBar()
- {
- // free strings before freeing array of elements
- for (int i = 0; i < m_nCount; i++)
- VERIFY(SetPaneText(i, NULL, FALSE)); // no update
- }
-
- BOOL CStatusBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
- {
- ASSERT_VALID(pParentWnd); // must have a parent
-
- // create the HWND
- CRect rect;
- rect.SetRectEmpty();
- if (!CWnd::Create(_afxWndControlBar, NULL, dwStyle, rect, pParentWnd, nID))
- return FALSE;
- // NOTE: Parent must resize itself for control bar to be resized
-
- // set initial font and calculate bar height
- OnSetFont((WPARAM)afxData.hStatusFont, 0); // initialize font height etc
- return TRUE;
- }
-
- BOOL CStatusBar::SetIndicators(const UINT FAR* lpIDArray, int nIDCount)
- {
- ASSERT_VALID(this);
- ASSERT(nIDCount >= 1); // must be at least one of them
- ASSERT(lpIDArray == NULL ||
- AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));
-
- // first allocate array for panes and copy initial data
- if (!AllocElements(nIDCount, sizeof(AFX_STATUSPANE)))
- return FALSE;
- ASSERT(nIDCount == m_nCount);
-
- BOOL bOK = TRUE;
- if (lpIDArray != NULL)
- {
- ASSERT(m_hFont != NULL); // must have a font !
- CString strText;
- CClientDC dcScreen(NULL);
- HGDIOBJ hOldFont = dcScreen.SelectObject(m_hFont);
- for (int i = 0; i < nIDCount; i++)
- {
- AFX_STATUSPANE* pSBP = _GetPanePtr(i);
- if ((pSBP->nID = *lpIDArray++) != 0)
- {
- if (!strText.LoadString(pSBP->nID))
- {
- TRACE1("Warning: failed to load indicator string 0x%04X\n",
- pSBP->nID);
- bOK = FALSE;
- break;
- }
- pSBP->cxText = dcScreen.GetTextExtent(strText,
- strText.GetLength()).cx;
- ASSERT(pSBP->cxText >= 0);
- if (!SetPaneText(i, strText, FALSE))
- {
- bOK = FALSE;
- break;
- }
- }
- else
- {
- // no indicator (must access via index)
- // default to 1/4 the screen width (first pane is stretchy)
- pSBP->cxText = ::GetSystemMetrics(SM_CXSCREEN) / 4;
- if (i == 0)
- pSBP->nStyle |= (SBPS_STRETCH | SBPS_NOBORDERS);
- }
- }
- dcScreen.SelectObject(hOldFont);
- }
- return bOK;
- }
-
- #ifdef AFX_CORE3_SEG
- #pragma code_seg(AFX_CORE3_SEG)
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // CStatusBar attribute access
-
- int CStatusBar::CommandToIndex(UINT nIDFind) const
- {
- ASSERT_VALID(this);
- AFX_STATUSPANE* pSBP = _GetPanePtr(0);
- for (int i = 0; i < m_nCount; i++, pSBP++)
- if (pSBP->nID == nIDFind)
- return i;
- return -1;
- }
-
- UINT CStatusBar::GetItemID(int nIndex) const
- {
- ASSERT_VALID(this);
- return _GetPanePtr(nIndex)->nID;
- }
-
- void CStatusBar::GetItemRect(int nIndex, LPRECT lpRect) const
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
-
- // return rectangle containing inset size
- ASSERT(nIndex >= 0 && nIndex < m_nCount);
- AFX_STATUSPANE* pSBP;
- int i;
-
- CRect rect;
- GetClientRect(rect);
- CalcInsideRect(rect);
-
- int cxExtra = rect.Width() - m_cxRightBorder + m_cxDefaultGap;
- // first walk through to calculate extra space
- for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
- cxExtra -= (pSBP->cxText + CX_BORDER * 4 + m_cxDefaultGap);
- // if cxExtra <= 0 then we will not stretch but just clip
-
- for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
- {
- ASSERT(pSBP->cxText >= 0);
- int cxText = pSBP->cxText;
- if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
- {
- cxText += cxExtra;
- cxExtra = 0;
- }
- rect.right = rect.left + cxText + CX_BORDER * 4;
- if (i == nIndex)
- break; // stop with correct rectangle (includes border)
- rect.left = rect.right + m_cxDefaultGap;
- }
- ASSERT(i == nIndex);
- *lpRect = rect;
- }
-
- inline UINT CStatusBar::_GetPaneStyle(int nIndex) const
- {
- return _GetPanePtr(nIndex)->nStyle;
- }
-
- void CStatusBar::_SetPaneStyle(int nIndex, UINT nStyle)
- {
- AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
- if (pSBP->nStyle != nStyle)
- {
- // just change the style of 1 pane, and invalidate it
- pSBP->nStyle = nStyle;
- CRect rect;
- GetItemRect(nIndex, &rect);
- InvalidateRect(rect);
- }
- }
-
- void CStatusBar::GetPaneInfo(int nIndex, UINT& nID, UINT& nStyle,
- int& cxWidth) const
- {
- ASSERT_VALID(this);
-
- AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
- nID = pSBP->nID;
- nStyle = pSBP->nStyle;
- cxWidth = pSBP->cxText;
- }
-
- void CStatusBar::SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth)
- {
- ASSERT_VALID(this);
-
- AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
- pSBP->nID = nID;
- _SetPaneStyle(nIndex, nStyle); // single pane invalidate
- if (cxWidth != pSBP->cxText)
- {
- // change width of one pane -> invalidate the entire status bar
- pSBP->cxText = cxWidth;
- Invalidate();
- }
- }
-
- void CStatusBar::GetPaneText(int nIndex, CString& s) const
- {
- ASSERT_VALID(this);
-
- AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
- s = pSBP->lpszText;
- }
-
- BOOL CStatusBar::SetPaneText(int nIndex, LPCSTR lpszNewText, BOOL bUpdate)
- {
- ASSERT_VALID(this);
-
- AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
- if (pSBP == NULL)
- return FALSE;
-
- if (pSBP->lpszText != NULL)
- {
- if (lpszNewText != NULL && lstrcmp(pSBP->lpszText, lpszNewText) == 0)
- return TRUE; // nothing to change
- _ffree((LPVOID)pSBP->lpszText);
- }
-
- BOOL bOK = TRUE;
- if (lpszNewText == NULL || *lpszNewText == '\0')
- {
- pSBP->lpszText = NULL;
- }
- else
- {
- pSBP->lpszText = _fstrdup(lpszNewText);
- if (pSBP->lpszText == NULL)
- bOK = FALSE; // old text is lost and replaced by NULL
- }
-
- if (bUpdate)
- {
- // invalidate the text of the pane - but not the border
- CRect rect;
- GetItemRect(nIndex, &rect);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- InvalidateRect(rect);
- }
- return bOK;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CStatusBar implementation
-
- void CStatusBar::DoPaint(CDC* pDC)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDC);
-
- CControlBar::DoPaint(pDC); // draw border
- CRect rect;
- GetClientRect(rect);
- CalcInsideRect(rect);
-
- AFX_STATUSPANE* pSBP;
- int i;
-
- ASSERT(m_hFont != NULL); // must have a font !
- HGDIOBJ hOldFont = pDC->SelectObject(m_hFont);
-
- int cxExtra = rect.Width() - m_cxRightBorder + m_cxDefaultGap;
- // first walk through to calculate extra space
- for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
- cxExtra -= (pSBP->cxText + CX_BORDER * 4 + m_cxDefaultGap);
- // if cxExtra <= 0 then we will not stretch but just clip
-
- for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
- {
- ASSERT(pSBP->cxText >= 0);
- int cxText = pSBP->cxText;
- if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
- {
- cxText += cxExtra;
- cxExtra = 0;
- }
- rect.right = rect.left + cxText + CX_BORDER * 4;
- if (::RectVisible(pDC->m_hDC, &rect))
- DrawStatusText(pDC->m_hDC, rect, pSBP->lpszText, pSBP->nStyle);
- rect.left = rect.right + m_cxDefaultGap;
- }
- pDC->SelectObject(hOldFont);
- }
-
- void PASCAL CStatusBar::DrawStatusText(HDC hDC, CRect const& rect,
- LPCSTR lpszText, UINT nStyle)
- {
- ASSERT(hDC != NULL);
-
- HBRUSH hbrHilite = NULL;
- HBRUSH hbrShadow = NULL;
- if (!(nStyle & SBPS_NOBORDERS))
- {
- if (nStyle & SBPS_POPOUT)
- {
- // reverse colors
- hbrHilite = afxData.hbrBtnShadow;
- hbrShadow = afxData.hbrBtnHilite;
- }
- else
- {
- // normal colors
- hbrHilite = afxData.hbrBtnHilite;
- hbrShadow = afxData.hbrBtnShadow;
- }
- }
-
- // background is already grey
- UINT nOpts = ETO_CLIPPED;
- int nOldMode = SetBkMode(hDC, TRANSPARENT);
- COLORREF crTextColor = SetTextColor(hDC, afxData.clrBtnText);
- COLORREF crBkColor = SetBkColor(hDC, afxData.clrBtnFace);
-
- // Draw the hilites
- if (hbrHilite != NULL)
- {
- HGDIOBJ hOldBrush = SelectObject(hDC, hbrHilite);
- if (hOldBrush)
- {
- PatBlt(hDC, rect.right, rect.bottom,
- -(rect.Width() - CX_BORDER),
- -CY_BORDER, PATCOPY);
- PatBlt(hDC, rect.right, rect.bottom,
- -CX_BORDER,
- -(rect.Height() - CY_BORDER), PATCOPY);
- SelectObject(hDC, hOldBrush);
- }
- }
-
- if (hbrShadow != NULL)
- {
- HGDIOBJ hOldBrush = SelectObject(hDC, hbrShadow);
- if (hOldBrush)
- {
- PatBlt(hDC, rect.left, rect.top,
- rect.Width(), CY_BORDER, PATCOPY);
- PatBlt(hDC, rect.left, rect.top,
- CX_BORDER, rect.Height(), PATCOPY);
- SelectObject(hDC, hOldBrush);
- }
- }
-
- // We need to adjust the rect for the ExtTextOut, and then adjust it back
-
- // just support left justified text
- if (lpszText != NULL && !(nStyle & SBPS_DISABLED))
- {
- CRect rectText(rect);
- rectText.InflateRect(-2*CX_BORDER, -CY_BORDER);
-
- // align on bottom (since descent is more important than ascent)
- SetTextAlign(hDC, TA_LEFT | TA_BOTTOM);
- ExtTextOut(hDC, rectText.left, rectText.bottom,
- nOpts, &rectText, lpszText, lstrlen(lpszText), NULL);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CStatusBar message handlers
-
- BEGIN_MESSAGE_MAP(CStatusBar, CControlBar)
- //{{AFX_MSG_MAP(CStatusBar)
- // control messages
- ON_WM_SIZE()
- ON_MESSAGE(WM_SETFONT, OnSetFont)
- ON_MESSAGE(WM_GETFONT, OnGetFont)
- ON_MESSAGE(WM_SETTEXT, OnSetText)
- ON_MESSAGE(WM_GETTEXT, OnGetText)
- ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- void CStatusBar::OnSize(UINT, int, int)
- {
- // force repaint on resize (recalculate stretchy)
- Invalidate();
- }
-
- LRESULT CStatusBar::OnSetFont(WPARAM wParam, LPARAM)
- {
- m_hFont = (HFONT)wParam;
- ASSERT(m_hFont != NULL);
-
- // recalculate based on font height + borders
- TEXTMETRIC tm;
- // get text metrics of font
- {
- CClientDC dcScreen(NULL);
- HGDIOBJ hOldFont = dcScreen.SelectObject(m_hFont);
- VERIFY(dcScreen.GetTextMetrics(&tm));
- dcScreen.SelectObject(hOldFont);
- }
- CRect rectSize;
- rectSize.SetRectEmpty();
- CalcInsideRect(rectSize); // will be negative size
- m_sizeFixedLayout.cy = (tm.tmHeight - tm.tmInternalLeading) +
- CY_BORDER*3 /* 1 extra on top, 2 on bottom */ - rectSize.Height();
- ASSERT(m_sizeFixedLayout.cx == 32767); // max size
-
- return 0L; // does not re-draw or invalidate - resize parent instead
- }
-
-
- LRESULT CStatusBar::OnGetFont(WPARAM, LPARAM)
- {
- return (LRESULT)(UINT)m_hFont;
- }
-
- LRESULT CStatusBar::OnSetText(WPARAM, LPARAM lParam)
- {
- return SetPaneText(0, (LPCSTR)lParam) ? 0 : -1;
- }
-
- LRESULT CStatusBar::OnGetText(WPARAM wParam, LPARAM lParam)
- {
- int nMaxLen = (int)wParam;
- if (nMaxLen == 0)
- return 0; // nothing copied
- LPSTR lpszDest = (LPSTR)lParam;
-
- AFX_STATUSPANE* pSBP = _GetPanePtr(0);
- int nLen = (pSBP != NULL && pSBP->lpszText != NULL) ?
- lstrlen(pSBP->lpszText) : 0;
- if (nLen > nMaxLen)
- nLen = nMaxLen - 1; // number of characters to copy (less term.)
- _fmemcpy(lpszDest, pSBP->lpszText, nLen);
- lpszDest[nLen] = '\0';
- return nLen+1; // number of bytes copied
- }
-
- LRESULT CStatusBar::OnGetTextLength(WPARAM, LPARAM)
- {
- AFX_STATUSPANE* pSBP = _GetPanePtr(0);
- return (pSBP != NULL && pSBP->lpszText != NULL) ?
- lstrlen(pSBP->lpszText) : 0;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CStatusBar idle update through CStatusCmdUI class
-
- class CStatusCmdUI : public CCmdUI // class private to this file !
- {
- public: // re-implementations only
- virtual void Enable(BOOL bOn);
- virtual void SetCheck(int nCheck);
- virtual void SetText(LPCSTR lpszText);
- };
-
- void CStatusCmdUI::Enable(BOOL bOn)
- {
- m_bEnableChanged = TRUE;
- CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
- ASSERT(pStatusBar != NULL);
- ASSERT(pStatusBar->IsKindOf(RUNTIME_CLASS(CStatusBar)));
- ASSERT(m_nIndex < m_nIndexMax);
-
- UINT nNewStyle = pStatusBar->_GetPaneStyle(m_nIndex) & ~SBPS_DISABLED;
- if (!bOn)
- nNewStyle |= SBPS_DISABLED;
- pStatusBar->_SetPaneStyle(m_nIndex, nNewStyle);
- }
-
- void CStatusCmdUI::SetCheck(int nCheck) // "checking" will pop out the text
- {
- CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
- ASSERT(pStatusBar != NULL);
- ASSERT(pStatusBar->IsKindOf(RUNTIME_CLASS(CStatusBar)));
- ASSERT(m_nIndex < m_nIndexMax);
-
- UINT nNewStyle = pStatusBar->_GetPaneStyle(m_nIndex) & ~SBPS_POPOUT;
- if (nCheck != 0)
- nNewStyle |= SBPS_POPOUT;
- pStatusBar->_SetPaneStyle(m_nIndex, nNewStyle);
- }
-
- void CStatusCmdUI::SetText(LPCSTR lpszText)
- {
- ASSERT(m_pOther != NULL);
- ASSERT(m_pOther->IsKindOf(RUNTIME_CLASS(CStatusBar)));
- ASSERT(m_nIndex < m_nIndexMax);
-
- ((CStatusBar*)m_pOther)->SetPaneText(m_nIndex, lpszText);
- }
-
- void CStatusBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
- {
- CStatusCmdUI state;
- state.m_pOther = this;
- state.m_nIndexMax = (UINT)m_nCount;
- for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
- state.m_nIndex++)
- {
- state.m_nID = _GetPanePtr(state.m_nIndex)->nID;
- state.DoUpdate(pTarget, bDisableIfNoHndler);
- }
-
- // update the dialog controls added to the status bar
- UpdateDialogControls(pTarget, bDisableIfNoHndler);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CStatusBar diagnostics
-
- #ifdef _DEBUG
- void CStatusBar::AssertValid() const
- {
- CControlBar::AssertValid();
- }
-
- void CStatusBar::Dump(CDumpContext& dc) const
- {
- CControlBar::Dump(dc);
-
- AFX_DUMP1(dc, "\nm_cxRightBorder = ", m_cxRightBorder);
- AFX_DUMP1(dc, "\nm_hFont = ", (UINT)m_hFont);
-
- if (dc.GetDepth() > 0)
- {
- for (int i = 0; i < m_nCount; i++)
- {
- AFX_DUMP1(dc, "status pane[", i); AFX_DUMP0(dc, "] = { ");
- AFX_DUMP1(dc, "\n\tnID = ", _GetPanePtr(i)->nID);
- AFX_DUMP1(dc, "\n\tnStyle = ", _GetPanePtr(i)->nStyle);
- AFX_DUMP1(dc, "\n\tcxText = ", _GetPanePtr(i)->cxText);
- AFX_DUMP1(dc, "\n\tlpszText = ", _GetPanePtr(i)->lpszText);
- AFX_DUMP0(dc, "\n\t}");
- }
- }
- }
- #endif //_DEBUG
-
-
- /////////////////////////////////////////////////////////////////////////////
-