CDialog:: Создать не удалось для диалога с элементом управления ActiveX
У меня есть модуль, который создает немодальное диалоговое окно, содержащее элемент управления ActiveX. Этот модуль был частью приложения MFC EXE, и создание диалогового окна работало нормально. Недавно я переместил модуль на ATL/COM-сервер и скопировал ресурс диалога из EXE-файла на COM-сервер. При попытке создать немодальный диалог с помощью CDialog::Create()
ошибка происходит.
Я отладил в CDialog::Create
и заметил, что он терпит неудачу в ::CreateDialogIndirect()
который возвращается NULL
а также GetLastError
возвращается 0
, Я изменил флаг "Нет создания ошибки" на "Истина" в свойствах ресурса диалога, и я получил более подробную информацию об ошибке. Проблема происходит в диалоге DoDataExchange()
в пределах DDX_Control
макро. Это вызывает в CDataExchange::PrepareCtrl()
с идентификатором ресурса элемента управления следующим образом:
HWND CDataExchange::PrepareCtrl(int nIDC)
{
ASSERT(nIDC != 0);
ASSERT(nIDC != -1); // not allowed
HWND hWndCtrl;
COleControlSite* pSite = NULL;
m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
if (hWndCtrl == NULL)
{
// Could be a windowless OCX
pSite = m_pDlgWnd->GetOleControlSite(nIDC);
if (pSite == NULL)
{
TRACE(traceAppMsg, 0, "Error: no data exchange control with ID 0x%04X.\n", nIDC);
ASSERT(FALSE);
AfxThrowNotSupportedException();
}
}
m_idLastControl = nIDC;
m_bEditLastControl = FALSE; // not an edit item by default
return hWndCtrl;
}
Вызов функции m_pDlgWnd->GetOleControlSite()
происходит сбой для переданного идентификатора ресурса. Кстати, идентификатор ресурса - это идентификатор элемента управления.
Любые предложения о том, почему это работает внутри EXE и не работает на COM-сервере?
5 ответов
У меня была точно такая же проблема. В моем случае проблема оказалась в том, что я не вызвал AfxEnableControlContainer(). Я добавил вызов в функцию-член InitInstance моего приложения, и это устранило проблему.
Была похожая проблема только на днях. Скопировал элемент управления из одного диалогового ресурса в другой. Как это произошло, вы не можете просто скопировать элемент управления ActiveX из одного диалога в другой, как это делается с другими элементами управления MFC. Для элемента управления ActiveX rc-файл содержит раздел DLGINIT. Например, у меня есть форма с элементом управления IE WebBrowser:
IDD_ONLINE_REPORTVIEW_FORM DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
CONTROL "",IDC_EXPLORER1,"{8856F961-340A-11D0-A96B-00C04FD705A2}",WS_TABSTOP,7,61,299,77
END
и ниже в файле rc есть раздел DLGINIT:
IDD_ONLINE_REPORTVIEW_FORM DLGINIT
BEGIN
IDC_EXPLORER1, 0x376, 160, 0
0x0000, 0x0000, 0x004c, 0x0000, 0x2e68, 0x0000, 0x0ceb, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x004c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
0x0000, 0xd0e0, 0x0057, 0x3573, 0x11cf, 0x69ae, 0x0008, 0x2e2b, 0x6212,
0x0008, 0x0000, 0x0000, 0x0000, 0x004c, 0x0000, 0x1401, 0x0002, 0x0000,
0x0000, 0x00c0, 0x0000, 0x0000, 0x4600, 0x0080, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0
END
Откройте исходный файл rc и найдите свой контрольный идентификатор. Найдите раздел DLGINIT и скопируйте его в новый диалог.
В моем случае при вызове я указал неверный идентификатор диалога
BOOL Create(UINT nID, CWnd * pWnd);
так не удалось на DoDataExchange()
,
Вот еще одна ситуация, когда можно получить те же предупреждения об отладке (ошибка: нет управления обменом данными с ID dlgdata: строка 40):
например, если вы создаете экземпляр диалога CDialogExExample с помощью виртуальной функции CDialogExExample::Create(CONTROL_ID, ..), в то время как CONTROL_ID не совпадает с IDD_EXAMPLE(enum{ IDD = IDD_EXAMPLE};) в заголовочном файле CDialogExExample.... затем один мог добавить контроль всегда терпит неудачу.
Вот вдохновляющая ссылка от MSDN!
может быть полезным для кого-то:)
PS: эта ситуация, возможно, такая же, как и с ответом @Hank Chang
В моем случае у меня был диалог MFC, в котором размещается элемент управления.Net UI через ActiveX.
После отладки я обнаружил, что DoModal потерпел неудачу и вернул -1, а GetLastError дал 0.
После дня отладки проблема с несоответствием версий.Net Assemblies оказалась. Это приводит к ошибке инстанции управления OLE.
WinDBG выдержка:
(21b0.71cc): исключительная ситуация CLR - код e0434352 (первый шанс) Ошибка CoCreateInstance элемента управления OLE {EE3C4329-83A8-4DD8-A74C-680AC01AC593}.
Код результата: 0x80131040
Значение HRESULT 0x80131040 означает:
Определение манифеста обнаруженной сборки не соответствует ссылке на сборку.
Решение, которое я нашел после этой точной ошибки, состояло в том, чтобы проверить определение класса в заголовочном файле. Предполагая, что класс
Тогда в следующем коде
class CNewDlg : public CMyBaseDlg
{
DECLARE_DYNAMIC(CNewDlg)
public:
CNewDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CNewDlg();
// Dialog Data
enum { IDD = IDD_MYNEWDIALOGID };
проверьте строку:
enum { IDD = IDD_MYNEWDIALOGID };
убедившись, что у вас есть правильный идентификатор. Ошибка, которую вы получаете, может быть результатом копирования и вставки кода из другого заголовочного файла ранее созданного элемента управления / диалога без обновления этого идентификатора.
Это должно соответствовать определению диалога в вашем файле.rc. Например:
IDD_MYNEWDIALOGID DIALOGEX 0, 0, 445, 314