//------------------------------------------------------------------------------ // File: MapperDlg.cpp // // Desc: DirectShow sample code - an MFC based C++ filter mapper application. // // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // MapperDlg.cpp : implementation file // #include "stdafx.h" #include "Mapper.h" #include "MapperDlg.h" #include "types.h" #include "wxdebug.h" #include "fil_data.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // ID for unpublished filter data helper method const IID IID_IAMFilterData = {0x97f7c4d4,0x547b,0x4a5f,{0x83,0x32,0x53,0x64,0x30,0xad,0x2e,0x4d}}; ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMapperDlg dialog CMapperDlg::CMapperDlg(CWnd* pParent /*=NULL*/) : CDialog(CMapperDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMapperDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMapperDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMapperDlg) DDX_Control(pDX, IDC_BUTTON_SEARCH, m_bSearch); DDX_Control(pDX, IDC_BUTTON_CLEAR, m_bClear); DDX_Control(pDX, IDC_STATIC_NUMFILTERS, m_StrNumFilters); DDX_Control(pDX, IDC_CHECK_RENDERER, m_bIsRenderer); DDX_Control(pDX, IDC_CHECK_OUTPUT_PIN, m_bAtLeastOneOutputPin); DDX_Control(pDX, IDC_CHECK_INPUT_PIN, m_bAtLeastOneInputPin); DDX_Control(pDX, IDC_CHECK_EXACT_MATCH, m_bExactMatch); DDX_Control(pDX, IDC_LIST_OUTPUT_MINOR2, m_ListOutputMinor2); DDX_Control(pDX, IDC_LIST_OUTPUT_MINOR, m_ListOutputMinor); DDX_Control(pDX, IDC_LIST_OUTPUT_MAJOR2, m_ListOutputMajor2); DDX_Control(pDX, IDC_LIST_OUTPUT_MAJOR, m_ListOutputMajor); DDX_Control(pDX, IDC_LIST_INPUT_MINOR2, m_ListInputMinor2); DDX_Control(pDX, IDC_LIST_INPUT_MINOR, m_ListInputMinor); DDX_Control(pDX, IDC_LIST_INPUT_MAJOR2, m_ListInputMajor2); DDX_Control(pDX, IDC_LIST_INPUT_MAJOR, m_ListInputMajor); DDX_Control(pDX, IDC_COMBO_MERIT, m_ComboMerit); DDX_Control(pDX, IDC_COMBO_OUTPUT_CATEGORY, m_ComboOutputCat); DDX_Control(pDX, IDC_COMBO_INPUT_CATEGORY, m_ComboInputCat); DDX_Control(pDX, IDC_LIST_FILTERS, m_ListFilters); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CMapperDlg, CDialog) //{{AFX_MSG_MAP(CMapperDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_CLOSE() ON_WM_DESTROY() ON_BN_CLICKED(IDC_BUTTON_SEARCH, OnButtonSearch) ON_LBN_SELCHANGE(IDC_LIST_INPUT_MAJOR, OnSelchangeListInputMajor) ON_LBN_SELCHANGE(IDC_LIST_OUTPUT_MAJOR, OnSelchangeListOutputMajor) ON_LBN_SELCHANGE(IDC_LIST_INPUT_MAJOR2, OnSelchangeListInputMajor2) ON_LBN_SELCHANGE(IDC_LIST_OUTPUT_MAJOR2, OnSelchangeListOutputMajor2) ON_BN_CLICKED(IDC_BUTTON_CLEAR, OnButtonClear) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMapperDlg message handlers void CMapperDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMapperDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMapperDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } BOOL CMapperDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon ////////////////////////////////////////////////////////////////////////// // // DirectShow initialization code CoInitialize(NULL); // Create the filter mapper that will be used for all queries HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC, IID_IFilterMapper2, (void **) &m_pMapper); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return FALSE; // Initialize some application settings InitializeTooltips(); SetDefaults(); // Customize list box tab stops for good formatting int nTabStops[2]={140,230}; m_ListFilters.SetTabStops(2, nTabStops); return TRUE; // return TRUE unless you set the focus to a control } BOOL CMapperDlg::InitializeTooltips() { int rc; // Create the tooltip control m_pToolTip = new CToolTipCtrl; if(!m_pToolTip->Create(this)) { TRACE(TEXT("Unable To create ToolTip\n")); return FALSE; } // Set some tooltip defaults m_pToolTip->SetMaxTipWidth(250); m_pToolTip->SetDelayTime(TTDT_AUTOPOP, 10000); /* 10s */ m_pToolTip->SetDelayTime(TTDT_INITIAL, 2000); /* 2s */ // Add tooltip strings for the relevant controls rc = m_pToolTip->AddTool(&m_bExactMatch, TTSTR_EXACT_MATCH); rc = m_pToolTip->AddTool(&m_bAtLeastOneInputPin, TTSTR_ALOIP); rc = m_pToolTip->AddTool(&m_bAtLeastOneOutputPin, TTSTR_ALOOP); rc = m_pToolTip->AddTool(&m_bIsRenderer, TTSTR_IS_RENDERER); rc = m_pToolTip->AddTool(&m_bClear, TTSTR_CLEAR); rc = m_pToolTip->AddTool(&m_bSearch, TTSTR_SEARCH); rc = m_pToolTip->AddTool(&m_ListFilters, TTSTR_FILTERS); rc = m_pToolTip->AddTool(&m_ComboMerit, TTSTR_MERIT); rc = m_pToolTip->AddTool(&m_ComboInputCat, TTSTR_PIN_CAT); rc = m_pToolTip->AddTool(&m_ComboOutputCat, TTSTR_PIN_CAT); rc = m_pToolTip->AddTool(&m_ListInputMajor, TTSTR_TYPE); rc = m_pToolTip->AddTool(&m_ListInputMajor2, TTSTR_TYPE); rc = m_pToolTip->AddTool(&m_ListOutputMajor, TTSTR_TYPE); rc = m_pToolTip->AddTool(&m_ListOutputMajor2, TTSTR_TYPE); rc = m_pToolTip->AddTool(&m_ListInputMinor, TTSTR_SUBTYPE); rc = m_pToolTip->AddTool(&m_ListInputMinor2, TTSTR_SUBTYPE); rc = m_pToolTip->AddTool(&m_ListOutputMinor, TTSTR_SUBTYPE); rc = m_pToolTip->AddTool(&m_ListOutputMinor2, TTSTR_SUBTYPE); // Activate the tooltip control m_pToolTip->Activate(TRUE); return TRUE; } BOOL CMapperDlg::PreTranslateMessage(MSG* pMsg) { // Let the tooltip process the message, if appropriate if (m_pToolTip) m_pToolTip->RelayEvent(pMsg); return CDialog::PreTranslateMessage(pMsg); } void CMapperDlg::SetDefaults() { int i; // The app allows you to specify up to two major/minor type pairs FillMajorTypes(m_ListInputMajor); FillMajorTypes(m_ListInputMajor2); FillMajorTypes(m_ListOutputMajor); FillMajorTypes(m_ListOutputMajor2); // Initialize subtype list boxes m_ListInputMinor.ResetContent(); m_ListInputMinor2.ResetContent(); m_ListOutputMinor.ResetContent(); m_ListOutputMinor2.ResetContent(); // Set checkboxes to preferred default values m_bAtLeastOneInputPin.SetCheck(1); m_bAtLeastOneOutputPin.SetCheck(1); // Initialize merit box m_ComboMerit.ResetContent(); for (i=0; i < NUM_MERIT_TYPES; i++) { m_ComboMerit.InsertString(i, merittypes[i].szName); m_ComboMerit.SetItemData(i, merittypes[i].dwMerit); } m_ComboMerit.SetCurSel(4); // "Normal" merit // Initialize pin categories m_ComboInputCat.ResetContent(); m_ComboOutputCat.ResetContent(); m_ComboInputCat.AddString(TEXT("\0")); m_ComboOutputCat.AddString(TEXT("\0")); // Fill pin category lists for (i=1; i < NUM_PIN_TYPES; i++) { m_ComboInputCat.InsertString(i, pintypes[i].szName); m_ComboInputCat.SetItemDataPtr(i, (void *) pintypes[i].pGUID); m_ComboOutputCat.InsertString(i, pintypes[i].szName); m_ComboOutputCat.SetItemDataPtr(i, (void *) pintypes[i].pGUID); } m_ComboInputCat.SetCurSel(0); m_ComboOutputCat.SetCurSel(0); // Clear filter list m_ListFilters.ResetContent(); m_StrNumFilters.SetWindowText(TEXT("Filters Matching Query : 0")); // Select the first item in each type list FillSubType(m_ListInputMajor, m_ListInputMinor); FillSubType(m_ListInputMajor2, m_ListInputMinor2); FillSubType(m_ListOutputMajor, m_ListOutputMinor); FillSubType(m_ListOutputMajor2, m_ListOutputMinor2); // Disable the second type/subtype listboxes until the user selects // something other than "don't care" for the first type/subtype pair. OnSelchangeListInputMajor(); OnSelchangeListOutputMajor(); } void CMapperDlg::OnButtonClear() { // Clear all values and reset dialog SetDefaults(); } void CMapperDlg::OnClose() { // Disable and destroy the tooltip control if (m_pToolTip) { m_pToolTip->Activate(FALSE); delete m_pToolTip; m_pToolTip = 0; } // Release FilterMapper interface SAFE_RELEASE(m_pMapper); // Release COM CoUninitialize(); CDialog::OnClose(); } void CMapperDlg::OnDestroy() { // Disable and destroy the tooltip control if (m_pToolTip) { delete m_pToolTip; m_pToolTip = 0; } // Release FilterMapper interface SAFE_RELEASE(m_pMapper); CDialog::OnDestroy(); } void CMapperDlg::FillMajorTypes(CListBox& m_List) { m_List.ResetContent(); // Fill the specified list box with major type name/GUID for (int i=0; i < NUM_MAJOR_TYPES; i++) { m_List.InsertString(i, majortypes[i].szName); m_List.SetItemDataPtr(i, (void *) majortypes[i].pGUID); } m_List.SetCurSel(0); } void CMapperDlg::FillSubType(CListBox& m_List, CListBox& m_ListMinor) { const GUIDINFO *pSubtype; int nSelection = m_List.GetCurSel(); int nMajorType; // First clear the subtype list m_ListMinor.ResetContent(); // If the "don't care" item was selected, clear and exit if (nSelection == 0) { m_ListMinor.AddString(TEXT("\0")); m_ListMinor.SetCurSel(0); return; } else nMajorType = nSelection - 1; // Determine how to fill the minor type list, based on the // currently selected major type. pSubtype = pSubTypes[nMajorType]; // If there's no associated subtype, just add a default if (!pSubtype) { m_ListMinor.AddString(TEXT("\0")); m_ListMinor.SetCurSel(0); return; } else { // Set a default item for "don't care" m_ListMinor.AddString(TEXT("\0")); int i=0; // Fill the subtype list box. Enter N item data to the N+1 list slot. while (pSubtype[i].pGUID != NULL) { m_ListMinor.AddString(pSubtype[i].szName); m_ListMinor.SetItemDataPtr(i+1, (void *) pSubtype[i].pGUID); i++; } m_ListMinor.SetCurSel(0); } } void CMapperDlg::OnSelchangeListInputMajor() { // User has selected a new major type, so refill the subtype list box FillSubType(m_ListInputMajor, m_ListInputMinor); // Since the second type/subtype pair is irrelevant if the first // is a don't care, disable the second set if appropriate. EnableSecondTypePair(m_ListInputMajor, m_ListInputMajor2, m_ListInputMinor2); } void CMapperDlg::OnSelchangeListInputMajor2() { // User has selected a new major type, so refill the subtype list box FillSubType(m_ListInputMajor2, m_ListInputMinor2); } void CMapperDlg::OnSelchangeListOutputMajor() { // User has selected a new major type, so refill the subtype list box FillSubType(m_ListOutputMajor, m_ListOutputMinor); // Since the second type/subtype pair is irrelevant if the first // is a don't care, disable the second set if appropriate. EnableSecondTypePair(m_ListOutputMajor, m_ListOutputMajor2, m_ListOutputMinor2); } void CMapperDlg::OnSelchangeListOutputMajor2() { // User has selected a new major type, so refill the subtype list box FillSubType(m_ListOutputMajor2, m_ListOutputMinor2); } void CMapperDlg::EnableSecondTypePair(CListBox& m_ListMajor, CListBox& m_ListMajor2, CListBox& m_ListMinor2) { // If there is no selection in the first major type listbox, // clear and disable the second major/minor type listboxes. if (m_ListMajor.GetCurSel() == 0) { m_ListMajor2.SetCurSel(0); FillSubType(m_ListMajor2, m_ListMinor2); m_ListMajor2.EnableWindow(FALSE); m_ListMinor2.EnableWindow(FALSE); } else { m_ListMajor2.EnableWindow(TRUE); m_ListMinor2.EnableWindow(TRUE); } } void FillTypeArray(CListBox& m_ListMajor, CListBox& m_ListMinor, GUID *atypes, int nIndex, DWORD *pdwPairs) { int nMajorSel = m_ListMajor.GetCurSel(); int nMinorSel = m_ListMinor.GetCurSel(); // If no selection ("don't care"), just exit without modifying the array if (nMajorSel <= 0) return; // Get GUID for major type const GUID *p1 = (const GUID *)m_ListMajor.GetItemDataPtr(nMajorSel); // Since the FilterMapper interface requires GUIDs (instead of GUID *), // copy the specified GUID data into its array slot. memcpy(&atypes[nIndex], p1, sizeof(GUID)); // Increment number of type/subtype pairs (*pdwPairs)++; // If no selection ("don't care"), or uninitialized (returning -1), // just exit without modifying the array if (nMinorSel <= 0) return; // Get GUID for subtype const GUID *p2 = (const GUID *)m_ListMinor.GetItemDataPtr(nMinorSel); if (p2) memcpy(&atypes[nIndex+1], p2, sizeof(GUID)); } IEnumMoniker *CMapperDlg::GetFilterEnumerator(void) { // First set up the boolean values BOOL bExactMatch = m_bExactMatch.GetCheck(); BOOL bAtLeastOneInputPin = m_bAtLeastOneInputPin.GetCheck(); BOOL bAtLeastOneOutputPin = m_bAtLeastOneOutputPin.GetCheck(); BOOL bIsRenderer = m_bIsRenderer.GetCheck(); // Merit DWORD dwMerit = (DWORD) m_ComboMerit.GetItemData(m_ComboMerit.GetCurSel()); // Pin categories const GUID *pInCat = (const GUID *) m_ComboInputCat.GetItemDataPtr(m_ComboInputCat.GetCurSel()); const GUID *pOutCat = (const GUID *) m_ComboOutputCat.GetItemDataPtr(m_ComboOutputCat.GetCurSel()); // Major type/subtype pairs DWORD dwInputTypes=0, dwOutputTypes=0; GUID arrayInput[4], arrayOutput[4]; // Initialize GUID type/subtype arrays for (int i=0; i<4; i++) { arrayInput[i] = GUID_NULL; arrayOutput[i] = GUID_NULL; } // Fill each of the four GUID arrays (input/output, major/minor). // If the first call doesn't set anything (primary), don't bother to // read the secondary value, since it would be invalid anyway due to // its position within the array (2) but with a count of only 1. FillTypeArray(m_ListInputMajor, m_ListInputMinor, arrayInput, 0, &dwInputTypes); if (dwInputTypes) FillTypeArray(m_ListInputMajor2, m_ListInputMinor2, arrayInput, 2, &dwInputTypes); FillTypeArray(m_ListOutputMajor, m_ListOutputMinor, arrayOutput, 0, &dwOutputTypes); if (dwOutputTypes) FillTypeArray(m_ListOutputMajor2, m_ListOutputMinor2, arrayOutput, 2, &dwOutputTypes); // Enumerate all filters that match the specified criteria IEnumMoniker *pEnum; HRESULT hr=S_OK; hr = m_pMapper->EnumMatchingFilters( &pEnum, 0, // Reserved bExactMatch, // Use exact match? dwMerit, // Minimum merit bAtLeastOneInputPin, dwInputTypes, // Number of major type/subtype pairs for input arrayInput, // Array of major type/subtype pairs for input NULL, // Input medium pInCat, // Input pin category bIsRenderer, // Must be a renderer? bAtLeastOneOutputPin, dwOutputTypes, // Number of major type/subtype pairs for output arrayOutput, // Array of major type/subtype pairs for output NULL, // Output medium pOutCat); // Output pin category if (FAILED(hr)) return 0; else return pEnum; } int CMapperDlg::GetFilenameByCLSID(REFCLSID clsid, TCHAR *szFile) { HRESULT hr; LPOLESTR strCLSID; int rc=0; // Convert binary CLSID to a readable version hr = StringFromCLSID(clsid, &strCLSID); if(SUCCEEDED(hr)) { TCHAR szKey[512]; CString strQuery(strCLSID); // Create key name for reading filename from registry wsprintf(szKey, TEXT("Software\\Classes\\CLSID\\%s\\InprocServer32\0"), strQuery); // Free memory associated with strCLSID (allocated in StringFromCLSID) CoTaskMemFree(strCLSID); HKEY hkeyFilter=0; DWORD dwSize=MAX_PATH; BYTE szFilename[MAX_PATH]; // Open the CLSID key that contains information about the filter rc = RegOpenKey(HKEY_LOCAL_MACHINE, szKey, &hkeyFilter); if (rc == ERROR_SUCCESS) { rc = RegQueryValueEx(hkeyFilter, NULL, // Read (Default) value NULL, NULL, szFilename, &dwSize); if (rc == ERROR_SUCCESS) wsprintf(szFile, TEXT("%s"), szFilename); RegCloseKey(hkeyFilter); } } else return -1; return rc; } // Read merit and version information HRESULT CMapperDlg::GetMerit(IPropertyBag *pPropBag, DWORD *pdwMerit) { HRESULT hr; IAMFilterData *pData=0; *pdwMerit = 0; VARIANT varFilData={0}; varFilData.vt = VT_UI1 | VT_ARRAY; varFilData.parray = 0; // docs say to zero this BYTE *pbFilterData = 0; // 0 if not read DWORD dwcbFilterDAta = 0; // 0 if not read // Read compressed filter data from the property bag with a variant hr = pPropBag->Read(L"FilterData", &varFilData, 0); if(SUCCEEDED(hr)) { ASSERT(varFilData.vt == (VT_UI1 | VT_ARRAY)); dwcbFilterDAta = varFilData.parray->rgsabound[0].cElements; // Access the filter data HRESULT hrTmp = SafeArrayAccessData(varFilData.parray, (void **)&pbFilterData); ASSERT(hrTmp == S_OK); ASSERT(pbFilterData); } else { ASSERT(dwcbFilterDAta == 0 && pbFilterData == 0); return E_FAIL; } // Get the IAMFilterData interface for parsing the filter data hr = m_pMapper->QueryInterface(IID_IAMFilterData, (void **)&pData); if(SUCCEEDED(hr)) { BYTE *pb=0; // Use a helper method to parse the binary filter data. Pass in // the pointer to the filter data, its size, and a buffer to fill with // the resulting data. The "pb" buffer is allocated with CoTaskMemAlloc, // so it must be correspondingly freed by the caller. hr = pData->ParseFilterData(pbFilterData, dwcbFilterDAta, &pb); if(SUCCEEDED(hr)) { REGFILTER2 *pFil = ((REGFILTER2 **)pb)[0]; if(pbFilterData) { HRESULT hrTmp = SafeArrayUnaccessData(varFilData.parray); ASSERT(hrTmp == S_OK); hrTmp = VariantClear(&varFilData); ASSERT(hrTmp == S_OK); } // Assign the merit value from the REGFILTER2 structure if (pFil) *pdwMerit = pFil->dwMerit; // Free the memory allocated by ParseFilterData if (pb) CoTaskMemFree(pb); } // Release the IAMFilterData interface pData->Release(); } return hr; } void CMapperDlg::AddMerit(TCHAR *szInfo, DWORD dwMerit) { TCHAR szMerit[32]; switch (dwMerit) { case MERIT_NORMAL: wsprintf(szMerit, TEXT("MERIT_NORMAL\0")); break; // Assume normal case MERIT_PREFERRED: wsprintf(szMerit, TEXT("MERIT_PREFERRED\0")); break; case MERIT_UNLIKELY: wsprintf(szMerit, TEXT("MERIT_UNLIKELY\0")); break; case MERIT_DO_NOT_USE: wsprintf(szMerit, TEXT("MERIT_DO_NOT_USE\0")); break; case MERIT_SW_COMPRESSOR: wsprintf(szMerit, TEXT("MERIT_SW_COMPRESSOR\0")); break; case MERIT_HW_COMPRESSOR: wsprintf(szMerit, TEXT("MERIT_HW_COMPRESSOR\0")); break; default: wsprintf(szMerit, TEXT("0x%08x\0"), dwMerit); break; } // Add new merit information to string _tcscat(szInfo, szMerit); } void CMapperDlg::AddFilter(const TCHAR *szFilterName, const GUID *pCatGuid, DWORD dwMerit) { TCHAR szInfo[300], szFilename[255]; // First add the friendly name of the filter wsprintf(szInfo, TEXT("%s\t\0"), szFilterName); // Add the filter's merit value AddMerit(szInfo, dwMerit); // Get the filter's server name from the registry int rc = GetFilenameByCLSID(*pCatGuid, szFilename); // Add the filter's server name if (rc == ERROR_SUCCESS) { _tcscat(szInfo, TEXT("\t\0")); _tcscat(szInfo, szFilename); } // Add the filter name and filename to the listbox m_ListFilters.AddString(szInfo); } void CMapperDlg::OnButtonSearch() { HRESULT hr=S_OK; IEnumMoniker *pEnum; IMoniker *pMoniker=0; ULONG cFetched=0; VARIANT varName={0}; int nFilters=0; // Clear any previous results m_ListFilters.ResetContent(); // Enumerate filters based on the current dialog box selections pEnum = GetFilterEnumerator(); if (!pEnum) { m_ListFilters.AddString(TEXT("")); return; } hr = pEnum->Reset(); // Enumerate all filters that match the search criteria. The enumerator // that is returned from GetFilterEnumerator() will only list filters // that matched the user's search request. while((hr = pEnum->Next(1, &pMoniker, &cFetched)) == S_OK) { IPropertyBag *pPropBag; ASSERT(pMoniker); // Associate the moniker with a file hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); ASSERT(SUCCEEDED(hr)); ASSERT(pPropBag); if (FAILED(hr)) continue; // Read filter name from property bag varName.vt = VT_BSTR; hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (FAILED(hr)) continue; // Get filter name (converting BSTR name to a CString) CString str(varName.bstrVal); SysFreeString(varName.bstrVal); nFilters++; // Read Merit value from property bag DWORD dwMerit; GetMerit(pPropBag, &dwMerit); // Read filter's CLSID from property bag. This CLSID string will be // converted to a binary CLSID and passed to AddFilter(), which will // add the filter's name to the listbox and its CLSID to the listbox // item's DataPtr item. VARIANT varFilterClsid; varFilterClsid.vt = VT_BSTR; // Read CLSID string from property bag hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0); if(SUCCEEDED(hr)) { CLSID clsidFilter; // Add filter name and filename to listbox if(CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter) == S_OK) { AddFilter(str, &clsidFilter, dwMerit); } SysFreeString(varFilterClsid.bstrVal); } // Clean up interfaces SAFE_RELEASE(pPropBag); SAFE_RELEASE(pMoniker); } // Display number of filters matching query TCHAR szNumFilters[48]; wsprintf(szNumFilters, TEXT("Filters Matching Query : %d"), nFilters); m_StrNumFilters.SetWindowText(szNumFilters); // Clean up enumerator if (pEnum) pEnum->Release(); }