📄 propertytree.h
字号:
case _T(' '):
// Don't want to hear nasty Windows beep sound...
return 0;
default:
bHandled = FALSE;
return 0;
}
}
LRESULT OnNavigate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
switch( wParam) {
case VK_UP:
case VK_DOWN:
_DestroyInplaceWindow();
SelectItem(GetNextItem(GetSelectedItem(), wParam == VK_UP ? TVGN_PREVIOUSVISIBLE : TVGN_NEXTVISIBLE));
break;
}
return 0;
}
LRESULT OnSetCheckState(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
return SetCheckState( (HTREEITEM) wParam, (BOOL) lParam );
}
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_iInplaceIndex == NULL ) return 0;
ATLASSERT(hWnd==m_hwndInplace);
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(m_iInplaceIndex));
ATLASSERT(prop);
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_iInplaceIndex);
// Recycle in-place control so it displays the correct value
// NOTE: Traps condition where the SetValue() fails!
HTREEITEM hItem = _FindProperty(prop);
if( hItem && (hItem == m_iInplaceIndex) ) _SpawnInplaceWindow(prop, hItem);
}
return 0;
}
LRESULT OnCancelProperty(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_iInplaceIndex == NULL ) return 0;
ATLASSERT(hWnd==m_hwndInplace);
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(m_iInplaceIndex));
ATLASSERT(prop);
// Repaint item
_InvalidateItem(m_iInplaceIndex);
// Recycle in-place control so it displays the (old) value
HTREEITEM hItem = _FindProperty(prop);
if( hItem && (hItem == m_iInplaceIndex) ) _SpawnInplaceWindow(prop, hItem);
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 tree item
HTREEITEM hItem = _FindProperty(prop);
// Repaint item
_InvalidateItem(hItem);
// Recycle in-place control so it displays the new value
if( hItem && (hItem == m_iInplaceIndex) ) _SpawnInplaceWindow(prop, hItem);
return 0;
}
LRESULT OnDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) pnmh;
_DestroyInplaceWindow();
ATLASSERT(pnmtv->itemOld.lParam);
delete (IProperty*) pnmtv->itemOld.lParam;
return 0;
}
LRESULT OnClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& bHandled)
{
m_bSeenClicks = true;
// Get the item we're clicking on
DWORD dwPos = ::GetMessagePos();
POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
ScreenToClient(&pt);
UINT uFlags;
HTREEITEM hItem = HitTest(pt, &uFlags);
// Send click event
if( hItem ) {
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
// Test for icon-area click restriction
bool bClick = prop->IsEnabled() == TRUE;
switch( prop->GetKind() ) {
case PROPKIND_CHECK:
bClick = ((m_di.dwExtStyle & PTS_EX_ICONCLICK) == 0) || (uFlags & TVHT_ONITEMICON);
if( uFlags & TVHT_ONITEMRIGHT ) bClick = false;
break;
case PROPKIND_SIMPLE:
if( uFlags & TVHT_ONITEMRIGHT ) bClick = false;
break;
default:
if( GetSelectedItem() != hItem ) SelectItem(hItem); // When clicking on the right
if( uFlags & TVHT_ONITEMRIGHT ) bClick = true;
break;
}
if( bClick ) {
// Ask owner first
NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_CLICK, prop };
if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
// Send Click action
LPARAM lParam = ::GetMessagePos();
prop->Activate(PACT_CLICK, lParam);
}
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnDblClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& bHandled)
{
HTREEITEM hItem = GetSelectedItem();
if( hItem ) {
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
// Ask owner first
NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_DBLCLICK, prop };
if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) == 0 ) {
// Send DblClick action
LPARAM lParam = ::GetMessagePos();
prop->Activate(PACT_DBLCLICK, lParam);
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnSelChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
{
IProperty* prop = NULL;
HTREEITEM hItem = GetSelectedItem();
if( hItem ) {
prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
if( prop->IsEnabled() ) {
_SpawnInplaceWindow(prop, hItem);
prop->Activate(PACT_ACTIVATE, 0);
if( m_di.dwExtStyle & PTS_EX_SINGLECLICKEDIT ) {
if( prop->GetKind() == PROPKIND_EDIT ) prop->Activate(PACT_DBLCLICK, 0);
}
}
else {
_DestroyInplaceWindow();
}
}
// Let owner know
NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), PIN_SELCHANGED, prop };
::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh);
return 0;
}
LRESULT OnExpanding(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
{
// Test for style that prevents collapsing
if( (m_di.dwExtStyle & PTS_EX_NOCOLLAPSE) && m_bSeenClicks ) return TRUE;
// Convert to PropertyTree notifications...
LPNMTREEVIEW nmtv = (LPNMTREEVIEW) pnmh;
HTREEITEM hItem = nmtv->itemNew.hItem;
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
UINT nMsg = nmtv->action == TVE_COLLAPSE ? PIN_COLLAPSING : PIN_EXPANDING;
NMPROPERTYITEM nmh = { m_hWnd, GetDlgCtrlID(), nMsg, prop };
if( ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM) &nmh) != 0 ) return TRUE;
// Let others have a go...
bHandled = FALSE;
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_NOTIFYPOSTPAINT; // We need more notifications
}
DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
T* pT = static_cast<T*>(this);
pT->DrawTreeItem(lpNMCustomDraw->hdc, (HTREEITEM) lpNMCustomDraw->dwItemSpec, lpNMCustomDraw->uItemState);
return CDRF_DODEFAULT;
}
// Overridables
void DrawTreeItem(CDCHandle dc, HTREEITEM hItem, UINT iState)
{
IProperty* prop = reinterpret_cast<IProperty*>(TBase::GetItemData(hItem));
ATLASSERT(prop);
// Get paint rectangle
RECT rcItem;
_GetInplaceRect(hItem, &rcItem);
// Setup drawinfo
PROPERTYDRAWINFO di = m_di;
di.hDC = dc;
di.rcItem = rcItem;
di.state = 0;
if( !prop->IsEnabled() ) di.state |= ODS_DISABLED;
if( hItem == m_iInplaceIndex ) di.state |= ODS_COMBOBOXEDIT;
// A disabled TreeView control is painted grey in Windows2000
if( GetStyle() & WS_DISABLED ) {
di.clrText = di.clrDisabled;
di.clrBack = ::GetSysColor(COLOR_BTNFACE);
}
// Erase background
dc.FillSolidRect(&rcItem, di.clrBack);
// Draw border
bool bDrawBorder;
switch( prop->GetKind() ) {
case PROPKIND_SIMPLE:
case PROPKIND_CHECK:
bDrawBorder = false;
break;
default:
bDrawBorder = (iState & CDIS_SELECTED) != 0;
}
if( bDrawBorder ) {
RECT rcBorder = rcItem;
::OffsetRect(&rcBorder, -1, 0);
CBrush brBorder;
brBorder.CreateSolidBrush(di.clrBorder);
dc.FrameRect(&rcBorder, brBorder);
}
// Paint value
HFONT hOldFont = dc.SelectFont(di.TextFont);
prop->DrawValue(di);
dc.SelectFont(hOldFont);
}
};
class CPropertyTreeCtrl : public CPropertyTreeImpl<CPropertyTreeCtrl>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_PropertyTree"), GetWndClassName())
};
#endif // !defined(AFX_PROPERTYTREE_H__20020106_D62E_63DE_426B_0080AD509054__INCLUDED_)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -