// PropBrowseCtl.h : Property browser ActiveX Control // // This is a part of the Active Template Library. // Copyright (C) 1996-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Active Template Library Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Active Template Library product. #ifndef __PROPBROWSECTL_H_ #define __PROPBROWSECTL_H_ #include "resource.h" // main symbols #include "ATLControls.h" // Common control helpers using namespace ATLControls; class CProperty { public: DISPID m_dispid; VARTYPE m_vtNative; CComVariant m_value; CComPtr m_spDisp; CComPtr m_spInfo; CComBSTR m_bstrDesc; CProperty(IDispatch* pDisp, DISPID di, VARIANT val, BSTR bstrDesc, ITypeInfo* p = NULL) { m_dispid = di; m_value = val; m_bstrDesc = bstrDesc; m_vtNative = m_value.vt; m_spDisp = pDisp; m_spInfo = p; } bool IsCombo() { return ((m_spInfo != NULL) || (m_vtNative == VT_BOOL)); } HRESULT GetStringValue(BSTR* pbstr) { if (m_spInfo == NULL) { switch(m_vtNative) { case VT_BOOL: { CComBSTR bstr = (m_value.boolVal == VARIANT_TRUE) ? L"True" : L"False"; *pbstr = bstr.Detach(); } break; default: CComVariant v = m_value; v.ChangeType(VT_BSTR); *pbstr = v.bstrVal; v.bstrVal = NULL; break; } } else { USES_CONVERSION; TYPEATTR *pta=NULL; m_spInfo->GetTypeAttr(&pta); if(pta && pta->typekind == TKIND_ENUM) { VARDESC* pvd=NULL; for (int i=0;icVars;i++) { m_spInfo->GetVarDesc(i, &pvd); if (pvd->lpvarValue->lVal == m_value.lVal) { DISPID idMember = pvd->memid; CComBSTR bstrName; m_spInfo->GetDocumentation(idMember, &bstrName, NULL, NULL, NULL); TCHAR buf[256]; wsprintf(buf, _T("%d - %s"), pvd->lpvarValue->lVal, OLE2T(bstrName)); *pbstr = T2BSTR(buf); } m_spInfo->ReleaseVarDesc(pvd); } } if(pta) m_spInfo->ReleaseTypeAttr(pta); } return S_OK; } HRESULT SetValue(LPCTSTR pstr) { _ASSERTE(m_spInfo == NULL); switch(m_vtNative) { case VT_BOOL: m_value = (lstrcmpi(pstr, _T("True"))==0) ? true : false; break; default: m_value = pstr; m_value.ChangeType(m_vtNative); break; } CComDispatchDriver dd(m_spDisp); dd.PutProperty(m_dispid, &m_value); return S_OK; } HRESULT SetValue(int nIndex) { if (m_spInfo == NULL) { switch(m_vtNative) { case VT_BOOL: m_value = (nIndex == 0) ? true : false; break; default: break; } } else { VARDESC* pvd=NULL; m_spInfo->GetVarDesc(nIndex, &pvd); m_value = pvd->lpvarValue->lVal; m_spInfo->ReleaseVarDesc(pvd); } CComDispatchDriver dd(m_spDisp); dd.PutProperty(m_dispid, &m_value); return S_OK; } HRESULT AddEnumValues(HWND hwnd) { USES_CONVERSION; CComboBox cb = hwnd; cb.ResetContent(); if (m_vtNative == VT_BOOL) { cb.AddString(_T("True")); cb.AddString(_T("False")); cb.SetCurSel( (m_value.boolVal==VARIANT_TRUE) ? 0 : 1); } if (m_spInfo != NULL) { TYPEATTR *pta=NULL; m_spInfo->GetTypeAttr(&pta); if(pta && pta->typekind == TKIND_ENUM) { VARDESC* pvd=NULL; for (int i=0;icVars;i++) { m_spInfo->GetVarDesc(i, &pvd); DISPID idMember = pvd->memid; CComBSTR bstrName; m_spInfo->GetDocumentation(idMember, &bstrName, NULL, NULL, NULL); TCHAR buf[256]; wsprintf(buf, _T("%d - %s"), pvd->lpvarValue->lVal, OLE2T(bstrName)); cb.AddString(buf); if (pvd->lpvarValue->lVal == m_value.lVal) cb.SetCurSel(i); m_spInfo->ReleaseVarDesc(pvd); } } if(pta) m_spInfo->ReleaseTypeAttr(pta); } return S_OK; } }; ///////////////////////////////////////////////////////////////////////////// // CPropertyBrowseControl class ATL_NO_VTABLE CPropertyBrowseControl : public CComObjectRootEx, public IDispatchImpl, public CComControl > >, public IOleControlImpl, public IOleObjectImpl, public IOleInPlaceActiveObjectImpl, public IViewObjectExImpl, public IOleInPlaceObjectWindowlessImpl, public CComCoClass { public: CPropertyBrowseControl() { // Initialize control hosting support AtlAxWinInit(); m_bWindowOnly = true; m_bShowDesc = true; } DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW) BEGIN_COM_MAP(CPropertyBrowseControl) COM_INTERFACE_ENTRY(IATLConPropertyBrowser) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IViewObjectEx) COM_INTERFACE_ENTRY(IViewObject2) COM_INTERFACE_ENTRY(IViewObject) COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceObject) COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceActiveObject) COM_INTERFACE_ENTRY(IOleControl) COM_INTERFACE_ENTRY(IOleObject) END_COM_MAP() BEGIN_MSG_MAP(CPropertyBrowseControl) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) MESSAGE_HANDLER(WM_NOTIFY, OnNotify) MESSAGE_HANDLER(WM_SIZE, OnSize) DEFAULT_REFLECTION_HANDLER() ALT_MSG_MAP(1) //ListView MESSAGE_HANDLER(WM_DESTROY, OnListViewDestroy) COMMAND_HANDLER(103, CBN_KILLFOCUS, OnComboKillFocus) COMMAND_HANDLER(103, CBN_SELCHANGE, OnComboOK) ALT_MSG_MAP(2) //Edit control MESSAGE_HANDLER(WM_CHAR, OnChar) MESSAGE_HANDLER(WM_KILLFOCUS, OnEditKillFocus) ALT_MSG_MAP(3) //Combobox ALT_MSG_MAP(4) //Static control END_MSG_MAP() LRESULT OnEditKillFocus(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { RECT rc = {0,0,0,0}; m_edit.MoveWindow(&rc); bHandled = FALSE; return 1; } LRESULT OnComboKillFocus(int, int, HWND h, BOOL& bHandled) { RECT rc = {0,0,0,0}; m_combobox.MoveWindow(&rc); bHandled = FALSE; return 1; } void OnComboDone() { RECT rc = {0,0,0,0}; m_combobox.MoveWindow(&rc); CComBSTR bstrText; m_combobox.GetWindowText(bstrText.m_str); USES_CONVERSION; m_list.SetItemText(m_nItem, m_nSubItem, OLE2T(bstrText)); m_list.SetFocus(); CProperty* pProp = (CProperty*)m_list.GetItemData(m_nItem); pProp->SetValue(m_combobox.GetCurSel()); } LRESULT OnComboOK(int, int, HWND h, BOOL& bHandled) { OnComboDone(); return 1; } LRESULT OnSize(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { WORD cx = LOWORD(lParam); WORD cy = HIWORD(lParam); if (m_bShowDesc) cy -= m_nHeightDesc; m_list.MoveWindow(0, 0, cx, cy); m_wndDesc.MoveWindow(0, cy, cx, cy+m_nHeightDesc); return 999; } BOOL PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet) { if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: case VK_HOME: case VK_END: case VK_NEXT: case VK_PRIOR: hRet = S_FALSE; return TRUE; } } return FALSE; } LRESULT OnSetFocus(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { BOOL b; CComControlBase::OnSetFocus(0, 0, 0, b); DoVerbUIActivate(&m_rcPos, NULL); if(!IsChild(::GetFocus())) m_list.SetFocus(); return DefWindowProc(); } LRESULT OnListViewDestroy(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ClearListView(); bHandled = FALSE; return 1; } void ClearListView() { int n = m_list.GetItemCount(); for (int i=0;i spTypeInfo; VARTYPE vt = VT_USERDEFINED; HRESULT hr = E_FAIL; hr = pTI->GetRefTypeInfo(hrt, &spTypeInfo); if(FAILED(hr)) return vt; TYPEATTR *pta=NULL; spTypeInfo->GetTypeAttr(&pta); if(pta && pta->typekind == TKIND_ALIAS) { if (pta->tdescAlias.vt == VT_USERDEFINED) GetUserDefinedType(spTypeInfo,pta->tdescAlias.hreftype); else vt = pta->tdescAlias.vt; } if(pta) spTypeInfo->ReleaseTypeAttr(pta); return vt; } static HRESULT GetEnumTypeInfo(ITypeInfo *pTI, HREFTYPE hrt, ITypeInfo** ppEnumInfo) { CComPtr spTypeInfo; HRESULT hr = E_FAIL; hr = pTI->GetRefTypeInfo(hrt, &spTypeInfo); if(FAILED(hr)) return hr; TYPEATTR *pta=NULL; spTypeInfo->GetTypeAttr(&pta); if(pta != NULL) { if (pta->typekind == TKIND_ALIAS) { if (pta->tdescAlias.vt == VT_USERDEFINED) return GetEnumTypeInfo(spTypeInfo,pta->tdescAlias.hreftype, ppEnumInfo); } else if (pta->typekind == TKIND_ENUM) spTypeInfo.CopyTo(ppEnumInfo); spTypeInfo->ReleaseTypeAttr(pta); } return (*ppEnumInfo != NULL) ? S_OK : E_FAIL; } int m_nItem; int m_nSubItem; int m_nHeightDesc; bool m_bShowDesc; LRESULT OnNotify(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnChar(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled); HRESULT AddDispatch(IDispatch* pDisp); // IViewObjectEx DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE) // IPropertyBrowseControl public: STDMETHOD(put_Dispatch)(IDispatch* pDisp); STDMETHOD(get_Dispatch)(IDispatch** ppDisp); STDMETHOD(get_ShowDescription)(/*[out, retval]*/ BOOL *pVal); STDMETHOD(put_ShowDescription)(/*[in]*/ BOOL newVal); CComPtr m_spDispatch; CContainedWindowT > m_list; CContainedWindowT > m_edit; CContainedWindowT > m_combobox; CContainedWindowT > m_wndDesc; LRESULT OnCreate(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled); }; #endif //__PROPBROWSECTL_H_