home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / BARSTAT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  18.6 KB  |  756 lines

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