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

📄 propertygrid.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 3 页
字号:
#ifndef __PROPERTYGRID__H
#define __PROPERTYGRID__H

#pragma once

/////////////////////////////////////////////////////////////////////////////
// CPropertyGrid - A simple grid control
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2002-2003 Bjarke Viksoe.
// Thanks to Ludvig A. Norin for the PGS_EX_ADDITEMATEND feature.
//
// Add the following macro to the parent's message map:
//   REFLECT_NOTIFICATIONS()
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

#ifndef __cplusplus
  #error WTL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
  #error PropertyGrid.h requires atlapp.h to be included first
#endif

#if (_WTL_VER < 0x0700)
   #error This file requires WTL version 7.0 or higher
#endif

#ifndef __ATLCTRLS_H__
  #error PropertyGrid.h requires atlctrls.h to be included first
#endif

#if (_WIN32_IE < 0x0400)
  #error PropertyGrid.h requires IE4
#endif

#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
  #include <zmouse.h>
#endif //!((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))


// Include property base class
#include "PropertyItem.h"

// Include property implementations
#include "PropertyItemEditors.h"
#include "PropertyItemImpl.h"



/////////////////////////////////////////////////////////////////////////////
// CPropertyGrid control

// Extended Grid styles
#define PGS_EX_SINGLECLICKEDIT   0x00000001
#define PGS_EX_NOGRID            0x00000002
#define PGS_EX_TABNAVIGATION     0x00000004
#define PGS_EX_NOSHEETNAVIGATION 0x00000008
#define PGS_EX_FULLROWSELECT     0x00000010
#define PGS_EX_INVERTSELECTION   0x00000020
#define PGS_EX_ADDITEMATEND      0x00000040



/////////////////////////////////////////////////////////////////////////////
// The "Last item" property (PGS_EX_ADDITEMATEND support)

class CPropertyLastItem : public CProperty
{
public:
   CPropertyLastItem(LPCTSTR pstrName, LPARAM lParam) : 
      CProperty(pstrName, lParam)
   {
   }
   BYTE GetKind() const 
   { 
      return PROPKIND_SIMPLE;
   }
   void DrawValue(PROPERTYDRAWINFO& di)
   {
	   try{
	   
#ifdef IDS_LASTVALUE
      TCHAR szText[128] = { 0 };
      ::LoadString(_Module.GetResourceInstance(), IDS_LASTVALUE, szText, (sizeof(szText)/sizeof(TCHAR))-1);
      LPCTSTR pstrText = szText;
#else
      LPCTSTR pstrText = _T("<< 单击这里添加新的选项 >>");
#endif
      CDCHandle dc(di.hDC);
      dc.SetBkMode(TRANSPARENT);
      dc.SetTextColor(di.state & ODS_DISABLED ? di.clrDisabled : di.clrText);
      dc.SetBkColor(di.clrBack);
      RECT rcText = di.rcItem;
      rcText.left += PROP_TEXT_INDENT;
      dc.DrawText(pstrText, -1, 
         &rcText, 
         DT_LEFT | DT_SINGLELINE | DT_EDITCONTROL | DT_NOPREFIX | DT_END_ELLIPSIS | DT_VCENTER);
	   }
	   catch (_com_error &e)
	   {

		   error("File:%s\nLine:%d\nCode = %08lx\nCode meaning = %s\nSource = %s\nError Description = %s\n",
				__FILE__,
				__LINE__,
				e.Error(), 
				(TCHAR*) e.ErrorMessage(),
				(TCHAR*) e.Source()
				, (TCHAR*) e.Description());

	   }
	   catch(...)
	   {
		   TCHAR szErr[1024];
		   GetErrDesc(szErr);
		   error("File:%s \n Line:%d\n Error:%s",__FILE__,__LINE__,szErr);
	   }

   }
   BOOL Activate(UINT action, LPARAM /*lParam*/) 
   { 
      switch( action ) {
      case PACT_SPACE:
      case PACT_CLICK:
      case PACT_DBLCLICK:
         // Send AddItem notification to parent of control
         NMPROPERTYITEM nmh = { m_hWndOwner, ::GetDlgCtrlID(m_hWndOwner), PIN_ADDITEM, NULL };
         ::SendMessage(::GetParent(m_hWndOwner), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
         break;
      }
      return TRUE;
   }
};

inline HPROPERTY PropCreateLastItem(LPCTSTR pstrName, LPARAM lParam = 0)
{
   return new CPropertyLastItem(pstrName, lParam);
}


/////////////////////////////////////////////////////////////////////////////
// Block property - looks like a header (or button)

class CPropertyBlockItem : public CProperty
{
public:
   CPropertyBlockItem(LPCTSTR pstrName, LPARAM lParam) : 
      CProperty(pstrName, lParam)
   {
   }
   BYTE GetKind() const 
   { 
      return PROPKIND_SIMPLE;
   }
   void DrawValue(PROPERTYDRAWINFO& di)
   {
      RECT rc = di.rcItem;
      rc.bottom--;
      ::DrawFrameControl(di.hDC, &rc, DFC_BUTTON, DFCS_BUTTONPUSH);
   }
   BOOL Activate(UINT action, LPARAM /*lParam*/) 
   { 
      switch( action ) {
      case PACT_SPACE:
      case PACT_CLICK:
      case PACT_DBLCLICK:
         // Send AddItem notification to parent of control
         NMPROPERTYITEM nmh = { m_hWndOwner, ::GetDlgCtrlID(m_hWndOwner), PIN_BROWSE, NULL };
         ::SendMessage(::GetParent(m_hWndOwner), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
         break;
      }
      return TRUE;
   }
};

inline HPROPERTY PropCreateBlockItem(LPCTSTR pstrName, LPARAM lParam = 0)
{
   return new CPropertyBlockItem(pstrName, lParam);
}


/////////////////////////////////////////////////////////////////////////////
// The Property Grid control

template< class T, class TBase = CListViewCtrl, class TWinTraits = CWinTraitsOR<LVS_SINGLESEL|LVS_SHOWSELALWAYS> >
class ATL_NO_VTABLE CPropertyGridImpl : 
   public CWindowImpl< T, TBase, TWinTraits >,
   public CCustomDraw< CPropertyGridImpl >
{
public:
   DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())

