Уважаемые взломы MFC / ActiveX / COM, я «унаследовал» исходный код старого приложения MFC (первоначально созданного с помощью Visual Studio 6), которое до сих пор создается и запускается в VS 2010, но в качестве исходного кода встроило некоторые элементы управления ActiveX.по-видимому, сгенерированный мастером Visual Studio (файлы .h и .cpp, см. ниже);однако не в собственном подпроекте, так что создаются файлы .dll или .ocx.Вот соответствующая часть заголовочного файла одного такого элемента управления:
#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
Обратите внимание, что этот класс наследуется от CWnd, а не от какого-либо класса OCX.Но поскольку все окна MFC являются компонентами COM (как я где-то читал), и это сгенерированный код, он должен был сработать некоторое время назад.Я также читал, что это может быть пробел в миграции, который произошел где-то до 2005 года. Также обратите внимание на DECLARE_DYNCREATE, так что я думаю, что это поздняя привязка с использованием интерфейса IDispatch.Таким образом, MFC вызовет функцию Create () для нас.
Вышеупомянутый элемент управления используется посредством агрегирования с помощью прилагаемого CDialog (также созданного с помощью мастера VS):
//... analysedlg.h - leading auto-generated stuff omitted
class CAnalyseDlg : public CDialog
{
CChartfx m_chhrtfx;
//... enum for resource ID, DoDataExchange, message map, other members…
}
Диалог вочередь, встраивается в класс представления приложения (опять же, через переменную-член) и создается путем вызова DoModal () в обработчике события пункта меню.
Итак, когда я нажимаю на соответствующий пункт меню,Я получаю утверждение m_hWnd NULL и при нажатии 'retry' в появившемся диалоге следующий стек (отрывок):
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++
В выходных данных отладки VS есть следующие строки:
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.
Таким образом, очевидно, что вызов CoCreateInstance уже был сделан и молча провалился без утверждения, которое было бы неплохо иметь.Кто-нибудь знает, где это находится?
Мой главный вопрос: правильно ли, что в этом случае обычно MFC позаботится о регистрации элемента управления, даже если он не находится в проекте .dll или .ocx, и что онДолжно быть, работал так в прошлом.Я где-то читал, что CreateDlgIndirect с DialogTemplate является способом создания элементов управления ActiveX без необходимости файла .dll или .ocx.В вышеупомянутом стеке это также вызывается, но не для элемента управления ActiveX, а для диалога.
Кто-нибудь знает больше об этой проблеме и как ее исправить?Если мне нужно вручную зарегистрировать элементы управления, например, используя regsvr32.exe или через исходный код, есть ли способ без файлов .dll или .ocx?Или мне нужно переупаковать компоненты ActiveX в их собственных проектах (в любом случае, что будет более модульным / модульным)?
Я надеюсь, что мое описание проблемы достаточно точное, и я был бы очень благодарен за любой ответ.С уважением.