// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #ifdef AFXCTL_PAGE_SEG #pragma code_seg(AFXCTL_PAGE_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// // CStockPropPage implementation BEGIN_MESSAGE_MAP(CStockPropPage, COlePropertyPage) END_MESSAGE_MAP() void _AfxSizeComboToContent(CComboBox* pCombo) { ASSERT_VALID(pCombo); int cyEdit = (int)(pCombo->SendMessage(CB_GETITEMHEIGHT, (WPARAM)-1, 0L)); int cyItem = (int)(pCombo->SendMessage(CB_GETITEMHEIGHT, (WPARAM)0, 0L)); CRect rcCombo; pCombo->GetWindowRect(&rcCombo); pCombo->SetWindowPos(NULL, 0, 0, rcCombo.Width(), cyEdit + pCombo->GetCount() * cyItem + GetSystemMetrics(SM_CYBORDER) * 8, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); } CStockPropPage::CStockPropPage(UINT idDlg, UINT idCaption) : COlePropertyPage(idDlg, idCaption) { m_lcid = 0; } void CStockPropPage::FillPropnameList(REFGUID guid, int nIndirect, CComboBox& combo) { USES_CONVERSION; combo.ResetContent(); UINT cProps = 0; ULONG nObjects; LPDISPATCH* ppDisp = GetObjectArray(&nObjects); if (ppDisp != NULL) { LPTYPEINFO pTypeInfo; LPTYPEATTR pTypeAttr; LPVARDESC pVarDesc; ULONG iObj; WORD iProp; BSTR rgbstr[1]; UINT cName; // Get the property sheet locale LPPROPERTYPAGESITE pPageSite; if ((pPageSite = GetPageSite()) != NULL) if (FAILED(pPageSite->GetLocaleID(&m_lcid))) m_lcid = 0; // Iterate through all objects. for (iObj = 0; iObj < nObjects; iObj++) { pTypeInfo = NULL; if ((ppDisp[iObj] != NULL) && SUCCEEDED(ppDisp[iObj]->GetTypeInfo(0, m_lcid, &pTypeInfo))) { ASSERT(pTypeInfo != NULL); pTypeAttr = NULL; if (SUCCEEDED(pTypeInfo->GetTypeAttr(&pTypeAttr))) { ASSERT(pTypeAttr != NULL); // Iterate through all properties of object. for (iProp = 0; iProp < pTypeAttr->cVars; iProp++) { pVarDesc = NULL; if (SUCCEEDED(pTypeInfo->GetVarDesc(iProp, &pVarDesc))) { // Check whether property has desired type if (!(pVarDesc->wVarFlags & VARFLAG_FHIDDEN) && AfxOleTypeMatchGuid(pTypeInfo, &pVarDesc->elemdescVar.tdesc, guid, nIndirect)) { // Get property name and insert into list. if (SUCCEEDED(pTypeInfo->GetNames( pVarDesc->memid, rgbstr, 1, &cName))) { // Don't insert duplicates. LPCTSTR lpstr = OLE2CT(rgbstr[0]); if (combo.FindString(-1, lpstr) == CB_ERR) { int iItem = combo.AddString(lpstr); if (iItem >= 0) { combo.SetItemData(iItem, (DWORD)pVarDesc->memid); ++cProps; } } SysFreeString(rgbstr[0]); } } pTypeInfo->ReleaseVarDesc(pVarDesc); } } pTypeInfo->ReleaseTypeAttr(pTypeAttr); } pTypeInfo->Release(); } } } // Select the first one m_iPropName = 0; // Prevents save from happening if (combo.SetCurSel(0) != CB_ERR) combo.GetLBText(0, m_strPropName); // Disable or set the size of the combo, as appropriate if (cProps <= 1) combo.EnableWindow(FALSE); else _AfxSizeComboToContent(&combo); UpdateData(FALSE); SetModifiedFlag(FALSE); } void CStockPropPage::OnSelchangePropname(CComboBox& combo) { int iPropNameNew = combo.GetCurSel(); if (iPropNameNew != m_iPropName) { UpdateData(TRUE); if (iPropNameNew != CB_ERR) combo.GetLBText(iPropNameNew, m_strPropName); else m_strPropName = _T(""); m_iPropName = iPropNameNew; UpdateData(FALSE); SetModifiedFlag(FALSE); } } BOOL CStockPropPage::OnEditProperty(DISPID dispid, CComboBox& combo) { int cItems = combo.GetCount(); int i; for (i = 0; i < cItems; i++) { if ((DISPID)(combo.GetItemData(i)) == dispid) { combo.SetCurSel(i); OnSelchangePropname(combo); return TRUE; } } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // AfxOleTypeMatchGuid: Tests whether a given TYPEDESC matches a type with a // given GUID, when all aliases have been expanded. BOOL AFXAPI AfxOleTypeMatchGuid( LPTYPEINFO pTypeInfo, TYPEDESC* pTypeDesc, REFGUID guidType, ULONG cIndirectionLevels) { ASSERT(pTypeInfo != NULL); ASSERT(pTypeDesc != NULL); ASSERT(cIndirectionLevels >= 0); LPTYPEINFO pTypeInfoRef = NULL; BOOL bMatch = FALSE; switch (pTypeDesc->vt) { case VT_USERDEFINED: // It's an alias: Expand the alias and try to match. if (SUCCEEDED(pTypeInfo->GetRefTypeInfo( pTypeDesc->hreftype, &pTypeInfoRef))) { ASSERT(pTypeInfoRef != NULL); LPTYPEATTR pTypeAttr = NULL; if (SUCCEEDED(pTypeInfoRef->GetTypeAttr(&pTypeAttr))) { ASSERT(pTypeAttr != NULL); // If we've dereferenced the correct number of times, // test the GUIDs for equality. if (cIndirectionLevels == 0) bMatch = IsEqualGUID(pTypeAttr->guid, guidType); if (!bMatch && pTypeAttr->typekind == TKIND_ALIAS) { // GUIDs didn't match, but type expanded to another alias! bMatch = AfxOleTypeMatchGuid(pTypeInfoRef, &pTypeAttr->tdescAlias, guidType, cIndirectionLevels); } pTypeInfoRef->ReleaseTypeAttr(pTypeAttr); } pTypeInfoRef->Release(); } break; case VT_PTR: // It's a pointer: Dereference and try to match with one less level // of indirection. ASSERT(pTypeDesc->lptdesc != NULL); bMatch = AfxOleTypeMatchGuid(pTypeInfo, pTypeDesc->lptdesc, guidType, cIndirectionLevels - 1); break; } return bMatch; } ///////////////////////////////////////////////////////////////////////////// // Force any extra compiler-generated code into AFX_INIT_SEG #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif IMPLEMENT_DYNAMIC(CStockPropPage, COlePropertyPage)