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

📄 propertygrid.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 3 页
字号:
            if( prop->GetKind() == PROPKIND_EDIT && 
                prop->IsEnabled() ) 
            {
               if( _SpawnInplaceWindow(prop, m_iSelectedRow, m_iSelectedCol) ) {
                  prop->Activate(PACT_SPACE, 0);
                  // Simulate typing in the inplace editor...
                  ::SendMessage(m_hwndInplace, WM_KEYDOWN, wParam, 0L);
                  _InvalidateItem(m_iSelectedRow, m_iSelectedCol);
               }
            }
         }
         return 0;
      }
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
   {      
      // If the user is typing stuff, we should spawn an editor right away
      // and simulate the keypress in the editor-window...
      if( wParam > _T(' ') ) {
         if( _IsValidSelection() ) {
            IProperty* prop = GetProperty(m_iSelectedRow, m_iSelectedCol);
            ATLASSERT(prop);
            if( prop->IsEnabled() ) {
               if( _SpawnInplaceWindow(prop, m_iSelectedRow, m_iSelectedCol) ) {
                  prop->Activate(PACT_SPACE, 0);
                  // Simulate typing in the inplace editor...
                  ::SendMessage(m_hwndInplace, WM_CHAR, wParam, 1L);
                  _InvalidateItem(m_iSelectedRow, m_iSelectedCol);
               }
            }
            return 0;
         }
      }
      if( wParam == _T(' ') ) return 0;
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {      
      return DefWindowProc() | DLGC_WANTALLKEYS;
   }
   LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      // Standard colors
      m_di.clrText = ::GetSysColor(COLOR_WINDOWTEXT);
      m_di.clrBack = ::GetSysColor(COLOR_WINDOW);
      m_di.clrSelText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
      m_di.clrSelBack = ::GetSysColor(COLOR_HIGHLIGHT);
      m_di.clrDisabled = ::GetSysColor(COLOR_GRAYTEXT);
      m_di.clrDisabledBack = ::GetSysColor(COLOR_BTNFACE);
      // Border
      m_di.clrBorder = ::GetSysColor(COLOR_BTNFACE);
      if( !m_BorderPen.IsNull() ) m_BorderPen.DeleteObject();
      m_di.Border = m_BorderPen.CreatePen(PS_SOLID, 1, m_di.clrBorder);
      // Fonts
      if( !m_TextFont.IsNull() ) m_TextFont.DeleteObject();
      if( !m_CategoryFont.IsNull() ) m_CategoryFont.DeleteObject();
      LOGFONT lf;
      HFONT hFont = (HFONT) ::SendMessage(GetParent(), WM_GETFONT, 0, 0);
      if( hFont == NULL ) hFont = AtlGetDefaultGuiFont();
      ::GetObject(hFont, sizeof(lf), &lf);
      m_di.TextFont = m_TextFont.CreateFontIndirect(&lf);
      SetFont(m_di.TextFont);
      lf.lfWeight += FW_BOLD;
      m_di.CategoryFont = m_CategoryFont.CreateFontIndirect(&lf);
      // Text metrics
      CClientDC dc(m_hWnd);
      HFONT hOldFont = dc.SelectFont(m_di.TextFont);
      dc.GetTextMetrics(&m_di.tmText);
      dc.SelectFont(hOldFont);
      // Repaint
      Invalidate();
      return 0;
   }

   LRESULT OnSelChanged(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
   {
      LPNMLISTVIEW pnmlv = (LPNMLISTVIEW) pnmh;
      // Only items with selection changes...
      if( (pnmlv->uNewState & LVIS_SELECTED) == 0 ) return 0;
      // Process changed item
      int iItem = pnmlv->iItem;
      if( iItem != -1 ) {
         m_iSelectedRow = iItem;
         if( m_iSelectedCol == -1 ) m_iSelectedCol = 0;
         if( _IsLastAddItem(iItem) ) m_iSelectedCol = 0;
         _InvalidateItem(m_iSelectedRow, m_iSelectedCol);
         // Let owner know
         IProperty* prop = GetProperty(m_iSelectedRow, m_iSelectedCol);
         ATLASSERT(prop);
         NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_SELCHANGED, prop };
         ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
      }
      bHandled = FALSE;
      return 0;
   }

   LRESULT OnDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
   {
      ATLASSERT(m_nColumns>0);
      LPNMLISTVIEW pnmlv = (LPNMLISTVIEW) pnmh;      
      // Destroy in-place editor if active
      _DestroyInplaceWindow();
      if( pnmlv->iItem == m_iSelectedRow && m_iSelectedRow != -1 ) SelectItem(-1, -1);
      // Free sub-item place-holder array
      ATLASSERT(pnmlv->lParam);
      IProperty** props = reinterpret_cast<IProperty**>(pnmlv->lParam);
      for( int i = 0; i < m_nColumns; i++ ) if( props[i] ) delete props[i];
      delete [] props;
      return 0;
   }

   LRESULT OnNavigate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      if( (m_di.dwExtStyle & PGS_EX_NOSHEETNAVIGATION) != 0 ) return 0;
      if( !_IsValidSelection() ) return 0;
      // No editor, please
      _DestroyInplaceWindow();
      // Navigate in the grid control
      switch( wParam) {
      case VK_TAB:
         SendMessage(WM_USER_PROP_NAVIGATE, VK_RIGHT);
         break;
      case VK_LEFT:
         if( m_iSelectedRow >= 0 && m_iSelectedCol > 0 ) {
            // Can we navigate?
            if( _IsLastAddItem(m_iSelectedRow ) ) return 0;
            // Navigate
            m_iSelectedCol--;
            // Let owner know
            IProperty* prop = GetProperty(m_iSelectedRow, m_iSelectedCol);
            ATLASSERT(prop);
            NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_SELCHANGED, prop };
            ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
            // Repaint new and old item
            _InvalidateItem(m_iSelectedRow, m_iSelectedCol + 1);
            _InvalidateItem(m_iSelectedRow, m_iSelectedCol);
         }
         break;
      case VK_RIGHT:
         if( m_iSelectedRow >= 0 && m_iSelectedCol < m_nColumns - 1 ) {
            // Can we navigate?
            if( _IsLastAddItem(m_iSelectedRow ) ) return 0;
            // Navigate
            m_iSelectedCol++;
            // Let owner know
            IProperty* prop = GetProperty(m_iSelectedRow, m_iSelectedCol);
            ATLASSERT(prop);
            NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_SELCHANGED, prop };
            ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
            // Repaint new and old item
            _InvalidateItem(m_iSelectedRow, m_iSelectedCol - 1);
            _InvalidateItem(m_iSelectedRow, m_iSelectedCol);
         }
         break;
      case VK_UP:
         if( m_iSelectedRow > 0 ) SelectItem(m_iSelectedRow - 1, m_iSelectedCol);
         break;
      case VK_DOWN:
         if( m_iSelectedRow < GetItemCount() - 1 ) SelectItem(m_iSelectedRow + 1, m_iSelectedCol);
         break;
      }
      return 0;
   }
   LRESULT OnUpdateProperty(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Updates a property value using an active editor window.
      // The editor window uses this message to update the attached property class.
      // Parameters:
      //   LPARAM = Window (HWND)
      HWND hWnd = reinterpret_cast<HWND>(lParam);     
      ATLASSERT(hWnd);
      if( !::IsWindow(hWnd) || (m_iInplaceRow == -1) || (m_iInplaceCol == -1) ) return 0;
      ATLASSERT(hWnd==m_hwndInplace);
      IProperty* prop = GetProperty(m_iInplaceRow, m_iInplaceCol);
      if( prop == NULL ) return 0;
      // Ask owner about change
      NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_ITEMCHANGING, prop };
      if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
         // Set new value
         if( !prop->SetValue(hWnd) ) ::MessageBeep((UINT)-1);
         // Let owner know
         nmh.hdr.code = PIN_ITEMCHANGED;
         ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
         // Repaint item
         _InvalidateItem(m_iInplaceRow, m_iInplaceCol);
      }
      // Replace in-place control...
      _DestroyInplaceWindow();
      return 0;
   }
   LRESULT OnCancelProperty(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Restores a property value using an active editor window.
      // The editor window uses this message to restore the attached property class
      // with it original value.
      // Parameters:
      //   LPARAM = Window (HWND)
      HWND hWnd = reinterpret_cast<HWND>(lParam);     
      ATLASSERT(hWnd);
      if( !::IsWindow(hWnd) || (m_iInplaceRow == -1) || (m_iInplaceCol == -1) ) return 0;
      ATLASSERT(hWnd==m_hwndInplace);
      // NOTE: The list-item already has the original value; it has only been
      //       obscured by the editor window which it was shown. All we need
      //       to do, is to repaint the list control.
      // Repaint item
      _InvalidateItem(m_iInplaceRow, m_iInplaceCol);
      // Replace in-place control...
      _DestroyInplaceWindow();
      return 0;
   }
   LRESULT OnChangedProperty(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Updates a property value.
      // A property class uses this message to make sure the corresponding editor window
      // is updated as well.
      // Parameters:
      //   WPARAM = New value (VARIANT*)
      //   LPARAM = Property (IProperty*)
      IProperty* prop = reinterpret_cast<IProperty*>(lParam);
      VARIANT* pVariant = reinterpret_cast<VARIANT*>(wParam);
      ATLASSERT(prop && pVariant);
      if( prop == NULL || pVariant == NULL ) return 0;
      // Ask owner about change
      NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_ITEMCHANGING, prop };
      if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
         // Set new value
         // NOTE: Do not call this from IProperty::SetValue(VARIANT*) = endless loop
         if( !prop->SetValue(*pVariant) ) ::MessageBeep((UINT)-1);
         // Let owner know
         nmh.hdr.code = PIN_ITEMCHANGED;
         ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
      }
      // Locate the updated list item
      int iItem;
      int iSubItem;
      if( !FindProperty(prop, iItem, iSubItem) ) return 0;
      // Repaint item
      _InvalidateItem(iItem, iSubItem);
      // Recycle in-place control so it displays the new value
      if( (iItem != -1) && (iItem == m_iInplaceRow) ) _SpawnInplaceWindow(prop, m_iInplaceRow, m_iInplaceCol);
      return 0;
   }

   // Header messages

   LRESULT OnHeaderChanging(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& bHandled)
   {
      // HACK: With the PGS_EX_ADDITEMATEND style we need to
      //       repaint the last item to avoid a paint bug.
      //       Code supplied by Ludvig A. Norin.
      if( (m_di.dwExtStyle & PGS_EX_ADDITEMATEND) != 0 ) {
         RECT rcItem = { 0 };
         GetItemRect(GetItemCount(), &rcItem, LVIR_BOUNDS);
         InvalidateRect(&rcItem, FALSE);
      }
      // Destroy in-place window before dragging header control
      _DestroyInplaceWindow();
      // Done
      bHandled = FALSE;
      return 0;
   }

   LRESULT OnHeaderDblClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
   {
      // TODO
      return 0;
   }

   // Custom painting

   DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
   {
      return CDRF_NOTIFYITEMDRAW;   // We need per-item notifications
   }
   DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
   {
      return CDRF_NOTIFYSUBITEMDRAW; // We need per-subitem notifications
   }
   DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
   {
      T* pT = static_cast<T*>(this);
      LPNMLVCUSTOMDRAW lpNMLVCustomDraw = (LPNMLVCUSTOMDRAW) lpNMCustomDraw;
      pT->DrawItem(lpNMLVCustomDraw->nmcd.hdc, 
         (int) lpNMLVCustomDraw->nmcd.dwItemSpec, 
         lpNMLVCustomDraw->iSubItem,
         lpNMLVCustomDraw->nmcd.uItemState);
      return CDRF_SKIPDEFAULT;
   }

   // Overridables

   void DrawItem(CDCHandle dc, int iItem, int iSubItem, UINT iState)
   {
      bool bIsLastItem = _IsLastAddItem(iItem);
      if( bIsLastItem && iSubItem != 0 ) return;

      IProperty* prop = GetProperty(iItem, iSubItem);
      if( prop == NULL ) return;

      // Figure out rectangle
      RECT rc;
      _GetSubItemRect(iItem, iSubItem, &rc);

      // Draw properties
      PROPERTYDRAWINFO di = m_di;
      di.hDC = dc;
      di.rcItem = rc;

      di.state = 0;   
      if( iItem == m_iSelectedRow && iSubItem == m_iSelectedCol ) di.state |= ODS_SELECTED;
      if( iItem == m_iInplaceRow && iSubItem == m_iInplaceCol ) di.state |= ODS_COMBOBOXEDIT;
      if( !prop->IsEnabled() ) di.state |= ODS_DISABLED;

      if( iItem == m_iSelectedRow ) {
         // Full row-select feature
         if( (m_di.dwExtStyle & PGS_EX_FULLROWSELECT) != 0 ) {
            di.clrBack = di.clrDisabledBack;
         }
         // Is this the selected sub-item
         if( iSubItem == m_iSelectedCol ) {
            di.state |= ODS_SELECTED;
            // Selection inverted feature
            if( (m_di.dwExtStyle & PGS_EX_INVERTSELECTION) != 0 ) {
               di.clrBack = di.clrSelBack;
               di.clrText = di.clrSelText;
            }
         }
      }

      // A disabled ListView control is painted grey on Win2000
      // but the text remains black...
      DWORD dwStyle = GetStyle();
      if( dwStyle & WS_DISABLED ) di.clrBack = di.clrDisabledBack;

      // Erase background
      dc.FillSolidRect(&rc, di.clrBack);

      // Draw item
      HFONT hOldFont = dc.SelectFont(di.TextFont);
      prop->DrawValue(di);
      dc.SelectFont(hOldFont);

      // Draw borders
      if( (di.dwExtStyle & PGS_EX_NOGRID) == 0 ) {
         CPen pen;
         pen.CreatePen(PS_SOLID, 1, di.clrBorder);
         HPEN hOldPen = dc.SelectPen(pen);
         dc.MoveTo(rc.left, rc.bottom-1);
         dc.LineTo(rc.right - 1, rc.bottom - 1);
         dc.LineTo(rc.right - 1, rc.top - 1);
         dc.SelectPen(hOldPen);
      }

      // Paint focus rectangle
      if( (::GetFocus() == m_hWnd && (iState & CDIS_FOCUS) != 0) || (dwStyle & LVS_SHOWSELALWAYS) != 0 ) {
         if( (iItem == m_iSelectedRow) && (iSubItem == m_iSelectedCol || bIsLastItem ) ) {
            if( iItem != m_iInplaceRow && iSubItem != m_iInplaceCol ) {
               if( (GetExtendedListViewStyle() & LVS_EX_GRIDLINES) != 0 ) {
                  rc.left++; rc.right--; rc.bottom--;
               }
               CBrush brush;
               brush.CreateSolidBrush(di.clrSelBack);
               dc.FrameRect(&rc, brush);
            }
         }
      }
   }
};


class CPropertyGridCtrl : public CPropertyGridImpl<CPropertyGridCtrl>
{
public:
   DECLARE_WND_SUPERCLASS(_T("WTL_PropertyGrid"), GetWndClassName())
};


#endif __PROPERTYGRID__H

⌨️ 快捷键说明

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