📄 propertytree.h
字号:
#if !defined(AFX_PROPERTYTREE_H__20020106_D62E_63DE_426B_0080AD509054__INCLUDED_)
#define AFX_PROPERTYTREE_H__20020106_D62E_63DE_426B_0080AD509054__INCLUDED_
#pragma once
/////////////////////////////////////////////////////////////////////////////
// CPropertyTree - A Property Tree control
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2001 Bjarke Viksoe.
//
// 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 PropertyTree.h requires atlapp.h to be included first
#endif
#ifndef __ATLCTRLS_H__
#error PropertyTree.h requires atlctrls.h to be included first
#endif
#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
#include <zmouse.h>
#endif //!((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
// Extended Tree styles
#define PTS_EX_ICONCLICK 0x00000001
#define PTS_EX_NOCOLLAPSE 0x00000002
#define PTS_EX_SINGLECLICKEDIT 0x00000004
// Include property base class
#include "PropertyItem.h"
// Include property implementations
#include "PropertyItemEditors.h"
#include "PropertyItemImpl.h"
/////////////////////////////////////////////////////////////////////////////
// The Checkmark & Option Controls
class CPropertyCheckmarkItem : public CProperty
{
public:
CTreeViewCtrl m_tree;
HTREEITEM m_hItem;
bool m_bValue;
CPropertyCheckmarkItem(LPCTSTR pstrName, bool bValue, LPARAM lParam) :
CProperty(pstrName, lParam),
m_hItem(NULL), m_bValue(bValue)
{
}
BYTE GetKind() const
{
return PROPKIND_CHECK;
}
void SetOwner(HWND hWnd, LPVOID pData)
{
ATLASSERT(::IsWindow(hWnd));
ATLASSERT(m_hWndOwner==NULL); // Cannot set it twice
m_hWndOwner = hWnd;
m_tree.Attach( hWnd );
m_hItem = reinterpret_cast<HTREEITEM>(pData);
CComVariant v(m_bValue);
SetValue(v);
}
BOOL GetValue(VARIANT* pVal) const
{
return SUCCEEDED( CComVariant(m_bValue).Detach(pVal) );
}
BOOL SetValue(const VARIANT& value)
{
// Set a new value
switch( value.vt ) {
case VT_BOOL:
m_bValue = value.boolVal != VARIANT_FALSE;
break;
default:
ATLASSERT(false);
return FALSE;
}
// Update images
int iImage = m_bValue ? 1 : 0;
if( !IsEnabled() ) iImage += 4;
m_tree.SetItemImage(m_hItem, iImage, iImage);
return TRUE;
}
BOOL Activate(UINT action, LPARAM /*lParam*/)
{
switch( action ) {
case PACT_SPACE:
case PACT_CLICK:
case PACT_DBLCLICK:
if( IsEnabled() ) {
CComVariant v = !m_bValue;
::SendMessage(m_hWndOwner, WM_USER_PROP_CHANGEDPROPERTY, (WPARAM)(VARIANT*) &v, (LPARAM) this);
}
break;
}
return TRUE;
}
};
class CPropertyOptionItem : public CPropertyCheckmarkItem
{
public:
CPropertyOptionItem(LPCTSTR pstrName, bool bValue, LPARAM lParam) : CPropertyCheckmarkItem(pstrName, bValue, lParam)
{
}
BOOL SetValue(const VARIANT& value)
{
// Set value
switch( value.vt ) {
case VT_BOOL:
m_bValue = value.boolVal != VARIANT_FALSE;
break;
default:
ATLASSERT(false);
return FALSE;
}
// Set new image
int iImage = m_bValue ? 3 : 2;
if( !IsEnabled() ) iImage += 4;
m_tree.SetItemImage(m_hItem, iImage, iImage);
// If we clicked this item (rather than someone removed the checkmark)
// we automatically exclude all siblings around us
if( m_bValue ) {
// NOTE: We need to use SendMessage() and a private msg, since
// we only have a CTreeViewCtrl and not a complete CPropertyTreeCtrl
// control on our hands.
HTREEITEM hItem;
hItem = m_tree.GetPrevSiblingItem(m_hItem);
while( hItem ) {
if( m_tree.SendMessage(WM_USER_PROP_SETCHECKSTATE, (WPARAM) hItem, (LPARAM) FALSE) == FALSE ) break;
hItem = m_tree.GetPrevSiblingItem(hItem);
}
hItem = m_tree.GetNextSiblingItem(m_hItem);
while( hItem ) {
if( m_tree.SendMessage(WM_USER_PROP_SETCHECKSTATE, (WPARAM) hItem, (LPARAM) FALSE) == FALSE ) break;
hItem = m_tree.GetNextSiblingItem(hItem);
}
}
return TRUE;
}
BOOL Activate(UINT action, LPARAM /*lParam*/)
{
switch( action ) {
case PACT_SPACE:
case PACT_CLICK:
if( IsEnabled() ) {
CComVariant v = true;
::SendMessage(m_hWndOwner, WM_USER_PROP_CHANGEDPROPERTY, (WPARAM) (VARIANT*) &v, (LPARAM) this);
}
break;
}
return TRUE;
}
};
inline HPROPERTY PropCreateCheckmark(LPCTSTR pstrName, bool bValue=false, LPARAM lParam=0)
{
return new CPropertyCheckmarkItem(pstrName, bValue, lParam);
}
inline HPROPERTY PropCreateOptionCheck(LPCTSTR pstrName, bool bValue=false, LPARAM lParam=0)
{
return new CPropertyOptionItem(pstrName, bValue, lParam);
}
/////////////////////////////////////////////////////////////////////////////
// CPropertyTree control
template< class T, class TBase = CTreeViewCtrl, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE CPropertyTreeImpl :
public CWindowImpl< T, TBase, TWinTraits >,
public CCustomDraw< CPropertyTreeImpl >
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
enum { HORIZ_VALUE_GAP = 4 };
PROPERTYDRAWINFO m_di;
CFont m_TextFont;
CFont m_CategoryFont;
CPen m_BorderPen;
HWND m_hwndInplace;
HTREEITEM m_iInplaceIndex;
bool m_bSeenClicks;
int m_cxColumn;
CPropertyTreeImpl() :
m_hwndInplace(NULL),
m_iInplaceIndex(NULL),
m_bSeenClicks(false),
m_cxColumn(0)
{
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 SetExtendedTreeStyle(DWORD dwExtStyle)
{
ATLASSERT(::IsWindow(m_hWnd));
m_di.dwExtStyle = dwExtStyle;
Invalidate();
}
DWORD GetExtendedTreeStyle() const
{
return m_di.dwExtStyle;
}
void SetColumnPosition(int iPos)
{
m_cxColumn = iPos;
}
BOOL DeleteAllItems()
{
ATLASSERT(::IsWindow(m_hWnd));
_DestroyInplaceWindow();
return TBase::DeleteAllItems();
}
HTREEITEM InsertItem(HPROPERTY hProp, int nImage, int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter = TVI_LAST)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(hProp);
m_bSeenClicks = false;
// NOTE: This is the only InsertItem() we support...
UINT mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
LPARAM lParam = (LPARAM)hProp;
HTREEITEM hItem = TBase::InsertItem(mask, hProp->GetName(), nImage, nSelectedImage, 0, 0, lParam, hParent, hInsertAfter);
if( hItem ) {
hProp->SetOwner(m_hWnd, (LPVOID) hItem);
Expand(hParent);
}
return hItem;
}
BOOL GetItem(LPTVITEM pItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
// On the fly replacement of LPARAM...
BOOL bRes = TBase::GetItem(pItem);
if( bRes && (pItem->mask & TVIF_PARAM) ) {
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(pItem->hItem));
ATLASSERT(prop);
if( prop == NULL ) return FALSE;
pItem->lParam = prop->GetItemData();
}
return bRes;
}
BOOL SetItem(LPTVITEM pItem)
{
ATLASSERT(::IsWindow(m_hWnd));
// NOTE: Cannot change these styles...
// TEXT is duplicated in both tree and in property class - and
// not really available to us.
// PARAM is private. Use SetItemData() instead!
ATLASSERT(pItem->mask & (TVIF_TEXT|TVIF_PARAM))==0);
return TBase::SetItem(pItem);
}
BOOL GetItemValue(HTREEITEM hItem, VARIANT* pVal) const
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -