?? propertyitemimpl.h
字號:
#ifndef __PROPERTYITEMIMPL__H
#define __PROPERTYITEMIMPL__H
#pragma once
/////////////////////////////////////////////////////////////////////////////
// CPropertyItemImpl - Property implementations for the Property controls
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2001-2002 Bjarke Viksoe.
//
// 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 __PROPERTYITEM__H
#error PropertyItemImpl.h requires PropertyItem.h to be included first
#endif
#ifndef __PROPERTYITEMEDITORS__H
#error PropertyItemImpl.h requires PropertyItemEditors.h to be included first
#endif
#ifndef __ATLBASE_H__
#error PropertyItem.h requires atlbase.h to be included first
#endif
/////////////////////////////////////////////////////////////////////////////
// Base CProperty class
class CProperty : public IProperty
{
protected:
HWND m_hWndOwner;
LPTSTR m_pszName;
bool m_fEnabled;
LPARAM m_lParam;
public:
CProperty(LPCTSTR pstrName, LPARAM lParam) : m_fEnabled(true), m_lParam(lParam), m_hWndOwner(NULL)
{
ATLASSERT(!::IsBadStringPtr(pstrName,-1));
ATLTRY(m_pszName = new TCHAR[ (::lstrlen(pstrName) * sizeof(TCHAR)) + 1 ]);
ATLASSERT(m_pszName);
::lstrcpy(m_pszName, pstrName);
}
virtual ~CProperty()
{
delete [] m_pszName;
}
virtual void SetOwner(HWND hWnd, LPVOID /*pData*/)
{
ATLASSERT(::IsWindow(hWnd));
ATLASSERT(m_hWndOwner==NULL); // Cannot set it twice
m_hWndOwner = hWnd;
}
virtual LPCTSTR GetName() const
{
return m_pszName; // Dangerous!
}
virtual void SetEnabled(BOOL bEnable)
{
m_fEnabled = bEnable == TRUE;
}
virtual BOOL IsEnabled() const
{
return m_fEnabled;
}
virtual void SetItemData(LPARAM lParam)
{
m_lParam = lParam;
}
virtual LPARAM GetItemData() const
{
return m_lParam;
}
virtual void DrawName(PROPERTYDRAWINFO& di)
{
CDCHandle dc(di.hDC);
COLORREF clrBack, clrFront;
if( di.state & ODS_DISABLED ) {
clrFront = di.clrDisabled;
clrBack = di.clrBack;
}
else if( di.state & ODS_SELECTED ) {
clrFront = di.clrSelText;
clrBack = di.clrSelBack;
}
else {
clrFront = di.clrText;
clrBack = di.clrBack;
}
RECT rcItem = di.rcItem;
dc.FillSolidRect(&rcItem, clrBack);
rcItem.left += 2; // Indent text
dc.SetBkMode(TRANSPARENT);
dc.SetBkColor(clrBack);
dc.SetTextColor(clrFront);
dc.DrawText(m_pszName, -1, &rcItem, DT_LEFT | DT_SINGLELINE | DT_EDITCONTROL | DT_NOPREFIX | DT_VCENTER);
}
virtual void DrawValue(PROPERTYDRAWINFO& /*di*/)
{
}
virtual HWND CreateInplaceControl(HWND /*hWnd*/, const RECT& /*rc*/)
{
return NULL;
}
virtual BOOL Activate(UINT /*action*/, LPARAM /*lParam*/)
{
return TRUE;
}
virtual BOOL GetDisplayValue(LPTSTR /*pstr*/, UINT /*cchMax*/) const
{
return FALSE;
}
virtual UINT GetDisplayValueLength() const
{
return 0;
}
virtual BOOL GetValue(VARIANT* /*pValue*/) const
{
return FALSE;
}
virtual BOOL SetValue(const VARIANT& /*value*/)
{
ATLASSERT(false);
return FALSE;
}
virtual BOOL SetValue(HWND /*hWnd*/)
{
ATLASSERT(false);
return FALSE;
}
};
/////////////////////////////////////////////////////////////////////////////
// Simple property (displays text)
class CPropertyItem : public CProperty
{
protected:
CComVariant m_val;
public:
CPropertyItem(LPCTSTR pstrName, LPARAM lParam) : CProperty(pstrName, lParam)
{
}
BYTE GetKind() const
{
return PROPKIND_SIMPLE;
}
void DrawValue(PROPERTYDRAWINFO& di)
{
UINT cchMax = GetDisplayValueLength() + 1;
LPTSTR pszText = (LPTSTR) _alloca(cchMax * sizeof(TCHAR));
ATLASSERT(pszText);
if( !GetDisplayValue(pszText, cchMax) ) return;
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(pszText, -1,
&rcText,
DT_LEFT | DT_SINGLELINE | DT_EDITCONTROL | DT_NOPREFIX | DT_END_ELLIPSIS | DT_VCENTER);
}
BOOL GetDisplayValue(LPTSTR pstr, UINT cchMax) const
{
ATLASSERT(!::IsBadStringPtr(pstr, cchMax));
// Convert VARIANT to string and use that as display string...
CComVariant v;
if( FAILED( v.ChangeType(VT_BSTR, &m_val) ) ) return FALSE;
USES_CONVERSION;
::lstrcpyn(pstr, OLE2CT(v.bstrVal), cchMax);
return TRUE;
}
UINT GetDisplayValueLength() const
{
// Hmm, need to convert it to display string first and
// then take the length...
// TODO: Call GetDisplayValue() instead...
CComVariant v;
if( FAILED( v.ChangeType(VT_BSTR, &m_val) ) ) return 0;
return v.bstrVal == NULL ? 0 : ::lstrlenW(v.bstrVal);
}
BOOL GetValue(VARIANT* pVal) const
{
return SUCCEEDED( CComVariant(m_val).Detach(pVal) );
}
BOOL SetValue(const VARIANT& value)
{
m_val = value;
return TRUE;
}
};
/////////////////////////////////////////////////////////////////////////////
// ReadOnly property (enhanced display feature)
class CPropertyReadOnlyItem : public CPropertyItem
{
protected:
UINT m_uStyle;
HICON m_hIcon;
COLORREF m_clrBack;
COLORREF m_clrText;
public:
CPropertyReadOnlyItem(LPCTSTR pstrName, LPARAM lParam) :
CPropertyItem(pstrName, lParam),
m_uStyle( DT_LEFT | DT_SINGLELINE | DT_EDITCONTROL | DT_NOPREFIX | DT_END_ELLIPSIS | DT_VCENTER ),
m_clrBack( (COLORREF) -1 ),
m_clrText( (COLORREF) -1 ),
m_hIcon(NULL)
{
}
void DrawValue(PROPERTYDRAWINFO& di)
{
// Get property text
UINT cchMax = GetDisplayValueLength() + 1;
LPTSTR pszText = (LPTSTR) _alloca(cchMax * sizeof(TCHAR));
ATLASSERT(pszText);
if( !GetDisplayValue(pszText, cchMax) ) return;
// Prepare paint
RECT rcText = di.rcItem;
CDCHandle dc(di.hDC);
dc.SetBkMode(OPAQUE);
// Set background color
COLORREF clrBack = di.clrBack;
if( m_clrBack != (COLORREF) -1 ) clrBack = m_clrBack;
dc.SetBkColor(clrBack);
// Set text color
COLORREF clrText = di.clrText;
if( m_clrText != (COLORREF) -1 ) clrText = m_clrText;
if( di.state & ODS_DISABLED ) clrText = di.clrDisabled;
dc.SetTextColor(clrText);
// Draw icon if available
if( m_hIcon ) {
POINT pt = { rcText.left + 2, rcText.top + 2 };
SIZE sz = { ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON) };
::DrawIconEx(dc, pt.x, pt.y, m_hIcon, sz.cx, sz.cy, 0, NULL, DI_NORMAL);
rcText.left += sz.cx + 4;
}
// Draw text with custom style
rcText.left += PROP_TEXT_INDENT;
dc.DrawText(pszText, -1,
&rcText,
m_uStyle);
}
// Operations
// NOTE: To use these methods, you must cast the HPROPERTY
// handle back to the CPropertyReadOnlyItem class.
// Nasty stuff, but so far I've settled with this approach.
COLORREF SetBkColor(COLORREF clrBack)
{
COLORREF clrOld = m_clrBack;
m_clrBack = clrBack;
return clrOld;
}
COLORREF SetTextColor(COLORREF clrText)
{
COLORREF clrOld = m_clrText;
m_clrText = clrText;
return clrOld;
}
HICON SetIcon(HICON hIcon)
{
HICON hOldIcon = m_hIcon;
m_hIcon = hIcon;
return hOldIcon;
}
void ModifyDrawStyle(UINT uRemove, UINT uAdd)
{
m_uStyle = (m_uStyle & ~uRemove) | uAdd;
}
};
/////////////////////////////////////////////////////////////////////////////
// Simple Value property
class CPropertyEditItem : public CPropertyItem
{
protected:
HWND m_hwndEdit;
public:
CPropertyEditItem(LPCTSTR pstrName, LPARAM lParam) :
CPropertyItem(pstrName, lParam),
m_hwndEdit(NULL)
{
}
BYTE GetKind() const
{
return PROPKIND_EDIT;
}
HWND CreateInplaceControl(HWND hWnd, const RECT& rc)
{
// Get default text
UINT cchMax = GetDisplayValueLength() + 1;
LPTSTR pszText = (LPTSTR) _alloca(cchMax * sizeof(TCHAR));
ATLASSERT(pszText);
if( !GetDisplayValue(pszText, cchMax) ) return NULL;
// Create EDIT control
CPropertyEditWindow* win = new CPropertyEditWindow();
ATLASSERT(win);
RECT rcWin = rc;
m_hwndEdit = win->Create(hWnd, rcWin, pszText, WS_VISIBLE | WS_CHILD | ES_LEFT | ES_AUTOHSCROLL);
win->SetWindowText(pszText);
ATLASSERT(::IsWindow(m_hwndEdit));
// Simple hack to validate numbers
switch( m_val.vt ) {
case VT_UI1:
case VT_UI2:
case VT_UI4:
win->ModifyStyle(0, ES_NUMBER);
}
return m_hwndEdit;
}
BOOL SetValue(const VARIANT& value)
{
if( m_val.vt == VT_EMPTY ) m_val = value;
return SUCCEEDED( m_val.ChangeType(m_val.vt, &value) );
}
BOOL SetValue(HWND hWnd)
{
ATLASSERT(::IsWindow(hWnd));
int len = ::GetWindowTextLength(hWnd) + 1;
LPTSTR pstr = (LPTSTR) _alloca(len * sizeof(TCHAR));
ATLASSERT(pstr);
if( ::GetWindowText(hWnd, pstr, len) == 0 ) {
// Bah, an empty string AND an error causes the same return code!
if( ::GetLastError() != 0 ) return FALSE;
}
CComVariant v = pstr;
return SetValue(v);
}
BOOL Activate(UINT action, LPARAM /*lParam*/)
{
switch( action ) {
case PACT_TAB:
case PACT_SPACE:
case PACT_DBLCLICK:
if( ::IsWindow(m_hwndEdit) ) {
::SetFocus(m_hwndEdit);
::SendMessage(m_hwndEdit, EM_SETSEL, 0, -1);
}
break;
}
return TRUE;
}
};
/////////////////////////////////////////////////////////////////////////////
// Simple Value property
class CPropertyDateItem : public CPropertyEditItem
{
public:
CPropertyDateItem(LPCTSTR pstrName, LPARAM lParam) :
CPropertyEditItem(pstrName, lParam)
{
}
HWND CreateInplaceControl(HWND hWnd, const RECT& rc)
{
// Get default text
UINT cchMax = GetDisplayValueLength() + 1;
LPTSTR pszText = (LPTSTR) _alloca(cchMax * sizeof(TCHAR));
ATLASSERT(pszText);
if( !GetDisplayValue(pszText, cchMax) ) return NULL;
// Create window
CPropertyDateWindow* win = new CPropertyDateWindow();
ATLASSERT(win);
RECT rcWin = rc;
m_hwndEdit = win->Create(hWnd, rcWin, pszText);
ATLASSERT(win->IsWindow());
return *win;
}
BOOL GetDisplayValue(LPTSTR pstr, UINT cchMax) const
{
if( m_val.date == 0.0 ) {
::lstrcpy(pstr, _T(""));
return TRUE;
}
return CPropertyEditItem::GetDisplayValue(pstr, cchMax);
}
BOOL SetValue(const VARIANT& value)
{
if( value.vt == VT_BSTR && ::SysStringLen(value.bstrVal) == 0 ) {
m_val.date = 0.0;
return TRUE;
}
return CPropertyEditItem::SetValue(value);
}
BOOL SetValue(HWND hWnd)
{
if( ::GetWindowTextLength(hWnd) == 0 ) {
m_val.date = 0.0;
return TRUE;
}
return CPropertyEditItem::SetValue(hWnd);
}
};
/////////////////////////////////////////////////////////////////////////////
// Checkmark button
class CPropertyCheckButtonItem : public CProperty
{
protected:
bool m_bValue;
public:
CPropertyCheckButtonItem(LPCTSTR pstrName, bool bValue, LPARAM lParam) :
CProperty(pstrName, lParam),
m_bValue(bValue)
{
}
BYTE GetKind() const
{
return PROPKIND_CHECK;
}
BOOL GetValue(VARIANT* pVal) const
{
return SUCCEEDED( CComVariant(m_bValue).Detach(pVal) );
}
BOOL SetValue(const VARIANT& value)
{
// Set a new value
switch( value.vt ) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -