📄 propertytree.h
字号:
return prop->GetValue(pVal) == S_OK;
}
BOOL SetItemValue(HTREEITEM hItem, VARIANT* pValue)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(pValue);
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return FALSE;
// Assign value and repaint
BOOL bRes = prop->SetValue(*pValue);
_InvalidateItem(hItem);
// If changing selected item then recreate in-place editor
if( m_iInplaceIndex && (GetSelectedItem() == m_iInplaceIndex) ) _SpawnInplaceWindow(prop, m_iInplaceIndex);
return bRes;
}
DWORD_PTR GetItemData(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return 0;
return (DWORD_PTR) prop->GetItemData();
}
void SetItemData(HTREEITEM hItem, DWORD_PTR dwData)
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return;
prop->SetItemData( (LPARAM) dwData );
}
BOOL GetCheckState(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
ATLASSERT(prop->GetKind()==PROPKIND_CHECK);
if( prop == NULL ) return FALSE;
if( prop->GetKind() != PROPKIND_CHECK ) return FALSE;
CComVariant v;
prop->GetValue(&v);
return v.boolVal != VARIANT_FALSE;
}
BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck)
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
ATLASSERT(prop->GetKind()==PROPKIND_CHECK);
if( prop == NULL ) return FALSE;
if( prop->GetKind() != PROPKIND_CHECK ) return FALSE;
// Refresh image
CComVariant v = (bCheck == TRUE);
if( !prop->SetValue(v) ) return FALSE;
_InvalidateItem(hItem);
return TRUE;
}
BOOL IsItemEnabled(HTREEITEM hItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return FALSE;
return (DWORD_PTR) prop->IsEnabled();
}
void EnableItem(HTREEITEM hItem, BOOL bState)
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return;
prop->SetEnabled(bState);
// The checkmark/option tree-properties need special care, since
// they will not repaint correctly unless changing the value...
if( prop->GetKind() == PROPKIND_CHECK ) {
// Refresh image
CComVariant v;
prop->GetValue(&v);
prop->SetValue(v);
}
_InvalidateItem(hItem);
}
BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const
{
ATLASSERT(::IsWindow(m_hWnd));
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop == NULL ) return FALSE;
::lstrcpyn(lpstrText, prop->GetName(), nLen);
return TRUE;
}
BOOL SetItemText(HTREEITEM /*hItem*/, LPCTSTR /*lpszItem*/)
{
ATLASSERT(false);
return FALSE;
}
// Implementation
void _Init()
{
ATLASSERT(::IsWindow(m_hWnd));
ModifyStyle(TVS_CHECKBOXES | TVS_FULLROWSELECT, TVS_SHOWSELALWAYS);
SendMessage(WM_SETTINGCHANGE);
}
HTREEITEM _FindProperty(HPROPERTY prop, HTREEITEM hItem = NULL) const
{
if( hItem == NULL ) hItem = GetRootItem();
while( hItem ) {
if( TBase::GetItemData(hItem) == (DWORD_PTR) prop ) return hItem;
// Recurse into children
HTREEITEM hChild = GetChildItem(hItem);
if( hChild ) {
hChild = _FindProperty(prop, hChild);
if( hChild && (TBase::GetItemData(hChild) == (DWORD_PTR) prop) ) return hChild;
}
// Get next sibling
hItem = GetNextSiblingItem(hItem);
}
return NULL;
}
void _GetInplaceRect(HTREEITEM iItem, RECT* pRect) const
{
ATLASSERT(iItem);
ATLASSERT(pRect);
RECT rcText;
GetItemRect(iItem, &rcText, TRUE);
RECT rcItem;
GetItemRect(iItem, &rcItem, FALSE);
::SetRect(pRect, rcText.right + HORIZ_VALUE_GAP, rcItem.top, rcItem.right, rcItem.bottom);
if( m_cxColumn>0 ) pRect->left = max( (int) pRect->left, m_cxColumn );
}
void _DestroyInplaceWindow()
{
if( m_hwndInplace && ::IsWindow(m_hwndInplace) ) {
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(m_iInplaceIndex));
ATLASSERT(prop);
BYTE bKind = prop->GetKind();
// Set focus back to our control
if( ::GetFocus() != m_hWnd && IsChild(::GetFocus()) ) SetFocus();
// Destroy control
switch( bKind ) {
case PROPKIND_CONTROL:
::DestroyWindow(m_hwndInplace);
break;
default:
::PostMessage(m_hwndInplace, WM_CLOSE, 0,0);
}
}
m_hwndInplace = NULL;
m_iInplaceIndex = NULL;
}
BOOL _SpawnInplaceWindow(IProperty* prop, HTREEITEM hItem)
{
ATLASSERT(prop);
ATLASSERT(hItem);
// Destroy old editor
_DestroyInplaceWindow();
// Do we need an editor here?
if( hItem == NULL || hItem != GetSelectedItem() ) return FALSE;
if( !prop->IsEnabled() ) return FALSE;
// Create a new editor window
RECT rcValue;
_GetInplaceRect(hItem, &rcValue);
::InflateRect(&rcValue, 0, -1);
m_hwndInplace = prop->CreateInplaceControl(m_hWnd, rcValue);
if( m_hwndInplace != NULL ) {
// Activate the new editor window
ATLASSERT(::IsWindow(m_hwndInplace));
::SetWindowPos(m_hwndInplace, HWND_TOP, 0,0,0,0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
m_iInplaceIndex = hItem;
}
return m_hwndInplace != NULL;
}
void _InvalidateItem(HTREEITEM hItem)
{
if( hItem == NULL ) return;
RECT rc;
GetItemRect(hItem, &rc, FALSE);
InvalidateRect(&rc);
}
// Message map and handlers
BEGIN_MSG_MAP(CPropertyTreeImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_SIZE, OnScroll)
MESSAGE_HANDLER(WM_VSCROLL, OnScroll)
MESSAGE_HANDLER(WM_HSCROLL, OnScroll)
MESSAGE_HANDLER(WM_MOUSEWHEEL, OnScroll)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_CHAR, OnChar)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
MESSAGE_HANDLER(WM_USER_PROP_NAVIGATE, OnNavigate);
MESSAGE_HANDLER(WM_USER_PROP_UPDATEPROPERTY, OnUpdateProperty);
MESSAGE_HANDLER(WM_USER_PROP_CANCELPROPERTY, OnCancelProperty);
MESSAGE_HANDLER(WM_USER_PROP_CHANGEDPROPERTY, OnChangedProperty);
MESSAGE_HANDLER(WM_USER_PROP_SETCHECKSTATE, OnSetCheckState);
REFLECTED_NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnSelChanged)
REFLECTED_NOTIFY_CODE_HANDLER(TVN_DELETEITEM, OnDeleteItem)
REFLECTED_NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnExpanding)
REFLECTED_NOTIFY_CODE_HANDLER(NM_CLICK, OnClick)
REFLECTED_NOTIFY_CODE_HANDLER(NM_DBLCLK, OnDblClick)
CHAIN_MSG_MAP_ALT(CCustomDraw<CPropertyTreeImpl>, 1)
DEFAULT_REFLECTION_HANDLER()
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*/)
{
DeleteAllItems(); // Make sure to delete editor and item-data memory
return 0;
}
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);
// 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);
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 OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
LRESULT lRes = DefWindowProc();
// Spawn editor right away for selected item
IProperty* prop = NULL;
HTREEITEM hItem = GetSelectedItem();
if( hItem ) {
prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop->IsEnabled() ) {
prop->Activate(PACT_ACTIVATE, 0);
_SpawnInplaceWindow(prop, hItem);
}
}
return lRes;
}
LRESULT OnScroll(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// HACK: When scrolling we need to destroy the in-place editor
// because the cursor would become out-of-sync...
_DestroyInplaceWindow();
bHandled = FALSE;
return 0;
}
LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
HTREEITEM hItem = GetSelectedItem();
if( hItem == NULL ) return 0;
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
switch( LOWORD(wParam) ) {
case VK_TAB:
prop->Activate(PACT_TAB, 0);
break;
case VK_F2:
case VK_RIGHT:
case VK_SPACE:
_SpawnInplaceWindow(prop, hItem);
prop->Activate(PACT_SPACE, 0);
break;
}
return 0;
}
LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
switch( wParam ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -