⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collapsiblepanel.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 4 页
字号:
      if( m_cxLastWidth == 0 ) return;
      // Need to recreate all buttons because view changed
      for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
         if( m_aPanels[i].hbmpButton != NULL ) {
            ::DeleteObject(m_aPanels[i].hbmpButton);
            m_aPanels[i].hbmpButton = NULL;
         }
      }
      // Calculate button size
      CClientDC dc = m_hWnd;
      HFONT hOldFont = dc.SelectFont(GetFont());
      TEXTMETRIC tm = { 0 };
      dc.GetTextMetrics(&tm);
      dc.SelectFont(hOldFont);
      SIZE szIcons = { 0 };
      if( !m_Images.IsNull() ) m_Images.GetIconSize(szIcons);
      m_cyBar = max(16 + 6, tm.tmHeight + 6);
      m_cyButton = max(m_cyBar, szIcons.cy + IMAGE_GAP);
      // Repaint
      Invalidate();
   }
   void _RecalcScrollBar()
   {
      // Scrollbar support by Anatoly Ivasyuk.
      // Check that we can manipulate the scrollbar
      if( (m_dwExtStyle & CPS_EX_NOSCROLLBAR) == 0 )
      {
         // Get the location of the last panel in the list
         RECT rc = GetPanelRect(GetItemCount() - 1, FALSE);
         // Update the scroll bar based on the total height
         SCROLLINFO si;
         si.cbSize = sizeof(si);
         si.fMask = SIF_RANGE | SIF_PAGE;
         si.nMin = 0;
         si.nMax = rc.bottom + m_szMargin.cy;
         si.nPage = m_cyLastHeight - GetScrollPos(SB_VERT);
         SetScrollInfo(SB_VERT, &si, TRUE);
      }
   }
   void _RearrangePanels()
   {
      for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
         RECT rc = GetPanelRect(i, FALSE);
         ::SetWindowPos(m_aPanels[i].hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);
      }
      Invalidate();
   }
   void _CreateButton(CDCHandle dc, int iIndex, RECT rcItem)
   {
      // Create bitmap for button-background
      PANEL& panel = m_aPanels[iIndex];
      ::OffsetRect(&rcItem, -rcItem.left, -rcItem.top);
      int cx = rcItem.right - rcItem.left;
      int cy = rcItem.bottom - rcItem.top;
      CDC dcMem;
      dcMem.CreateCompatibleDC(dc);
      CBitmapHandle bmp;
      bmp.CreateCompatibleBitmap(dc, cx, cy);
      HBITMAP hOldBmp = dcMem.SelectBitmap(bmp);
      // Clear background
      dcMem.FillSolidRect(&rcItem, m_Theme.clrBack);
      // Figure out colors
      COLORREF clrBar1 = panel.clrBar1;
      if( clrBar1 == CLR_INVALID ) clrBar1 = m_Theme.clrBarActive1;
      if( iIndex == m_iCurSel && (m_dwExtStyle & CPS_EX_SELHIGHLIGHT) != 0 ) clrBar1 = m_Theme.clrBarSel1;
      if( !panel.bEnabled ) clrBar1 = m_Theme.clrBarInactive1;
      COLORREF clrBar2 = panel.clrBar2;
      if( clrBar2 == CLR_INVALID ) clrBar2 = m_Theme.clrBarActive2;
      if( iIndex == m_iCurSel && (m_dwExtStyle & CPS_EX_SELHIGHLIGHT) != 0 ) clrBar2 = m_Theme.clrBarSel2;
      if( !panel.bEnabled ) clrBar2 = m_Theme.clrBarInactive2;
      // Draw stuff
      if( (m_dwExtStyle & CPS_EX_OWNERDRAW) != 0 )
      {
#ifndef ODS_INACTIVE
         const UINT ODS_INACTIVE = 0x0080;
#endif
         DRAWITEMSTRUCT dis = { 0 };
         dis.CtlID = GetDlgCtrlID();
         dis.CtlType = ODT_STATIC;
         dis.itemAction = ODA_DRAWENTIRE;
         dis.hwndItem = m_hWnd;
         dis.hDC = dc;
         dis.itemID = iIndex;
         dis.itemState = 0;
         if( m_iCurSel == iIndex ) dis.itemState |= ODS_SELECTED;
         if( !panel.bExpanded ) dis.itemState |= ODS_INACTIVE;
         if( !panel.bEnabled ) dis.itemState |= ODS_DISABLED;
         dis.rcItem = GetPanelRect(iIndex, FALSE);
         ::SendMessage(GetParent(), WM_DRAWITEM, (WPARAM) dis.CtlID, (LPARAM) &dis);
      }
      else if( (m_dwExtStyle & CPS_EX_FLATSTYLE) != 0 )
      {
         CPen pen;
         pen.CreatePen(PS_SOLID, 1, clrBar2);
         CBrush brush;
         brush.CreateSolidBrush(clrBar1);
         HPEN hOldPen = dcMem.SelectPen(pen);
         HBRUSH hOldBrush = dcMem.SelectBrush(brush);
         dcMem.Rectangle(&rcItem);
         dcMem.SelectBrush(hOldBrush);
         dcMem.SelectPen(hOldPen);
      }
      else
      {
         // Prepare brushes and pens
         CPen pen;
         pen.CreatePen(PS_SOLID, 1, clrBar2);
         CBrush brush;
         brush.CreateSolidBrush(clrBar1);
         HPEN hOldPen = dcMem.SelectPen(pen);
         HBRUSH hOldBrush = dcMem.SelectBrush(brush);
         // Create clip region
         CRgn rgn;
         rgn.CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom + 666, m_Theme.iArc, m_Theme.iArc);
         dcMem.SelectClipRgn(rgn);
         // Paint gradient
         if( dcMem.GetDeviceCaps(BITSPIXEL) > 8 ) {
            // This will make 2^6 = 64 fountain steps
            const int nShift = 6;
            int nSteps = 1 << nShift;
            for( int i = 0; i < nSteps; i++ ) {
               // Do a little alpha blending
               BYTE bR = (BYTE) ((GetRValue(clrBar1) * (nSteps - i) +
                          GetRValue(clrBar2) * i) >> nShift);
               BYTE bG = (BYTE) ((GetGValue(clrBar1) * (nSteps - i) +
                          GetGValue(clrBar2) * i) >> nShift);
               BYTE bB = (BYTE) ((GetBValue(clrBar1) * (nSteps - i) +
                          GetBValue(clrBar2) * i) >> nShift);
               // then paint with the resulting color
               RECT r2 = rcItem;
               r2.left = rcItem.left + ((i * (rcItem.right - rcItem.left)) >> nShift);
               r2.right = rcItem.left + (((i + 1) * (rcItem.right - rcItem.left)) >> nShift);
               if( (r2.right - r2.left) > 0 ) dcMem.FillSolidRect(&r2, RGB(bR,bG,bB));
            }
         }
         dcMem.SelectClipRgn(NULL);
         // Repaint frame
         dcMem.SelectStockBrush(NULL_BRUSH);
         dcMem.RoundRect(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom + 666, m_Theme.iArc, m_Theme.iArc);
         // Done
         dcMem.SelectBrush(hOldBrush);
         dcMem.SelectPen(hOldPen);
      }
      dcMem.SelectBitmap(hOldBmp);
      panel.hbmpButton = bmp.Detach();
   }

   // Message map and handlers

   BEGIN_MSG_MAP(CCollapsiblePanelImpl)
      MESSAGE_HANDLER(WM_CREATE, OnCreate)
      MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
      MESSAGE_HANDLER(WM_SIZE, OnSize)
      MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
      MESSAGE_HANDLER(WM_TIMER, OnTimer)
      MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
      MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown)
      CHAIN_MSG_MAP( COffscreenDrawRect< T > )
   END_MSG_MAP()

   LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      LRESULT lRes = DefWindowProc();
      _Init();
      return lRes;
   }
   LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
   {
      RemoveAllItems();
      if( m_bOwnCollapseIcons ) {
         if( !m_iconCollapse.IsNull() ) m_iconCollapse.DestroyIcon();
         if( !m_iconExpand.IsNull() ) m_iconExpand.DestroyIcon();
      }
      if( (m_dwExtStyle & CPS_EX_SHAREIMAGELIST) == 0 ) {
         if( m_Images.IsNull() ) m_Images.Destroy();
         if( m_ImagesGrey.IsNull() ) m_ImagesGrey.Destroy();
      }
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
   {
      if( m_cxLastWidth != LOWORD(lParam) ) {
         m_cxLastWidth = LOWORD(lParam);
         _RecalcLayout();
         _RearrangePanels();
         _RecalcScrollBar();
      }
      if( m_cyLastHeight != HIWORD(lParam) ) {
         m_cyLastHeight = HIWORD(lParam);
         _RecalcScrollBar();
      }
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
   {
      bHandled = FALSE;
      if( wParam != ANIMATETIMER_ID ) return 0;
      // Process movement of any animating panel
      bool bStillAnimating = false;
      DWORD dwTick = ::GetTickCount();
      for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
         if( m_aPanels[i].dwAnimateStopTime > 0 ) {
            PANEL& panel = m_aPanels[i];
            if( dwTick >= panel.dwAnimateStopTime ) {
               // Done animating this panel
               panel.dwAnimateStopTime = 0;
               panel.cy = panel.bExpanded ? panel.szChild.cy : 0;
               // Show/hide child window
               ::ShowWindow(panel.hWnd, panel.bExpanded ? SW_SHOWNOACTIVATE : SW_HIDE);
               // Send notification
               ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), CPN_EXPANDED), (LPARAM) m_hWnd);
            }
            else 
            {
               // TODO: Need to calculate height based on the current time
               //       relative to the start time to favour slow machines.
               int iDiff = panel.bExpanded ? panel.szChild.cy - panel.cy : panel.cy;
               iDiff /= 2;
               panel.cy = panel.bExpanded ? panel.szChild.cy - iDiff : iDiff;
               bStillAnimating = true;
            }
         }
      }
      _RearrangePanels();
      if( !bStillAnimating ) 
      {
         _RecalcScrollBar();
         KillTimer(ANIMATETIMER_ID);
      }
      return 0;
   }
   LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      // Scrollbar support added by Anatoly Ivasyuk
      // Get all the vertial scroll bar information
      SCROLLINFO si = { 0 };
      si.cbSize = sizeof(si);
      si.fMask  = SIF_ALL;
      GetScrollInfo(SB_VERT, &si);  
      // Save the position for comparison later on
      int yPos = si.nPos;  
      switch( LOWORD(wParam) ) {
      case SB_TOP:
         // User clicked the HOME keyboard key
         si.nPos = si.nMin;
         break;           
      case SB_BOTTOM:
         // User clicked the END keyboard key
         si.nPos = si.nMax;
         break;          
      case SB_LINEUP:
         // User clicked the top arrow
         si.nPos -= 1;
         break;           
      case SB_LINEDOWN:
         // User clicked the bottom arrow
         si.nPos += 1;
         break;           
      case SB_PAGEUP:
         // User clicked the shaft above the scroll box
         si.nPos -= si.nPage;
         break;           
      case SB_PAGEDOWN:
         // User clicked the shaft below the scroll box
         si.nPos += si.nPage;
         break;           
      case SB_THUMBTRACK:
         // User dragged the scroll box
         si.nPos = si.nTrackPos;
         break;           
      default:
         break; 
      }
      // Set the position and then retrieve it.  Due to adjustments
      //   by Windows it may not be the same as the value set.
      si.fMask = SIF_POS;
      SetScrollInfo(SB_VERT, &si, TRUE);
      GetScrollInfo(SB_VERT, &si);
      if( si.nPos != yPos ) {                    
         _RecalcLayout();
         _RearrangePanels();
         Invalidate();
      }       
      return 0;
   }
   LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
      for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
         RECT rc = GetPanelRect(i, TRUE);
         rc.top += m_cyButton - m_cyBar;
         rc.bottom = rc.top + m_cyBar;
         if( (m_dwExtStyle & CPS_EX_EXPANDCLICK) != 0 ) ::SetRect(&rc, rc.right - 30, rc.top + 3, rc.right, rc.bottom - 3);
         if( ::PtInRect(&rc, pt) ) {
            if( GetItemEnabled(i) ) {
              m_iCurSel = i;
              SetItemExpanded(i, !GetItemExpanded(i), TRUE);
              if( (m_dwExtStyle & CPS_EX_SELHIGHLIGHT) != 0 ) _RecalcLayout();
              break;
            }
         }
      }
      return 0;
   }

   // Paint override

   void DoPaint(CDCHandle dc, RECT& rect)
   {
      ATLASSERT(!m_iconExpand.IsNull());

      RECT rcClient;
      GetClientRect(&rcClient);

      dc.FillSolidRect(&rect, m_Theme.clrBack);

      ::InflateRect(&rcClient, -m_szMargin.cx, -m_szMargin.cy);

      HFONT hOldFont = dc.SelectFont(GetFont());
      dc.SetBkMode(TRANSPARENT);
      for( int i = 0; i < m_aPanels.GetSize(); i++ ) {
         RECT rcItem = GetPanelRect(i, TRUE);
         // Should we paint this button at all?
         RECT rcButton = rcItem;
         rcButton.bottom = rcButton.top + m_cyButton;
         RECT rcDummy = { 0 };
         if( !::IntersectRect(&rcDummy, &rect, &rcButton) ) continue;
         // Recreate button bitmap?
         const PANEL& panel = m_aPanels[i];
         RECT rcBar = { rcButton.left, rcButton.bottom - m_cyBar, rcButton.right, rcButton.bottom };
         if( panel.hbmpButton == NULL ) _CreateButton(dc, i, rcBar);
         ATLASSERT(panel.hbmpButton!=NULL);
         // Paint button
         CDC dcBmp;
         dcBmp.CreateCompatibleDC(dc);
         HBITMAP hOldBmp = dcBmp.SelectBitmap(panel.hbmpButton);
         dc.BitBlt(rcBar.left, rcBar.top, rcBar.right - rcBar.left, rcBar.bottom, dcBmp, 0, 0, SRCCOPY);
         dcBmp.SelectBitmap(hOldBmp);
         // Rect for text
         RECT rcText = rcButton;
         rcText.left += 10;
         rcText.right -= 4;
         rcText.top = rcText.bottom - m_cyBar;
         // Add expander
         if( (m_dwExtStyle & CPS_EX_NOEXPANDBUTTON) == 0 ) {
            dc.DrawIconEx(rcBar.right - 24, rcBar.top + 3, panel.bExpanded ? m_iconCollapse : m_iconExpand, 16, 16);
            rcText.right -= 26;
         }
         // Add icon
         if( panel.iImage >= 0 && !m_Images.IsNull() ) {
            SIZE szIcon;
            m_Images.GetIconSize(szIcon);
            POINT pt = { rcItem.left + 2, rcItem.top + 2 };
            if( !panel.bEnabled && !m_ImagesGrey.IsNull() ) {
               m_ImagesGrey.Draw(dc, panel.iImage, pt, ILD_TRANSPARENT);
            }
            else {
               m_Images.Draw(dc, panel.iImage, pt, ILD_TRANSPARENT);
            }
            rcText.left += szIcon.cx;
         }
         // Print text
         COLORREF clrText = panel.clrText;
         if( clrText == CLR_INVALID ) clrText = m_Theme.clrTextActive;
         if( i == m_iCurSel && (m_dwExtStyle & CPS_EX_SELHIGHLIGHT) != 0 ) clrText = m_Theme.clrTextSel;
         if( !m_aPanels[i].bEnabled ) clrText = m_Theme.clrTextInactive;
         dc.SetTextColor(clrText);
         dc.DrawText(panel.pstrTitle, -1, &rcText, DT_SINGLELINE | DT_END_ELLIPSIS | DT_VCENTER);
         // Optional border around child
         if( GetStyle() & WS_BORDER ) {
            RECT rcChild = rcItem;
            rcChild.top += m_cyButton;
            CPen pen;
            pen.CreatePen(PS_SOLID, 1, m_Theme.clrBorder);
            HPEN hOldPen = dc.SelectPen(pen);
            HBRUSH hOldBrush = dc.SelectStockBrush(NULL_BRUSH);
            dc.Rectangle(&rcChild);
            dc.SelectBrush(hOldBrush);
            dc.SelectPen(hOldPen);
         }
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -