CoCreateInstance nonmodal



  • Moin,
    ich erstelle für meine eigene Verwendung im Verein eine Dokumentenverwaltung.
    Dazu möchte ich in einem Fenster die Voransicht der Office Dokuments anzeigen.
    Ich habe dazu ein schönes Beispiel gefunden, das habe ich eingebunden.
    Mit CoCreateInstance wird das entsprechende Programm zur Voransicht aufgerufen und das Dokument wird in einem Control im Dialog richtig dargestellt.
    Allerdings nur wenn der Dialog modal aufgerufen wird.
    Wenn ich den Dialog nonmodal ( per create ) aufrufe, was ich ja brauche wird zwar das entsprechende Programm gestartet, aber das Programm wird nicht auf das Control gemappt, sondern es wird einfach nur gestartet.
    Irgendwo geht da die Bindung verloren, kann mir vielleicht jemand aus diesem Forum einen Tipp geben in welche Richtung ich suchen muss ?
    Komm ich mit AfxOleInit weiter ??
    Mfg

    verwegener


  • |  Mod

    Zeige Code. Wie Dein Dialog läuft ist eigentlich egal.
    Die Frage ist: Hast Du eine Message Loop?
    Ohne die geht nichts...



  • Moin, hier etwas Code.
    Der Code ist nicht von mir, ich möchte mich nicht mit fremden Federn schücken.

    In der Aufrufenden Prozedur sieht es so aus :

    In der CPreviewAppDlg werden die installierten Previewer eingelesen usw.

    Dann wird über den Button Browse (OnBnClickedButtonBrowse) ein Verzeichnis in ein Array eingelesen
    und bei dem Button Next (OnBnClickedButtonNext) soll die nächste Datei im Array über die Funktion DoPreview angezeigt werden.

    Mfg verwegener

     ... Code ... 
    #include "CPreviewAppDlg.h"
    
    	pDialog = new CPreviewAppDlg();
    
    	bool ret = pDialog->Create(IDD_PREVIEWAPP_DIALOG);
    
    	pDialog->ShowWindow(SW_SHOW);
    
    
    

    Der aufrufende Dialog reagiert weiter auf Eingaben,

    
    
    CPreviewAppDlg.h
    #pragma once
    
    
    // CPreviewAppDlg-Dialog
    typedef struct tagGUIDNAMEPAIR
    {
    	CString guid;
    	CString name;
    }GUIDNAMEPAIR, *PGUIDNAMEPAIR;
    
    #define SAFERELEASE( X ) { if( X ) { X->Release(); X = NULL; } }
    
    
    class CPreviewAppDlg : public CDialogEx
    {
    	DECLARE_DYNAMIC(CPreviewAppDlg)
    
    public:
    	CPreviewAppDlg(CWnd* pParent = nullptr);   // Standardkonstruktor
    	virtual ~CPreviewAppDlg();
    
    // Dialogfelddaten
    #ifdef AFX_DESIGN_TIME
    	enum { IDD = IDD_PREVIEWAPP_DIALOG };
    #endif
    
    protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung
    
    	DECLARE_MESSAGE_MAP()
    	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    public:
    	virtual BOOL OnInitDialog();
    private:
    	CWnd *m_WndPreview;
    	RECT m_rectPreview;
    	void ListInstalledHandlers();
    	PGUIDNAMEPAIR m_pGuidFriendlyNamePair;
    	DWORD m_countHandlers;
    	CList<CString, CString&> m_FileList;
    	POSITION m_posNowShowing;
    	WCHAR path[MAX_PATH];
    	IPreviewHandler *m_pIP;
    	IInitializeWithFile *m_pIFile;
    	IInitializeWithStream *m_pIStream;
    
    
    
    public:
    	// Zeiger auf listbox
    	CListCtrl m_InstalledHandlers;
    	CComboBox m_cbAssociatedName;
    	CListCtrl m_AssociationsList;
    private:
    	void AssociationsList();
    public:
    	// CString CPreviewAppDlg::FriendlyNameFromGuid( WCHAR * GUID )
    	CString FriendlyNameFromGuid(WCHAR * GUID);
    	void ListAssociations();
    	afx_msg void OnBnClickedButtonBrowse();
    	CButton m_btnNext;
    	afx_msg void OnBnClickedButtonNext();
    private:
    	// DWORD WINAPI  DoPreview( HWND hWnd, RECT rectPreview, LPCTSTR szFile);
    	DWORD  DoPreview(HWND hWnd, RECT rectPreview, LPCTSTR szFile);
    	// CString GetClsidFromExtn( WCHAR * szExtn )
    	CString GetClsidFromExtn(WCHAR * szExtn);
    	HGLOBAL m_hGlobal;
    
    	IStream * m_pStream;
    };
    
    
     ... Code ... 
    // CPreviewAppDlg.cpp: Implementierungsdatei
    //
    
    #include "stdafx.h"
    #include "EAkteMFC6.h"
    #include "CPreviewAppDlg.h"
    #include "afxdialogex.h"
    
    
    // CPreviewAppDlg-Dialog
    
    IMPLEMENT_DYNAMIC(CPreviewAppDlg, CDialogEx)
    
    CPreviewAppDlg::CPreviewAppDlg(CWnd* pParent /*=nullptr*/)
    	: CDialogEx(IDD_PREVIEWAPP_DIALOG, pParent),
    	m_WndPreview(NULL),
    	m_pGuidFriendlyNamePair(NULL),
    	m_countHandlers(0),
    	m_pIP(NULL),
    	m_pIFile(NULL),
    	m_pIStream(NULL),
    	m_hGlobal(NULL),
    	m_pStream(NULL)
    	
    {
    
    }
    
    CPreviewAppDlg::~CPreviewAppDlg()
    {
    }
    
    void CPreviewAppDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialogEx::DoDataExchange(pDX);
    	// DDX_Text(pDX, IDC_PREVIEW, m_InstalledHandlers);
    	DDX_Control(pDX, IDC_LIST_PREVIEWERS_INSTALLED, m_InstalledHandlers);
    	DDX_Control(pDX, IDC_COMBO1, m_cbAssociatedName);
    	DDX_Control(pDX, IDC_LIST_ASSOCIATIONS, m_AssociationsList);
    	DDX_Control(pDX, IDC_BUTTON_NEXT, m_btnNext);
    }
    
    
    BEGIN_MESSAGE_MAP(CPreviewAppDlg, CDialogEx)
    	ON_BN_CLICKED(IDC_BUTTON_BROWSE, &CPreviewAppDlg::OnBnClickedButtonBrowse)
    	ON_BN_CLICKED(IDC_BUTTON_NEXT, &CPreviewAppDlg::OnBnClickedButtonNext)
    END_MESSAGE_MAP()
    
    
    // CPreviewAppDlg-Meldungshandler
    
    
    BOOL CPreviewAppDlg::PreCreateWindow(CREATESTRUCT& cs)
    {
    	// TODO: Fügen Sie hier Ihren spezialisierten Code ein, und/oder rufen Sie die Basisklasse auf.
    
    	return CDialogEx::PreCreateWindow(cs);
    }
    
    
    BOOL CPreviewAppDlg::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    
    	AfxDebugBreak();
    
    	m_WndPreview = GetDlgItem(IDC_PREVIEW);
    
    	CWnd* pWnd = GetDlgItem(IDC_PREVIEW);
    
    
    	m_WndPreview->GetWindowRect(&m_rectPreview);
    
    	m_rectPreview.right -= m_rectPreview.left + 10;
    	m_rectPreview.bottom -= m_rectPreview.top + 10;
    	m_rectPreview.top = 20;
    	m_rectPreview.left = 10;
    
    	// initialize the list controls to report view
    	m_InstalledHandlers.ModifyStyle(0, LVS_REPORT, 0);
    	ListView_SetExtendedListViewStyle(m_InstalledHandlers.m_hWnd, LVS_EX_FULLROWSELECT);
    	m_InstalledHandlers.InsertColumn(0, L"Name", 0, 150);
    	m_InstalledHandlers.InsertColumn(1, L"CLSID", 0, 200);
    
    
    	m_AssociationsList.ModifyStyle(0, LVS_REPORT, 0);
    	ListView_SetExtendedListViewStyle(m_AssociationsList.m_hWnd, LVS_EX_FULLROWSELECT);
    	m_AssociationsList.InsertColumn(0, L"Extension", 0, 150);
    	m_AssociationsList.InsertColumn(1, L"Handler", 0, 200);
    
    	// m_btnNext.EnableWindow(FALSE);
    
    	ListInstalledHandlers();
    	ListAssociations();
    	
    
    
    	m_cbAssociatedName.SetCurSel(0);
    	return TRUE;  // return TRUE unless you set the focus to a control
    				  // AUSNAHME: OCX-Eigenschaftenseite muss FALSE zurückgeben.
    }
    
    
    void CPreviewAppDlg::ListInstalledHandlers()
    {
    	AfxDebugBreak();
    	HKEY hk = 0;
    
    	WCHAR wcValue[MAX_PATH];
    	WCHAR wcData[MAX_PATH];
    	DWORD Type = 0;
    	DWORD cValue = sizeof(wcValue) / sizeof(wcValue[0]);
    	DWORD cbData = sizeof(wcData);
    	if (NULL != m_pGuidFriendlyNamePair)
    	{
    		// delete[] m_pGuidFriendlyNamePair;
    		m_pGuidFriendlyNamePair = NULL;
    	}
    	// m_InstalledHandlers ist ein Listcontroll !!
    	m_InstalledHandlers.DeleteAllItems();
    	//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PreviewHandlers
    	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    		L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers",
    		0,
    		KEY_READ,
    		&hk))
    	{
    		RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &m_countHandlers, NULL, NULL, NULL, NULL);
    		m_pGuidFriendlyNamePair = new GUIDNAMEPAIR[(m_countHandlers * sizeof(GUIDNAMEPAIR))];
    
    		for (DWORD i = 0; i < m_countHandlers; i++)
    		{
    			DWORD cValue = sizeof(wcValue) / sizeof(wcValue[0]);
    			DWORD cbData = sizeof(wcData);
    			DWORD dw = RegEnumValue(hk,
    				i,
    				wcValue,
    				&cValue,
    				NULL,
    				&Type,
    				(LPBYTE)wcData,
    				&cbData
    			);
    			{
    
    				LVITEM lvitem;
    				memset(&lvitem, 0, sizeof(lvitem));
    				lvitem.iItem = i;
    				lvitem.iSubItem = 0;
    				lvitem.pszText = wcData;
    				lvitem.mask = LVIF_TEXT;
    				// List Control !!
    				m_InstalledHandlers.InsertItem(&lvitem);
    				m_cbAssociatedName.AddString(wcData);
    				(m_pGuidFriendlyNamePair + i)->name = wcData;
    
    				memset(&lvitem, 0, sizeof(lvitem));
    				lvitem.iItem = i;
    				lvitem.iSubItem = 1;
    				lvitem.pszText = wcValue;
    				lvitem.mask = LVIF_TEXT;
    				// List Control !!
    				 m_InstalledHandlers.SetItem(&lvitem);
    				(m_pGuidFriendlyNamePair + i)->guid = wcValue;
    
    			}
    
    
    		}
    		RegCloseKey(hk);
    	}
    
    }
    
    
    
    void CPreviewAppDlg::AssociationsList()
    {
    	HKEY hk = 0;
    	DWORD dwCount = 0;
    	WCHAR wcName[MAX_PATH];
    	WCHAR wcData[MAX_PATH];
    	CString csExt = NULL;
    
    	DWORD cName = sizeof(wcName) / sizeof(wcName[0]);
    	LONG cbData = sizeof(wcData);
    	DWORD countFound = 0;
    
    	m_AssociationsList.DeleteAllItems();
    	for (DWORD i = 0; ; i++)
    	{
    		cName = sizeof(wcName) / sizeof(wcName[0]);
    		cbData = sizeof(wcData);
    		if (ERROR_SUCCESS == RegEnumKey(HKEY_CLASSES_ROOT,
    			i,
    			wcName,
    			cName))
    		{
    			if (L'.' != wcName[0])
    			{
    				continue;
    			}
    			csExt = wcName;
    
    			LVITEM lvitem;
    			memset(&lvitem, 0, sizeof(lvitem));
    			lvitem.iItem = m_AssociationsList.GetItemCount();
    			wcscat_s(wcName, L"\\ShellEx\\{8895b1c6-b41f-4c1c-a562-0d564250836f}");
    			// found the key, now find the GUID and match it with friendly name
    			if (ERROR_SUCCESS == RegQueryValue(HKEY_CLASSES_ROOT, wcName, wcData, &cbData))
    			{
    				lvitem.iSubItem = 0;
    				lvitem.pszText = (LPWSTR)(LPCTSTR)csExt;
    				lvitem.mask = LVIF_TEXT;
    				m_AssociationsList.InsertItem(&lvitem);
    				lvitem.iSubItem = 1;
    				lvitem.pszText = (LPWSTR)(LPCTSTR)FriendlyNameFromGuid(wcData); // TODO find the friendly name for this
    				m_AssociationsList.SetItem(&lvitem);
    			}
    		}
    		else
    		{
    			break;
    		}
    
    
    	}
    
    }
    
    
    
    
    // CString CPreviewAppDlg::FriendlyNameFromGuid( WCHAR * GUID )
    CString CPreviewAppDlg::FriendlyNameFromGuid(WCHAR * GUID)
    {
    	CString csRet = L"";
    	if (NULL != GUID)
    	{
    		for (DWORD dwIndex = 0; dwIndex < m_countHandlers; dwIndex++)
    		{
    			if (0 == (m_pGuidFriendlyNamePair + dwIndex)->guid.CompareNoCase(GUID))
    			{
    				csRet = (m_pGuidFriendlyNamePair + dwIndex)->name;
    			}
    		}
    	}
    
    	return csRet;
    }
    
    
    void CPreviewAppDlg::ListAssociations()
    {
    	HKEY hk = 0;
    	DWORD dwCount = 0;
    	WCHAR wcName[MAX_PATH];
    	WCHAR wcData[MAX_PATH];
    	CString csExt = NULL;
    
    	DWORD cName = sizeof(wcName) / sizeof(wcName[0]);
    	LONG cbData = sizeof(wcData);
    	DWORD countFound = 0;
    
    	m_AssociationsList.DeleteAllItems();
    	for (DWORD i = 0; ; i++)
    	{
    		cName = sizeof(wcName) / sizeof(wcName[0]);
    		cbData = sizeof(wcData);
    		if (ERROR_SUCCESS == RegEnumKey(HKEY_CLASSES_ROOT,
    			i,
    			wcName,
    			cName))
    		{
    			if (L'.' != wcName[0])
    			{
    				continue;
    			}
    			csExt = wcName;
    
    			LVITEM lvitem;
    			memset(&lvitem, 0, sizeof(lvitem));
    			lvitem.iItem = m_AssociationsList.GetItemCount();
    			wcscat_s(wcName, L"\\ShellEx\\{8895b1c6-b41f-4c1c-a562-0d564250836f}");
    			// found the key, now find the GUID and match it with friendly name
    			if (ERROR_SUCCESS == RegQueryValue(HKEY_CLASSES_ROOT, wcName, wcData, &cbData))
    			{
    				lvitem.iSubItem = 0;
    				lvitem.pszText = (LPWSTR)(LPCTSTR)csExt;
    				lvitem.mask = LVIF_TEXT;
    				m_AssociationsList.InsertItem(&lvitem);
    				lvitem.iSubItem = 1;
    				lvitem.pszText = (LPWSTR)(LPCTSTR)FriendlyNameFromGuid(wcData); // TODO find the friendly name for this
    				m_AssociationsList.SetItem(&lvitem);
    			}
    		}
    		else
    		{
    			break;
    		}
    
    
    	}
    
    }
    
    
    void CPreviewAppDlg::OnBnClickedButtonBrowse()
    {
    	CString findpath = L"";
    	HANDLE hFind = NULL;
    	BROWSEINFO bi = { 0 };
    	bi.lpszTitle = _T("Pick a Directory");
    	LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
    	if (pidl != 0)
    	{
    		// get the name of the folder
    
    		if (SHGetPathFromIDList(pidl, path))
    		{
    			_tprintf(_T("Selected Folder: %s\n"), path);
    		}
    
    		// free memory used
    		IMalloc * imalloc = 0;
    		if (SUCCEEDED(SHGetMalloc(&imalloc)))
    		{
    			imalloc->Free(pidl);
    			imalloc->Release();
    		}
    
    		findpath = path;
    		findpath.Append(L"\\*.*");
    		WIN32_FIND_DATA fd;
    		hFind = FindFirstFile(findpath, &fd);
    		SetDlgItemText(IDC_STATIC_NOW_SHOWING, L"click Next");
    		m_FileList.RemoveAll();
    		do
    		{
    
    			if (0 != (wcscmp(L".", fd.cFileName)) &&
    				0 != (wcscmp(L"..", fd.cFileName)) &&
    				(0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
    			{
    				CString stTemp;
    				stTemp.Format(L"%s\\%s", path, fd.cFileName);
    				m_FileList.AddTail(stTemp);
    
    			}
    		} while (FindNextFile(hFind, &fd));
    		m_posNowShowing = m_FileList.GetHeadPosition();
    	}
    	if (m_FileList.GetCount())
    	{
    		m_btnNext.EnableWindow(TRUE);
    	}
    }
    
    
    void CPreviewAppDlg::OnBnClickedButtonNext()
    {
    	if (NULL == m_posNowShowing)
    	{
    		m_posNowShowing = m_FileList.GetHeadPosition();
    	}
    
    	CString csShowFile;
    	csShowFile = m_FileList.GetNext(m_posNowShowing);
    	if (FALSE == csShowFile.IsEmpty())
    	{
    		DoPreview(m_WndPreview->m_hWnd, m_rectPreview, LPCTSTR(csShowFile));
    		SetDlgItemText(IDC_STATIC_NOW_SHOWING, LPCTSTR(csShowFile));
    	}
    }
    
    DWORD CPreviewAppDlg::DoPreview(HWND hWnd, RECT rectPreview, LPCTSTR szFile)
    {
    	// TODO: Fügen Sie hier Ihren Implementierungscode ein..
    	WCHAR *pwcExtn = NULL;
    	CString csClsid = L"";
    	CString csPreviewer = L"";
    	DWORD dwRet = ERROR_BAD_ARGUMENTS;
    
    
    	if ((NULL != hWnd) && (NULL != szFile) &&
    		(NULL != StrRChr(szFile, NULL, L'.')))
    	{
    		pwcExtn = StrRChr(szFile, NULL, L'.');
    		csClsid = GetClsidFromExtn(pwcExtn);
    		csPreviewer.Format(L"Using Previewer:-");
    
    		if (NULL != m_hGlobal)
    		{
    			GlobalFree(m_hGlobal);
    			m_hGlobal = NULL;
    		}
    		
    
    		SAFERELEASE(m_pIFile)
    		SAFERELEASE(m_pIStream)
    
    		SAFERELEASE(m_pStream)
    			if (NULL != m_pIP)
    			{
    				m_pIP->Unload();
    				SAFERELEASE(m_pIP);
    			}
    
    
    		if (FALSE == csClsid.IsEmpty())
    		{
    
    			HRESULT hr = E_FAIL;
    			CLSID cls;
    
    			CLSIDFromString((LPWSTR)(LPCTSTR)csClsid, &cls);
    
    			if (S_OK == CoCreateInstance(cls, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IPreviewHandler, (LPVOID*)&m_pIP))
    			{
    				m_pIP->QueryInterface(IID_IInitializeWithFile, (LPVOID*)&m_pIFile);
    				m_pIP->QueryInterface(IID_IInitializeWithStream, (LPVOID*)&m_pIStream);
    
    			}
    			if (m_pIFile)
    			{
    				hr = m_pIFile->Initialize(szFile, STGM_READ);
    			}
    			else if (m_pIStream)
    			{
    				HANDLE hFile = CreateFile(szFile, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    				if (INVALID_HANDLE_VALUE != hFile)
    				{
    					DWORD dwSize = GetFileSize(hFile, NULL);
    					m_hGlobal = GlobalAlloc(GPTR, dwSize);
    					BYTE * pByte = (BYTE *)GlobalLock(m_hGlobal);
    
    					if (pByte)
    					{
    						ReadFile(hFile, pByte, dwSize, &dwSize, NULL);
    						GlobalUnlock(m_hGlobal);
    
    						CreateStreamOnHGlobal(m_hGlobal, TRUE, &m_pStream);
    						hr = m_pIStream->Initialize(m_pStream, STGM_READ);
    					}
    
    					CloseHandle(hFile);
    				}
    			}
    
    			if (m_pIP)
    			{
    				csPreviewer += FriendlyNameFromGuid((WCHAR*)(LPCTSTR)csClsid);
    				hr = m_pIP->SetWindow(hWnd, &rectPreview);
    				hr = m_pIP->DoPreview();
    				dwRet = ERROR_SUCCESS;
    			}
    		}
    		if (ERROR_SUCCESS != dwRet)
    		{
    			csPreviewer += L"None";
    			::InvalidateRect(this->m_hWnd, NULL, TRUE);
    		}
    		SetDlgItemText(IDC_STATIC_PREVIEWER_USED, csPreviewer);
    
    	}
    	return dwRet;
    
    
    }
    
    
    CString CPreviewAppDlg::GetClsidFromExtn(WCHAR * szExtn)
    {
    	
    		CString cs = L"";
    		CString strRet = L"";
    		WCHAR wcData[MAX_PATH];
    		LONG cData = sizeof(wcData);
    		if (NULL != szExtn)
    		{
    			cs.Format(L"%s\\ShellEx\\{8895b1c6-b41f-4c1c-a562-0d564250836f}", szExtn);
    			if (ERROR_SUCCESS == RegQueryValue(HKEY_CLASSES_ROOT, cs, wcData, &cData))
    			{
    				strRet = wcData;
    			}
    		}
    		return strRet;
    	}
    
    
    
    

  • |  Mod

    Und was macht Dein Programm, nachdem es CreateDialog aufgerufen hat?
    Hast Du eine eigene Message Loop?

    Dein Inproc Server Viewer können nur funktionieren, wenn Du auch ein laufende eigene Message-Loop hats. Wie auch sonst sollten die Nachrichten Deiner Buttons in Deinem Dialog ankommen?



  • @martin-richter
    Ich habe eine Message Loop.
    Nachdem ich den nonmodalen Dialog aufgerufen habe, kann ich im Hauptdialog weitere Dialoge über mein Menü aufrufen, in einer Strukturansicht (Tree) andere Einträge anklicken usw.

    Mein Idee ist es die Dokumentbezeichnungen die in einer Datenbank abgelegt sind, im TreeView anzuzeigen ( funktioniert ) und wenn ich auf eine Dokumentbezeichnung klicke, soll das Dokument im nonmodalen Dialog angezeigt werden.

    Mfg
    verwegener