   CHeaderCtrl m_ctrlHeader;
   PROPERTYDRAWINFO m_di;
   CFont m_TextFont;
   CFont m_CategoryFont;
   CPen m_BorderPen;
   HWND m_hwndInplace;
   int m_iInplaceRow;
   int m_iInplaceCol;
   int m_nColumns;
   int m_iSelectedRow;
   int m_iSelectedCol;

   CPropertyGridImpl() : 
      m_hwndInplace(NULL), 
      m_iInplaceRow(-1), 
      m_iInplaceCol(-1), 
      m_nColumns(0), 
      m_iSelectedRow(-1), 
      m_iSelectedCol(-1)
   {
      m_di.dwExtStyle = 0;
   }

   // Operations

   BOOL SubclassWindow(HWND hWnd)
   {
      ATLASSERT(m_hWnd==NULL);
      ATLASSERT(::IsWindow(hWnd));
      BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
      if( bRet ) _Init();
      return bRet;
   }

   void SetExtendedGridStyle(DWORD dwExtStyle)
   {
      // Handle change of PGS_EX_ADDITEMATEND flag
      if( (m_di.dwExtStyle & PGS_EX_ADDITEMATEND) != 0 
          && (dwExtStyle & PGS_EX_ADDITEMATEND) == 0 ) 
      {
         // Remove last item
         DeleteItem(TBase::GetItemCount()-1);
      } 
      else if( (dwExtStyle & PGS_EX_ADDITEMATEND) != 0 ) {
         // Add last item
         InsertItem(TBase::GetItemCount(), PropCreateLastItem(_T(""))); 
      }
      // Assign new style
      m_di.dwExtStyle = dwExtStyle;
      // Recalc colours and fonts
      SendMessage(WM_SETTINGCHANGE);
   }
   DWORD GetExtendedGridStyle() const
   {
      return m_di.dwExtStyle;
   }

