home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / barstat.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  19KB  |  761 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE3_SEG
  14. #pragma code_seg(AFX_CORE3_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CStatusBar creation, etc
  26.  
  27. #define SBPF_UPDATE 0x0001  // pending update of text
  28.  
  29. struct AFX_STATUSPANE
  30. {
  31.     UINT    nID;        // IDC of indicator: 0 => normal text area
  32.     int     cxText;     // width of string area in pixels
  33.                         //   on both sides there is a 3 pixel gap and
  34.                         //   a one pixel border, making a pane 6 pixels wider
  35.     UINT    nStyle;     // style flags (SBPS_*)
  36.     UINT    nFlags;     // state flags (SBPF_*)
  37.     CString strText;    // text in the pane
  38. };
  39.  
  40. inline AFX_STATUSPANE* CStatusBar::_GetPanePtr(int nIndex) const
  41. {
  42.     ASSERT((nIndex >= 0 && nIndex < m_nCount) || m_nCount == 0);
  43.     return ((AFX_STATUSPANE*)m_pData) + nIndex;
  44. }
  45.  
  46. #ifdef AFX_INIT_SEG
  47. #pragma code_seg(AFX_INIT_SEG)
  48. #endif
  49.  
  50. #define CX_PANE_BORDER 6    // 3 pixels on each side of each pane
  51.  
  52. CStatusBar::CStatusBar()
  53. {
  54.     // setup default border/margin depending on type of system
  55.     m_cyTopBorder = 2;
  56.     if (afxData.bWin4)
  57.     {
  58.         m_cxLeftBorder = 0;
  59.         m_cxRightBorder = 0;
  60.         m_cyBottomBorder = 0;
  61.     }
  62.     else
  63.     {
  64.         m_cxLeftBorder = 2;
  65.         m_cxRightBorder = 2;
  66.         m_cyBottomBorder = 1;
  67.     }
  68.     // minimum height set with SB_SETMINHEIGHT is cached
  69.     m_nMinHeight = 0;
  70. }
  71.  
  72. CStatusBar::~CStatusBar()
  73. {
  74.     AllocElements(0, 0);    // destroys existing elements
  75. }
  76.  
  77. BOOL CStatusBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
  78. {
  79.     return CreateEx(pParentWnd, 0, dwStyle, nID);
  80. }
  81.  
  82. BOOL CStatusBar::CreateEx(CWnd* pParentWnd, DWORD dwCtrlStyle, DWORD dwStyle, UINT nID)
  83. {
  84.     ASSERT_VALID(pParentWnd);   // must have a parent
  85.  
  86.     // save the style (some of these style bits are MFC specific)
  87.     m_dwStyle = (dwStyle & CBRS_ALL);
  88.  
  89.     // translate MFC style bits to windows style bits
  90.     dwStyle &= ~CBRS_ALL;
  91.     dwStyle |= CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;
  92.     if (pParentWnd->GetStyle() & WS_THICKFRAME)
  93.         dwStyle |= SBARS_SIZEGRIP;
  94.     dwStyle |= dwCtrlStyle;
  95.  
  96.     // initialize common controls
  97.     VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTL_BAR_REG));
  98.  
  99.     // create the HWND
  100.     CRect rect; rect.SetRectEmpty();
  101.     return CWnd::Create(STATUSCLASSNAME, NULL, dwStyle, rect, pParentWnd, nID);
  102. }
  103.  
  104. BOOL CStatusBar::PreCreateWindow(CREATESTRUCT& cs)
  105. {
  106.     // in Win4, status bars do not have a border at all, since it is
  107.     //  provided by the client area.
  108.     if (afxData.bWin4 &&
  109.         (m_dwStyle & (CBRS_ALIGN_ANY|CBRS_BORDER_ANY)) == CBRS_BOTTOM)
  110.     {
  111.         m_dwStyle &= ~(CBRS_BORDER_ANY|CBRS_BORDER_3D);
  112.     }
  113.     return CControlBar::PreCreateWindow(cs);
  114. }
  115.  
  116. BOOL CStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
  117. {
  118.     ASSERT_VALID(this);
  119.     ASSERT(nIDCount >= 1);  // must be at least one of them
  120.     ASSERT(lpIDArray == NULL ||
  121.         AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));
  122.     ASSERT(::IsWindow(m_hWnd));
  123.  
  124.     // first allocate array for panes and copy initial data
  125.     if (!AllocElements(nIDCount, sizeof(AFX_STATUSPANE)))
  126.         return FALSE;
  127.     ASSERT(nIDCount == m_nCount);
  128.  
  129.     // copy initial data from indicator array
  130.     BOOL bResult = TRUE;
  131.     if (lpIDArray != NULL)
  132.     {
  133.         HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
  134.         CClientDC dcScreen(NULL);
  135.         HGDIOBJ hOldFont = NULL;
  136.         if (hFont != NULL)
  137.             hOldFont = dcScreen.SelectObject(hFont);
  138.  
  139.         AFX_STATUSPANE* pSBP = _GetPanePtr(0);
  140.         for (int i = 0; i < nIDCount; i++)
  141.         {
  142.             pSBP->nID = *lpIDArray++;
  143.             pSBP->nFlags |= SBPF_UPDATE;
  144.             if (pSBP->nID != 0)
  145.             {
  146.                 if (!pSBP->strText.LoadString(pSBP->nID))
  147.                 {
  148.                     TRACE1("Warning: failed to load indicator string 0x%04X.\n",
  149.                         pSBP->nID);
  150.                     bResult = FALSE;
  151.                     break;
  152.                 }
  153.                 pSBP->cxText = dcScreen.GetTextExtent(pSBP->strText).cx;
  154.                 ASSERT(pSBP->cxText >= 0);
  155.                 if (!SetPaneText(i, pSBP->strText, FALSE))
  156.                 {
  157.                     bResult = FALSE;
  158.                     break;
  159.                 }
  160.             }
  161.             else
  162.             {
  163.                 // no indicator (must access via index)
  164.                 // default to 1/4 the screen width (first pane is stretchy)
  165.                 pSBP->cxText = ::GetSystemMetrics(SM_CXSCREEN)/4;
  166.                 if (i == 0)
  167.                     pSBP->nStyle |= (SBPS_STRETCH | SBPS_NOBORDERS);
  168.             }
  169.             ++pSBP;
  170.         }
  171.         if (hOldFont != NULL)
  172.             dcScreen.SelectObject(hOldFont);
  173.     }
  174.     UpdateAllPanes(TRUE, TRUE);
  175.  
  176.     return bResult;
  177. }
  178.  
  179. BOOL CStatusBar::AllocElements(int nElements, int cbElement)
  180. {
  181.     // destruct old elements
  182.     AFX_STATUSPANE* pSBP = _GetPanePtr(0);
  183.     for (int i = 0; i < m_nCount; i++)
  184.     {
  185.         pSBP->strText.~CString();
  186.         ++pSBP;
  187.     }
  188.  
  189.     // allocate new elements
  190.     if (!CControlBar::AllocElements(nElements, cbElement))
  191.         return FALSE;
  192.  
  193.     // construct new elements
  194.     pSBP = _GetPanePtr(0);
  195.     for (i = 0; i < m_nCount; i++)
  196.     {
  197.         memcpy(&pSBP->strText, &afxEmptyString, sizeof(CString));
  198.         ++pSBP;
  199.     }
  200.     return TRUE;
  201. }
  202.  
  203. void CStatusBar::CalcInsideRect(CRect& rect, BOOL bHorz) const
  204. {
  205.     ASSERT_VALID(this);
  206.     ASSERT(::IsWindow(m_hWnd));
  207.     ASSERT(bHorz);  // vertical status bar not supported
  208.  
  209.     // subtract standard CControlBar borders
  210.     CControlBar::CalcInsideRect(rect, bHorz);
  211.  
  212.     // subtract size grip if present
  213.     if ((GetStyle() & SBARS_SIZEGRIP) && !::IsZoomed(::GetParent(m_hWnd)))
  214.     {
  215.         // get border metrics from common control
  216.         int rgBorders[3];
  217.         CStatusBar* pBar = (CStatusBar*)this;
  218.         pBar->DefWindowProc(SB_GETBORDERS, 0, (LPARAM)&rgBorders);
  219.  
  220.         // size grip uses a border + size of scrollbar + cx border
  221.         rect.right -= rgBorders[0] + ::GetSystemMetrics(SM_CXVSCROLL) +
  222.             ::GetSystemMetrics(SM_CXBORDER) * 2;
  223.     }
  224. }
  225.  
  226. void CStatusBar::UpdateAllPanes(BOOL bUpdateRects, BOOL bUpdateText)
  227. {
  228.     ASSERT_VALID(this);
  229.     ASSERT(::IsWindow(m_hWnd));
  230.  
  231.     // update the status pane locations
  232.     if (bUpdateRects)
  233.     {
  234.         // get border information and client work area
  235.         CRect rect; GetWindowRect(rect);
  236.         rect.OffsetRect(-rect.left, -rect.top);
  237.         CalcInsideRect(rect, TRUE);
  238.         int rgBorders[3];
  239.         VERIFY((BOOL)DefWindowProc(SB_GETBORDERS, 0, (LPARAM)&rgBorders));
  240.  
  241.         // determine extra space for stretchy pane
  242.         int cxExtra = rect.Width() + rgBorders[2];
  243.         int nStretchyCount = 0;
  244.         AFX_STATUSPANE* pSBP = _GetPanePtr(0);
  245.         for (int i = 0; i < m_nCount; i++)
  246.         {
  247.             if (pSBP->nStyle & SBPS_STRETCH)
  248.                 ++nStretchyCount;
  249.             cxExtra -= (pSBP->cxText+CX_PANE_BORDER + rgBorders[2]);
  250.             ++pSBP;
  251.         }
  252.  
  253.         // determine right edge of each pane
  254.         int* rgRights = (int*)_alloca(m_nCount * sizeof(int));
  255.         int right = rgBorders[0];
  256.         pSBP = _GetPanePtr(0);
  257.         for (i = 0; i < m_nCount; i++)
  258.         {
  259.             // determine size of the pane
  260.             ASSERT(pSBP->cxText >= 0);
  261.             right += pSBP->cxText+CX_PANE_BORDER;
  262.             if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
  263.             {
  264.                 ASSERT(nStretchyCount != 0);
  265.                 int cxAddExtra = cxExtra / nStretchyCount;
  266.                 right += cxAddExtra;
  267.                 --nStretchyCount;
  268.                 cxExtra -= cxAddExtra;
  269.             }
  270.             rgRights[i] = right;
  271.  
  272.             // next pane
  273.             ++pSBP;
  274.             right += rgBorders[2];
  275.         }
  276.  
  277.         // set new right edges for all panes
  278.         DefWindowProc(SB_SETPARTS, m_nCount, (LPARAM)rgRights);
  279.     }
  280.  
  281.     // update text in the status panes if specified
  282.     if (bUpdateText)
  283.     {
  284.         AFX_STATUSPANE* pSBP = _GetPanePtr(0);
  285.         for (int i = 0; i < m_nCount; i++)
  286.         {
  287.             if (pSBP->nFlags & SBPF_UPDATE)
  288.                 SetPaneText(i, pSBP->strText);
  289.             ++pSBP;
  290.         }
  291.     }
  292. }
  293.  
  294. #ifdef AFX_CORE3_SEG
  295. #pragma code_seg(AFX_CORE3_SEG)
  296. #endif
  297.  
  298. /////////////////////////////////////////////////////////////////////////////
  299. // CStatusBar attribute access
  300.  
  301. int CStatusBar::CommandToIndex(UINT nIDFind) const
  302. {
  303.     ASSERT_VALID(this);
  304.  
  305.     if (m_nCount <= 0)
  306.         return -1;
  307.  
  308.     AFX_STATUSPANE* pSBP = _GetPanePtr(0);
  309.     for (int i = 0; i < m_nCount; i++, pSBP++)
  310.         if (pSBP->nID == nIDFind)
  311.             return i;
  312.  
  313.     return -1;
  314. }
  315.  
  316. UINT CStatusBar::GetItemID(int nIndex) const
  317. {
  318.     ASSERT_VALID(this);
  319.     return _GetPanePtr(nIndex)->nID;
  320. }
  321.  
  322. void CStatusBar::GetItemRect(int nIndex, LPRECT lpRect) const
  323. {
  324.     ASSERT_VALID(this);
  325.     ASSERT(::IsWindow(m_hWnd));
  326.  
  327.     CStatusBar* pBar = (CStatusBar*)this;
  328.     if (!pBar->DefWindowProc(SB_GETRECT, nIndex, (LPARAM)lpRect))
  329.         ::SetRectEmpty(lpRect);
  330. }
  331.  
  332. UINT CStatusBar::GetPaneStyle(int nIndex) const
  333. {
  334.     return _GetPanePtr(nIndex)->nStyle;
  335. }
  336.  
  337. void CStatusBar::SetPaneStyle(int nIndex, UINT nStyle)
  338. {
  339.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  340.     if (pSBP->nStyle != nStyle)
  341.     {
  342.         // if the pane is changing SBPS_STRETCH, then...
  343.         if ((pSBP->nStyle ^ nStyle) & SBPS_STRETCH)
  344.         {
  345.             // ... we need to re-layout the panes
  346.             pSBP->nStyle = nStyle;
  347.             UpdateAllPanes(TRUE, FALSE);
  348.         }
  349.  
  350.         // use SetPaneText, since it updates the style and text
  351.         pSBP->nStyle = nStyle;
  352.         pSBP->nFlags |= SBPF_UPDATE;
  353.         SetPaneText(nIndex, pSBP->strText);
  354.     }
  355. }
  356.  
  357. void CStatusBar::GetPaneInfo(int nIndex, UINT& nID, UINT& nStyle,
  358.     int& cxWidth) const
  359. {
  360.     ASSERT_VALID(this);
  361.  
  362.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  363.     nID = pSBP->nID;
  364.     nStyle = pSBP->nStyle;
  365.     cxWidth = pSBP->cxText;
  366. }
  367.  
  368. void CStatusBar::SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth)
  369. {
  370.     ASSERT_VALID(this);
  371.  
  372.     BOOL bChanged = FALSE;
  373.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  374.     pSBP->nID = nID;
  375.     if (pSBP->nStyle != nStyle)
  376.     {
  377.         if ((pSBP->nStyle ^ nStyle) & SBPS_STRETCH)
  378.             bChanged = TRUE;
  379.         else
  380.         {
  381.             pSBP->nStyle = nStyle;
  382.             pSBP->nFlags |= SBPF_UPDATE;
  383.             SetPaneText(nIndex, pSBP->strText);
  384.         }
  385.         pSBP->nStyle = nStyle;
  386.     }
  387.     if (cxWidth != pSBP->cxText)
  388.     {
  389.         // change width of one pane -> invalidate the entire status bar
  390.         pSBP->cxText = cxWidth;
  391.         bChanged = TRUE;
  392.     }
  393.     if (bChanged)
  394.         UpdateAllPanes(TRUE, FALSE);
  395. }
  396.  
  397. void CStatusBar::GetPaneText(int nIndex, CString& s) const
  398. {
  399.     ASSERT_VALID(this);
  400.  
  401.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  402.     s = pSBP->strText;
  403. }
  404.  
  405. CString CStatusBar::GetPaneText(int nIndex) const
  406. {
  407.     ASSERT_VALID(this);
  408.  
  409.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  410.     return pSBP->strText;
  411. }
  412.  
  413. BOOL CStatusBar::SetPaneText(int nIndex, LPCTSTR lpszNewText, BOOL bUpdate)
  414. {
  415.     ASSERT_VALID(this);
  416.     ASSERT(::IsWindow(m_hWnd));
  417.  
  418.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  419.  
  420.     if (!(pSBP->nFlags & SBPF_UPDATE) &&
  421.         ((lpszNewText == NULL && pSBP->strText.IsEmpty()) ||
  422.          (lpszNewText != NULL && pSBP->strText.Compare(lpszNewText) == 0)))
  423.     {
  424.         // nothing to change
  425.         return TRUE;
  426.     }
  427.  
  428.     TRY
  429.     {
  430.         if (lpszNewText != NULL)
  431.             pSBP->strText = lpszNewText;
  432.         else
  433.             pSBP->strText.Empty();
  434.     }
  435.     CATCH_ALL(e)
  436.     {
  437.         // Note: DELETE_EXCEPTION(e) not required
  438.         return FALSE;
  439.     }
  440.     END_CATCH_ALL
  441.  
  442.     if (!bUpdate)
  443.     {
  444.         // can't update now, wait until later
  445.         pSBP->nFlags |= SBPF_UPDATE;
  446.         return TRUE;
  447.     }
  448.  
  449.     pSBP->nFlags &= ~SBPF_UPDATE;
  450.     DefWindowProc(SB_SETTEXT, ((WORD)pSBP->nStyle)|nIndex,
  451.         (pSBP->nStyle & SBPS_DISABLED) ? NULL :
  452.         (LPARAM)(LPCTSTR)pSBP->strText);
  453.  
  454.     return TRUE;
  455. }
  456.  
  457. /////////////////////////////////////////////////////////////////////////////
  458. // CStatusBar implementation
  459.  
  460. CSize CStatusBar::CalcFixedLayout(BOOL, BOOL bHorz)
  461. {
  462.     ASSERT_VALID(this);
  463.     ASSERT(::IsWindow(m_hWnd));
  464.  
  465.     // determinme size of font being used by the status bar
  466.     TEXTMETRIC tm;
  467.     {
  468.         CClientDC dc(NULL);
  469.         HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
  470.         HGDIOBJ hOldFont = NULL;
  471.         if (hFont != NULL)
  472.             hOldFont = dc.SelectObject(hFont);
  473.         VERIFY(dc.GetTextMetrics(&tm));
  474.         if (hOldFont != NULL)
  475.             dc.SelectObject(hOldFont);
  476.     }
  477.  
  478.     // get border information
  479.     CRect rect; rect.SetRectEmpty();
  480.     CalcInsideRect(rect, bHorz);
  481.     int rgBorders[3];
  482.     DefWindowProc(SB_GETBORDERS, 0, (LPARAM)&rgBorders);
  483.  
  484.     // determine size, including borders
  485.     CSize size;
  486.     size.cx = 32767;
  487.     size.cy = tm.tmHeight - tm.tmInternalLeading - 1
  488.         + rgBorders[1] * 2 + ::GetSystemMetrics(SM_CYBORDER) * 2
  489.         - rect.Height();
  490.     if (size.cy < m_nMinHeight)
  491.         size.cy = m_nMinHeight;
  492.  
  493.     return size;
  494. }
  495.  
  496. /////////////////////////////////////////////////////////////////////////////
  497. // CStatusBar message handlers
  498.  
  499. BEGIN_MESSAGE_MAP(CStatusBar, CControlBar)
  500.     //{{AFX_MSG_MAP(CStatusBar)
  501.     ON_WM_NCHITTEST()
  502.     ON_WM_NCPAINT()
  503.     ON_WM_PAINT()
  504.     ON_WM_NCCALCSIZE()
  505.     ON_WM_SIZE()
  506.     ON_WM_WINDOWPOSCHANGING()
  507.     ON_MESSAGE(WM_SETTEXT, OnSetText)
  508.     ON_MESSAGE(WM_GETTEXT, OnGetText)
  509.     ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)
  510.     ON_MESSAGE(SB_SETMINHEIGHT, OnSetMinHeight)
  511.     //}}AFX_MSG_MAP
  512. END_MESSAGE_MAP()
  513.  
  514. UINT CStatusBar::OnNcHitTest(CPoint)
  515. {
  516.     UINT nResult = (UINT)Default();
  517.     if (nResult == HTBOTTOMRIGHT)
  518.         return HTBOTTOMRIGHT;
  519.     else
  520.         return HTCLIENT;
  521. }
  522.  
  523. void CStatusBar::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp)
  524. {
  525.     // calculate border space (will add to top/bottom, subtract from right/bottom)
  526.     CRect rect; rect.SetRectEmpty();
  527.     CControlBar::CalcInsideRect(rect, TRUE);
  528.     ASSERT(rect.top >= 2);
  529.  
  530.     // adjust non-client area for border space
  531.     lpncsp->rgrc[0].left += rect.left;
  532.     lpncsp->rgrc[0].top += rect.top - 2;
  533.     lpncsp->rgrc[0].right += rect.right;
  534.     lpncsp->rgrc[0].bottom += rect.bottom;
  535. }
  536.  
  537. void CStatusBar::OnBarStyleChange(DWORD dwOldStyle, DWORD dwNewStyle)
  538. {
  539.     if (m_hWnd != NULL &&
  540.         ((dwOldStyle & CBRS_BORDER_ANY) != (dwNewStyle & CBRS_BORDER_ANY)))
  541.     {
  542.         // recalc non-client area when border styles change
  543.         SetWindowPos(NULL, 0, 0, 0, 0,
  544.             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_DRAWFRAME);
  545.     }
  546. }
  547.  
  548. void CStatusBar::OnNcPaint()
  549. {
  550.     EraseNonClient();
  551. }
  552.  
  553. // Derived class is responsible for implementing all of these handlers
  554. //  for owner/self draw controls.
  555. void CStatusBar::DrawItem(LPDRAWITEMSTRUCT)
  556. {
  557.     ASSERT(FALSE);
  558. }
  559.  
  560. BOOL CStatusBar::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  561. {
  562.     if (message != WM_DRAWITEM)
  563.         return CWnd::OnChildNotify(message, wParam, lParam, pResult);
  564.  
  565.     ASSERT(pResult == NULL);
  566.     UNUSED(pResult); // unused in release builds
  567.     DrawItem((LPDRAWITEMSTRUCT)lParam);
  568.     return TRUE;
  569. }
  570.  
  571. void CStatusBar::OnPaint()
  572. {
  573.     UpdateAllPanes(FALSE, TRUE);
  574.  
  575.     Default();
  576. }
  577.  
  578. void CStatusBar::OnSize(UINT nType, int cx, int cy)
  579. {
  580.     ASSERT_VALID(this);
  581.     ASSERT(::IsWindow(m_hWnd));
  582.  
  583.     CControlBar::OnSize(nType, cx, cy);
  584.  
  585.     // need to adjust pane right edges (because of stretchy pane)
  586.     UpdateAllPanes(TRUE, FALSE);
  587. }
  588.  
  589. void CStatusBar::OnWindowPosChanging(LPWINDOWPOS lpWndPos)
  590. {
  591.     // not necessary to invalidate the borders
  592.     DWORD dwStyle = m_dwStyle;
  593.     m_dwStyle &= ~(CBRS_BORDER_ANY);
  594.     CControlBar::OnWindowPosChanging(lpWndPos);
  595.     m_dwStyle = dwStyle;
  596. }
  597.  
  598. LRESULT CStatusBar::OnSetText(WPARAM, LPARAM lParam)
  599. {
  600.     ASSERT_VALID(this);
  601.     ASSERT(::IsWindow(m_hWnd));
  602.  
  603.     int nIndex = CommandToIndex(0);
  604.     if (nIndex < 0)
  605.         return -1;
  606.     return SetPaneText(nIndex, (LPCTSTR)lParam) ? 0 : -1;
  607. }
  608.  
  609. LRESULT CStatusBar::OnGetText(WPARAM wParam, LPARAM lParam)
  610. {
  611.     ASSERT_VALID(this);
  612.     ASSERT(::IsWindow(m_hWnd));
  613.  
  614.     int nMaxLen = (int)wParam;
  615.     if (nMaxLen == 0)
  616.         return 0;       // nothing copied
  617.     LPTSTR lpszDest = (LPTSTR)lParam;
  618.  
  619.     int nLen = 0;
  620.     int nIndex = CommandToIndex(0); // use pane with ID zero
  621.     if (nIndex >= 0)
  622.     {
  623.         AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  624.         nLen = pSBP->strText.GetLength();
  625.         if (nLen > nMaxLen)
  626.             nLen = nMaxLen - 1; // number of characters to copy (less term.)
  627.         memcpy(lpszDest, (LPCTSTR)pSBP->strText, nLen*sizeof(TCHAR));
  628.     }
  629.     lpszDest[nLen] = '\0';
  630.     return nLen+1;      // number of bytes copied
  631. }
  632.  
  633. LRESULT CStatusBar::OnGetTextLength(WPARAM, LPARAM)
  634. {
  635.     ASSERT_VALID(this);
  636.     ASSERT(::IsWindow(m_hWnd));
  637.  
  638.     int nLen = 0;
  639.     int nIndex = CommandToIndex(0); // use pane with ID zero
  640.     if (nIndex >= 0)
  641.     {
  642.         AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  643.         nLen = pSBP->strText.GetLength();
  644.     }
  645.     return nLen;
  646. }
  647.  
  648. LRESULT CStatusBar::OnSetMinHeight(WPARAM wParam, LPARAM)
  649. {
  650.     LRESULT lResult = Default();
  651.     m_nMinHeight = wParam;
  652.     return lResult;
  653. }
  654.  
  655. /////////////////////////////////////////////////////////////////////////////
  656. // CStatusBar idle update through CStatusCmdUI class
  657.  
  658. class CStatusCmdUI : public CCmdUI      // class private to this file!
  659. {
  660. public: // re-implementations only
  661.     virtual void Enable(BOOL bOn);
  662.     virtual void SetCheck(int nCheck);
  663.     virtual void SetText(LPCTSTR lpszText);
  664. };
  665.  
  666. void CStatusCmdUI::Enable(BOOL bOn)
  667. {
  668.     m_bEnableChanged = TRUE;
  669.     CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
  670.     ASSERT(pStatusBar != NULL);
  671.     ASSERT_KINDOF(CStatusBar, pStatusBar);
  672.     ASSERT(m_nIndex < m_nIndexMax);
  673.  
  674.     UINT nNewStyle = pStatusBar->GetPaneStyle(m_nIndex) & ~SBPS_DISABLED;
  675.     if (!bOn)
  676.         nNewStyle |= SBPS_DISABLED;
  677.     pStatusBar->SetPaneStyle(m_nIndex, nNewStyle);
  678. }
  679.  
  680. void CStatusCmdUI::SetCheck(int nCheck) // "checking" will pop out the text
  681. {
  682.     CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
  683.     ASSERT(pStatusBar != NULL);
  684.     ASSERT_KINDOF(CStatusBar, pStatusBar);
  685.     ASSERT(m_nIndex < m_nIndexMax);
  686.  
  687.     UINT nNewStyle = pStatusBar->GetPaneStyle(m_nIndex) & ~SBPS_POPOUT;
  688.     if (nCheck != 0)
  689.         nNewStyle |= SBPS_POPOUT;
  690.     pStatusBar->SetPaneStyle(m_nIndex, nNewStyle);
  691. }
  692.  
  693. void CStatusCmdUI::SetText(LPCTSTR lpszText)
  694. {
  695.     CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
  696.     ASSERT(pStatusBar != NULL);
  697.     ASSERT_KINDOF(CStatusBar, pStatusBar);
  698.     ASSERT(m_nIndex < m_nIndexMax);
  699.  
  700.     pStatusBar->SetPaneText(m_nIndex, lpszText);
  701. }
  702.  
  703. void CStatusBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
  704. {
  705.     CStatusCmdUI state;
  706.     state.m_pOther = this;
  707.     state.m_nIndexMax = (UINT)m_nCount;
  708.     for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  709.         state.m_nIndex++)
  710.     {
  711.         state.m_nID = _GetPanePtr(state.m_nIndex)->nID;
  712.  
  713.         // allow the statusbar itself to have update handlers
  714.         if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
  715.             continue;
  716.  
  717.         // allow target (owner) to handle the remaining updates
  718.         state.DoUpdate(pTarget, FALSE);
  719.     }
  720.  
  721.     // update the dialog controls added to the status bar
  722.     UpdateDialogControls(pTarget, bDisableIfNoHndler);
  723. }
  724.  
  725. /////////////////////////////////////////////////////////////////////////////
  726. // CStatusBar diagnostics
  727.  
  728. #ifdef _DEBUG
  729. void CStatusBar::AssertValid() const
  730. {
  731.     CControlBar::AssertValid();
  732. }
  733.  
  734. void CStatusBar::Dump(CDumpContext& dc) const
  735. {
  736.     CControlBar::Dump(dc);
  737.  
  738.     if (dc.GetDepth() > 0)
  739.     {
  740.         for (int i = 0; i < m_nCount; i++)
  741.         {
  742.             dc << "\nstatus pane[" << i << "] = {";
  743.             dc << "\n\tnID = " << _GetPanePtr(i)->nID;
  744.             dc << "\n\tnStyle = " << _GetPanePtr(i)->nStyle;
  745.             dc << "\n\tcxText = " << _GetPanePtr(i)->cxText;
  746.             dc << "\n\tstrText = " << _GetPanePtr(i)->strText;
  747.             dc << "\n\t}";
  748.         }
  749.     }
  750.     dc << "\n";
  751. }
  752. #endif //_DEBUG
  753.  
  754. #ifdef AFX_INIT_SEG
  755. #pragma code_seg(AFX_INIT_SEG)
  756. #endif
  757.  
  758. IMPLEMENT_DYNAMIC(CStatusBar, CControlBar)
  759.  
  760. /////////////////////////////////////////////////////////////////////////////
  761.