home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / atl / atlcon / propbrowsectl.cpp < prev    next >
C/C++ Source or Header  |  1998-04-03  |  8KB  |  278 lines

  1. // PropBrowseCtl.cpp : Implementation of a property browser control
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12.  
  13. #include "stdafx.h"
  14. #include "ATLCon.h"
  15. #include "PropBrowseCtl.h"
  16.  
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CPropertyBrowseControl
  19. #include <exdisp.h>
  20.  
  21. LRESULT CPropertyBrowseControl::OnCreate(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  22. {
  23.     DefWindowProc();
  24.     RECT rc;
  25.     GetClientRect(&rc);
  26.     m_list.Create(this, 1, m_hWnd, &rc, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 101);
  27.     m_list.SetExtendedListViewStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
  28.     HFONT hFont = m_list.GetFont();
  29.     m_list.AddColumn(_T("Name"), 0);
  30.     m_list.AddColumn(_T("Value"), 1);
  31.  
  32.     TEXTMETRIC tm;
  33.     HDC hdc = ::GetDC(NULL);
  34.     HFONT hOldFont = (HFONT)::SelectObject(hdc, hFont);
  35.     ::GetTextMetrics(hdc, &tm);
  36.     ::SelectObject(hdc, hOldFont);
  37.     ::ReleaseDC(NULL, hdc);
  38.     m_nHeightDesc = (tm.tmHeight+tm.tmExternalLeading)*3; //room for three lines of text
  39.  
  40.     rc.bottom -= m_nHeightDesc;
  41.     m_list.MoveWindow(&rc);
  42.  
  43.     RECT rc2 = {0,0,0,0};
  44.     m_edit.Create(this, 2, m_list, &rc2);
  45.     m_edit.SetFont(hFont);
  46.     // combobox has ID of 103
  47.     m_combobox.Create(this, 3, m_list, &rc2, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 103);
  48.     m_combobox.SetFont(hFont);
  49.  
  50.     rc.top = rc.bottom;
  51.     rc.bottom += m_nHeightDesc;
  52.     m_wndDesc.Create(this, 4, m_hWnd, &rc2, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 104);
  53.     m_wndDesc.SetFont(hFont);
  54.     return 0;
  55. }
  56.  
  57. LRESULT CPropertyBrowseControl::OnNotify(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  58. {
  59.     USES_CONVERSION;
  60.     NMLISTVIEW* pnmlv = (NMLISTVIEW*) lParam;
  61.     if (pnmlv->hdr.code == LVN_ITEMCHANGED)
  62.     {
  63.         NMLISTVIEW* pnmlv = (NMLISTVIEW*) lParam;
  64.         if (pnmlv->uNewState & LVIS_FOCUSED)
  65.         {
  66.             CProperty* pProp = (CProperty*)m_list.GetItemData(pnmlv->iItem);
  67.             LPCTSTR lpszDesc = (pProp == NULL) ? _T("") : OLE2T(pProp->m_bstrDesc);
  68.             m_wndDesc.SetWindowText(lpszDesc);
  69.         }
  70.     }
  71.  
  72.     if (pnmlv->hdr.code == NM_RETURN)
  73.     {
  74.         pnmlv->hdr.code = NM_DBLCLK;
  75.         pnmlv->iItem = m_list.GetSelectedIndex();
  76.         pnmlv->iSubItem = 1;
  77.     }
  78.     if ((pnmlv->hdr.code == NM_DBLCLK) || (pnmlv->hdr.code == NM_CLICK))
  79.     {
  80.         if (pnmlv->iSubItem == 1)
  81.         {
  82.             RECT rc;
  83.             m_nItem = pnmlv->iItem;
  84.             m_nSubItem = pnmlv->iSubItem;
  85.             CComBSTR bstrText;
  86.             m_list.GetItemText(m_nItem, m_nSubItem, bstrText.m_str);
  87.             m_list.GetSubItemRect(m_nItem, m_nSubItem, 0, &rc);
  88.             LPCTSTR lpszText = OLE2T(bstrText);
  89.             CProperty* pProp = (CProperty*)m_list.GetItemData(pnmlv->iItem);
  90.             if (pProp != NULL)
  91.             {
  92.                 if (!pProp->IsCombo()) // use edit control if not an enum
  93.                 {
  94.                     m_edit.SetWindowText(lpszText ? lpszText : _T(""));
  95.                     rc.top -= 2;
  96.                     rc.bottom -= 2;
  97.                     m_edit.MoveWindow(&rc);
  98.                     m_edit.SetFocus();
  99.                 }
  100.                 else
  101.                 {
  102.                     pProp->AddEnumValues(m_combobox);
  103.     //              m_combobox.SetWindowText(lpszText ? lpszText : _T(""));
  104.                     int nHeight = m_combobox.GetItemHeight(-1);
  105.                     int nOffset = (nHeight-(rc.bottom-rc.top))/2 + 2;
  106.                     rc.bottom -= nOffset;
  107.                     rc.top -= nOffset;
  108.                     rc.bottom += 100;
  109.                     m_combobox.MoveWindow(&rc);
  110.                     m_combobox.SetFocus();
  111.                 }
  112.             }
  113.         }
  114.         else
  115.         {
  116.             RECT rc = {0,0,0,0};
  117.             m_combobox.MoveWindow(&rc);
  118.             m_edit.MoveWindow(&rc);
  119.         }
  120.     }
  121.     return 0;
  122. }
  123.  
  124. LRESULT CPropertyBrowseControl::OnChar(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  125. {
  126.     TCHAR ch = (TCHAR) wParam;
  127.     if (ch == VK_RETURN)
  128.     {
  129.         USES_CONVERSION;
  130.         RECT rc = {0,0,0,0};
  131.         m_edit.MoveWindow(&rc);
  132.         CComBSTR bstrText;
  133.         m_edit.GetWindowText(bstrText.m_str);
  134.         m_list.SetItemText(m_nItem, m_nSubItem, OLE2T(bstrText));
  135.         m_list.SetFocus();
  136.         CProperty* pProp = (CProperty*)m_list.GetItemData(m_nItem);
  137.         pProp->SetValue(OLE2T(bstrText));
  138.         return 0;
  139.     }
  140.     return m_edit.DefWindowProc();
  141. }
  142.  
  143. HRESULT CPropertyBrowseControl::AddDispatch(IDispatch* pDisp)
  144. {
  145.     USES_CONVERSION;
  146.     CComPtr<ITypeInfo> spTypeInfo;
  147.     if (pDisp == NULL)
  148.         return S_OK;
  149.     pDisp->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &spTypeInfo);
  150.  
  151.     if (spTypeInfo == NULL)
  152.         return E_FAIL;
  153.  
  154.     TYPEATTR* pta;
  155.     spTypeInfo->GetTypeAttr(&pta);
  156.  
  157.     if (pta->typekind == TKIND_INTERFACE)
  158.     {
  159.         // Get the dual
  160.         CComPtr<ITypeInfo> spInfoTemp;
  161.         HREFTYPE hRef;
  162.         HRESULT hr = spTypeInfo->GetRefTypeOfImplType(-1, &hRef);
  163.         if (FAILED(hr))
  164.             return E_FAIL;
  165.  
  166.         hr = spTypeInfo->GetRefTypeInfo(hRef, &spInfoTemp);
  167.         if (FAILED(hr))
  168.             return E_FAIL;
  169.  
  170.         spTypeInfo->ReleaseTypeAttr(pta);
  171.         spTypeInfo = spInfoTemp;
  172.         spTypeInfo->GetTypeAttr(&pta);
  173.     }
  174.  
  175.  
  176.     int item = m_list.GetItemCount();
  177.     for (int i=0; i<pta->cFuncs; i++)
  178.     {
  179.         FUNCDESC* pfd;
  180.         spTypeInfo->GetFuncDesc(i, &pfd);
  181.         if (pfd->invkind & DISPATCH_PROPERTYGET
  182.             && (pfd->wFuncFlags & (FUNCFLAG_FRESTRICTED | FUNCFLAG_FHIDDEN)) == 0)
  183.         {
  184.             switch (pfd->elemdescFunc.tdesc.vt)
  185.             {
  186.             case VT_USERDEFINED:
  187.             case VT_EMPTY:
  188.             case VT_NULL:
  189.             case VT_I2:
  190.             case VT_I4:
  191.             case VT_R4:
  192.             case VT_R8:
  193.             case VT_CY:
  194.             case VT_DATE:
  195.             case VT_BSTR:
  196.             case VT_ERROR:
  197.             case VT_BOOL:
  198.             case VT_VARIANT:
  199.             case VT_DECIMAL:
  200.             case VT_I1:
  201.             case VT_UI1:
  202.             case VT_UI2:
  203.             case VT_UI4:
  204.             case VT_INT:
  205.             case VT_UINT:
  206.                 {
  207.                     CComPtr<ITypeInfo> spUserTypeInfo;
  208.                     if (pfd->elemdescFunc.tdesc.vt == VT_USERDEFINED)
  209.                     {
  210.                         HREFTYPE hrt = pfd->elemdescFunc.tdesc.hreftype;
  211.                         VARTYPE vt = VT_USERDEFINED;
  212.                         HRESULT hr = E_FAIL;
  213.                         hr = GetEnumTypeInfo(spTypeInfo, hrt, &spUserTypeInfo);
  214.                         if(FAILED(hr))
  215.                             vt = GetUserDefinedType(spTypeInfo, hrt);
  216.                     }
  217.                     USES_CONVERSION;
  218.                     CComVariant varVal;
  219.                     CComBSTR bstrVal;
  220.                     CComBSTR bstrName;
  221.                     CComBSTR bstrDocString;
  222.                     spTypeInfo->GetDocumentation(pfd->memid, &bstrName, &bstrDocString, NULL, NULL);
  223.                     CComDispatchDriver dd(pDisp);
  224.                     dd.GetProperty(pfd->memid, &varVal);
  225.                     CProperty* pProp = new CProperty(pDisp, pfd->memid, varVal, bstrDocString, spUserTypeInfo);
  226.                     pProp->GetStringValue(&bstrVal);
  227.                     m_list.AddItem(item, 0, OLE2T(bstrName));
  228.                     m_list.AddItem(item, 1, OLE2T(bstrVal));
  229.                     m_list.SetItemData(item, reinterpret_cast<DWORD>(pProp));
  230.                     item++;
  231.                 }
  232.             }
  233.         }
  234.         spTypeInfo->ReleaseFuncDesc(pfd);
  235.     }
  236.     spTypeInfo->ReleaseTypeAttr(pta);
  237.     return S_OK;
  238. }
  239.  
  240. STDMETHODIMP CPropertyBrowseControl::put_Dispatch(IDispatch* pDisp)
  241. {
  242.     USES_CONVERSION;
  243.     ClearListView();
  244.  
  245.     m_spDispatch = pDisp;
  246.     if (pDisp != NULL)
  247.     {
  248.         m_list.SetRedraw(FALSE);
  249.         AddDispatch(pDisp);
  250.         m_list.SetRedraw(TRUE);
  251.         m_list.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
  252.         m_list.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
  253.     }
  254.     return S_OK;
  255. }
  256.  
  257. STDMETHODIMP CPropertyBrowseControl::get_Dispatch(IDispatch** ppDisp)
  258. {
  259.     return m_spDispatch.CopyTo(ppDisp);
  260. }
  261.  
  262. STDMETHODIMP CPropertyBrowseControl::get_ShowDescription(BOOL *pVal)
  263. {
  264.     *pVal = m_bShowDesc ? VARIANT_TRUE : VARIANT_FALSE;
  265.     return S_OK;
  266. }
  267.  
  268. STDMETHODIMP CPropertyBrowseControl::put_ShowDescription(BOOL newVal)
  269. {
  270.     m_bShowDesc = (newVal == VARIANT_TRUE);
  271.     RECT rc;
  272.     GetWindowRect(&rc);
  273.     if (m_bShowDesc)
  274.         rc.bottom -= m_nHeightDesc;
  275.     m_list.MoveWindow(&rc);
  276.     return S_OK;
  277. }
  278.