   BOOL SelectItem(int iRow, int iCol = 0)
   {
      // No editor and remove focus
      _DestroyInplaceWindow();
      _InvalidateItem(m_iSelectedRow, m_iSelectedCol);
      // Select new item. If on same row then use internal update.
      m_iSelectedCol = iCol;
      if( GetSelectedIndex() == m_iSelectedRow && m_iSelectedRow == iRow ) {         
         NMLISTVIEW nmlv = { m_hWnd, 0, 0, m_iSelectedRow, m_iSelectedCol, LVIS_SELECTED };
         BOOL bDummy;   
         OnSelChanged(0, reinterpret_cast<LPNMHDR>(&nmlv), bDummy);
         return TRUE;
      }
      else {
         return TBase::SelectItem(iRow);
      }
   }
   int GetItemCount() const
   {
      if( (m_di.dwExtStyle & PGS_EX_ADDITEMATEND) != 0 ) return TBase::GetItemCount()-1;
      return TBase::GetItemCount();
   }
   int InsertItem(int nItem, HPROPERTY hProp)
   {
      // NOTE: This is the only InsertItem() we support...
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(hProp);
      // You must have initialized columns before calling this!
      // And you are not allowed to add columns once the list is populated!
      if( m_nColumns == 0 ) m_nColumns = m_ctrlHeader.GetItemCount();
      ATLASSERT(m_nColumns>0);
      ATLASSERT(m_ctrlHeader.GetItemCount()==m_nColumns);
      // Create a place-holder for all sub-items
      IProperty** props;
      ATLTRY( props = new IProperty*[m_nColumns] );
      ATLASSERT(props);
      if( props == NULL ) return -1;
      ::ZeroMemory(props, sizeof(IProperty*) * m_nColumns);
      props[0] = hProp;
      // Finally create the listview item itself...
      if( nItem < 0 || nItem > GetItemCount() ) nItem = GetItemCount();
      UINT mask = LVIF_TEXT | LVIF_PARAM;
      int iItem = TBase::InsertItem(mask, nItem, hProp->GetName(), 0, 0, 0, (LPARAM) props); 
      if( iItem != -1 ) hProp->SetOwner(m_hWnd, NULL);
      return iItem;
   }
   BOOL SetSubItem(int nItem, int nSubItem, HPROPERTY hProp)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(hProp);
      ATLASSERT(nSubItem >= 0);
      ATLASSERT(nSubItem < m_nColumns);
      IProperty** props = reinterpret_cast<IProperty**>(TBase::GetItemData(nItem));
      ATLASSERT(props);
      ATLASSERT(props[nSubItem]==NULL); // Do not replace HPROPERTY nodes.
      if( props == NULL ) return FALSE;
      if( nSubItem < 0 || nSubItem >= m_nColumns ) return FALSE;
      props[nSubItem] = hProp;
      hProp->SetOwner(m_hWnd, NULL);
      // Trick ListView into thinking there is a subitem...
      return TBase::SetItemText(nItem, nSubItem, _T(""));
   }
   BOOL GetItemText(int iItem, int iSubItem, LPTSTR pstrText, UINT cchMax) const
   {
      return GetItemText(GetProperty(iItem, iSubItem), pstrText, cchMax);
   }
   BOOL GetItemText(HPROPERTY hProp, LPTSTR pstrText, UINT cchMax) const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(hProp);
      ATLASSERT(!::IsBadWritePtr(pstrText,cchMax));
      if( hProp == NULL || pstrText == NULL ) return FALSE;
      return hProp->GetDisplayValue(pstrText, cchMax);
   }
   BOOL GetItemValue(HPROPERTY hProp, VARIANT* pValue) const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(hProp);
      ATLASSERT(pValue);
      if( hProp == NULL || pValue == NULL ) return FALSE;
      return hProp->GetValue(pValue);
   }
   BOOL SetItemValue(HPROPERTY hProp, VARIANT* pValue)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      ATLASSERT(hProp);
      ATLASSERT(pValue);
      if( hProp == NULL || pValue == NULL ) return FALSE;
      // Assign value and repaint
      BOOL bRes = hProp->SetValue(*pValue);
      // Find property position and repaint it...
      int nItem;
      int nSubItem;
      if( !FindProperty(hProp, nItem, nSubItem) ) return FALSE;
      _InvalidateItem(nItem, nSubItem);
      // If changing selected item then recreate in-place editor
      if( (m_hwndInplace != NULL) && (nItem == m_iInplaceRow) && (nSubItem == m_iInplaceCol) ) _SpawnInplaceWindow(hProp, m_iInplaceRow, m_iInplaceCol);
      return bRes;
   }
   int GetSelectedColumn() const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      return m_iSelectedCol;
   }
   BOOL DeleteColumn(int nCol)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      if( TBase::GetItemCount() == 0 ) {
         m_nColumns = 0;
         return TBase::DeleteColumn(nCol);
      }
      ATLASSERT(false); // Remove items first
      return FALSE;
   }
   BOOL GetColumnCount() const
   {
      ATLASSERT(::IsWindow(m_hWnd));
      return GetHeader().GetItemCount();
   }
   BOOL FindProperty(IProperty* prop, int& iItem, int& iSubItem) const
   {
      // Looks up the item index based on the property class.
      // The property class may be a subitem, so we need to scan ALL properties.
      ATLASSERT(prop);

⌨️ 快捷键说明

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