CWnd как элемент управления ActiveX без .dll или .ocx файла в C ++? - PullRequest
0 голосов
/ 08 ноября 2011

Уважаемые взломы 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 в их собственных проектах (в любом случае, что будет более модульным / модульным)?

Я надеюсь, что мое описание проблемы достаточно точное, и я был бы очень благодарен за любой ответ.С уважением.

1 Ответ

0 голосов
/ 31 января 2014

Я только что столкнулся с этим при использовании старого элемента управления ActiveX.Видимо, это была квартира с многопоточностью, и я пытался вызвать CoInitializeEx () с COINIT_MULTITHREADED.

...