2011-11-07 2 views
0

Chères fissures MFC/ActiveX/COM, j'ai hérité de la source d'une ancienne application MFC (créée à l'origine avec Visual Studio 6) qui est déjà compilée et exécutée dans VS 2010, mais qui intègre des contrôles ActiveX comme code source , apparemment généré par l'assistant Visual Studio (fichiers .h et .cpp, voir ci-dessous); cependant pas dans un sous-projet propre de sorte qu'un fichier .dll ou .ocx est généré. Voici la partie pertinente du fichier d'en-tête d'un tel contrôle:CWnd en tant que contrôle ActiveX sans fichier .dll ou .ocx en C++?

#if !defined(AFX_CHARTFX_H__F8A080E0_0647_11D4_92B0_0000E886CDCC__INCLUDED_) 
#define AFX_CHARTFX_H__F8A080E0_0647_11D4_92B0_0000E886CDCC__INCLUDED_ 

#if _MSC_VER >= 1000 
#pragma once 
#endif // _MSC_VER >= 1000 
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ 

// NOTE: Do not modify the contents of this file. If this class is regenerated by 
// Microsoft Visual C++, your modifications will be overwritten. 

///////////////////////////////////////////////////////////////////////////// 
// CChartfx wrapper class 

class CChartfx : public CWnd 
{ 
protected: 
    DECLARE_DYNCREATE(CChartfx) 
public: 
    CLSID const& GetClsid() 
    { 
     static CLSID const clsid 
      = { 0x8996b0a1, 0xd7be, 0x101b, { 0x86, 0x50, 0x0, 0xaa, 0x0, 0x3a, 0x55, 0x93 } }; 
     return clsid; 
    } 
    virtual BOOL Create(LPCTSTR lpszClassName, 
     LPCTSTR lpszWindowName, DWORD dwStyle, 
     const RECT& rect, 
     CWnd* pParentWnd, UINT nID, 
     CCreateContext* pContext = NULL) 
    { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); } 

    BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, 
     const RECT& rect, CWnd* pParentWnd, UINT nID, 
     CFile* pPersist = NULL, BOOL bStorage = FALSE, 
     BSTR bstrLicKey = NULL) 
    { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID, 
     pPersist, bStorage, bstrLicKey); } 
    //rest of header file omitted 

Notez que cette classe hérite de CWnd et non une classe OCX. Mais puisque toutes les fenêtres de MFC sont des composants de COM (comme je l'ai lu quelque part) et ceci est le code généré il devrait avoir fonctionné il ya quelque temps. J'ai également lu que cela peut être vraiment un écart de migration qui s'est produit quelque part avant 2005. Notez également le DECLARE_DYNCREATE, donc je pense que c'est une liaison tardive, en utilisant l'interface IDispatch. Ainsi, MFC appellera une fonction Create() pour nous.

La commande ci-dessus est utilisé par l'intermédiaire d'une agrégation par un englobant CDialog (également créé avec assistant VS):

//... analysedlg.h - leading auto-generated stuff omitted 
class CAnalyseDlg : public CDialog 
{ 
    CChartfx m_chhrtfx; 
    //... enum for resource ID, DoDataExchange, message map, other members… 
} 

La boîte de dialogue, à son tour, est noyée dans une classe de vue de l'application (à nouveau, par l'intermédiaire d'un variable membre) et créé en appelant DoModal() dans un gestionnaire d'événements d'élément de menu.

Alors, quand je clique sur l'élément de menu correspondant, je reçois une assertion NULL m_hWnd et quand frapper « retry » dans le dialogue sauté vers le haut, la pile suivante (extrait):

mfc100d.dll!COleControlContainer::FillListSitesOrWnds(_AFX_OCC_DIALOG_INFO * pOccDlgInfo) line 925 + 0x23 Bytes C++ 
mfc100d.dll!COccManager::CreateDlgControls(CWnd * pWndParent, const char * lpszResourceName, _AFX_OCC_DIALOG_INFO * pOccDlgInfo) line 410 C++ 
mfc100d.dll!CDialog::HandleInitDialog(unsigned int __formal, unsigned int __formal) line 715 + 0x22 Bytes C++ 
mfc100d.dll!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult) line 2383 + 0x11 Bytes C++ 
mfc100d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) line 2087 + 0x20 Bytes C++ 
mfc100d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) line 257 + 0x1c Bytes C++ 
mfc100d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) line 420 C++ 
mfc100d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) line 420 + 0x15 Bytes C++ 
user32.dll!766162fa() 
[missing frames omitted by me] 
mfc100d.dll!CWnd::CreateDlgIndirect(const DLGTEMPLATE * lpDialogTemplate, CWnd * pParentWnd, HINSTANCE__ * hInst) line 366 + 0x2a Bytes C++ 
mfc100d.dll!CDialog::DoModal() line 630 + 0x20 Bytes C++ 

Dans le VS sortie de débogage, il y a les lignes suivantes:

CoCreateInstance of OLE control {8996B0A1-D7BE-101B-8650-00AA003A5593} failed. 
>>> Result code: 0x80040154 
>>> Is the control is properly registered? 
Warning: Resource items and Win32 Z-order lists are out of sync. Tab order may be not defined well. 

donc apparemment l'appel à CoCreateInstance avait déjà été fait et silencieusement échoué sans une affirmation qui aurait été agréable d'avoir eu. Est-ce que quelqu'un sait où c'est?

Ma question est de savoir s'il est vrai que dans ce cas normalement MFC prendrait soin de enregistrer le contrôle même si elle est pas dans un projet .dll ou .ocx et qu'il doit avoir travaillé comme celui-ci dans le passé. J'ai lu quelque part que CreateDlgIndirect avec un DialogTemplate est un moyen de créer des contrôles ActiveX sans avoir besoin d'un fichier .dll ou .ocx. Dans la pile ci-dessus, cela s'appelle, aussi, mais pas pour le contrôle ActiveX, mais pour le dialogue à la place.

Quelqu'un sait-il plus sur ce problème et comment le résoudre? Si je dois enregistrer manuellement les commandes, par ex. en utilisant regsvr32.exe ou via le code source, est-il un moyen sans fichiers .dll ou .ocx? Ou dois-je reconditionner les composants ActiveX dans leurs propres projets (quoi de plus basé sur les composants/modulaire de toute façon)?

J'espère que ma description du problème est assez précise et je serais très reconnaissant pour toute réponse. Cordialement.

+0

"... toutes les fenêtres MFC sont des composants COM ..." - J'en doute. Un CWnd est juste une enveloppe autour de la poignée HWND. Alors, avez-vous la source pour le composant ChartFx ou pas? – dwo

+0

> "... toutes les fenêtres MFC sont des composants COM ..." - J'en doute. Un CWnd est juste une enveloppe autour de la poignée HWND. R: Vous avez raison, cette déclaration était erronée. J'avais mal interprété l'article suivant par Paul DiLascia: http://msdn.microsoft.com/en-us/magazine/cc301408.aspx (Deux articles sur cette page, recherchez 'programmer COM' sur cette page pour aller à la première phrase.) – juniper

+0

J'ai trouvé plus d'informations sur ces CWnds encapsulant les contrôles ActiveX: http://www.murrayc.com/learning/windows/useactivex.shtml http://msdn.microsoft.com/fr-fr /library/aa294388(v=VS.60).aspx '[..] Les contrôles créés avec les classes de contrôle MFC ActiveX sont auto-enregistrés car deux points d'entrée dans l'exécutable du contrôle, DLLRegisterServer et DLLUnregisterServer, sont automatiquement ajoutés lorsque ControlWizard crée les fichiers du contrôle. [..] ' – juniper

Répondre

0

Je viens d'exécuter ceci en utilisant un ancien contrôle ActiveX. Apparemment, il était thread appartement et j'essayais d'appeler CoInitializeEx() avec COINIT_MULTITHREADED.

Questions connexes