У меня есть устаревшее приложение, которое было построено с VC ++ 6.0 и использует элемент управления OCX. Я обновил приложение для сборки с VS2013. Первоначально я получил его для сборки и запуска успешно, но когда я попытался восстановить файлы ocx.h и ocx.cpp с помощью мастера классов
В сгенерированных выходных файлах h и cpp отсутствуют все методы Attribute
// Attributes
public:
// Operations
public:
void ClearTablet()
{ . . .
Я также попытался дать Class Wizard файл OCX напрямую, а не использовать реестр, но у меня были те же результаты. Я прибегнул к ручному редактированию файлов ocx.h и ocx.cpp, чтобы добавить недостающие методы атрибутов, но не понимаю, почему Class Wizard их не генерирует. Я подумал вернуться к версии VC ++ 6.0, чтобы посмотреть, будет ли он правильно генерировать файлы, но мне неясно, как использовать 6.0 для генерации файлов ocx.h и ocx.cpp, поскольку те же опции меню недоступны.
Добавлено 3-5-2018 в ответ на комментарий Ганса
Вот как выглядел один из отсутствующих атрибутов в оригинальном проекте OCX
===== FILE: SigPlusCtl.h =========
class CSigPlusCtrl : public COleControl
{
DECLARE_DYNCREATE(CSigPlusCtrl)
DECLARE_INTERFACE_MAP()
. . .
// Dispatch maps
//{{AFX_DISPATCH(CSigPlusCtrl)
afx_msg short GetImageFileFormat();
afx_msg void SetImageFileFormat(short nNewValue);
. . .
===== FILE: SigPlusCtl.cpp =========
// Dispatch map
BEGIN_DISPATCH_MAP(CSigPlusCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CSigPlusCtrl)
DISP_PROPERTY_EX(CSigPlusCtrl, "ImageFileFormat", GetImageFileFormat, SetImageFileFormat, VT_I2)
. . .
===== FILE: SigPlusImage.cpp ====
short CSigPlusCtrl::GetImageFileFormat()
{
return ImageFileFormat;
}
void CSigPlusCtrl::SetImageFileFormat( short nNewValue)
{
if ( ( nNewValue >= 0 ) && ( nNewValue <= 11 ) )
{
ImageFileFormat = nNewValue;
}
SetModifiedFlag();
}
. . .
И вот что мне пришлось добавить в сгенерированные файлы .h и .cpp в проекте контейнера, чтобы использовать этот отсутствующий атрибут. Я скопировал этот код из исходных файлов OCX .h и .cpp в приложении-контейнере, прежде чем пытался восстановить их с помощью VS2013. Поскольку я не смог восстановить эти файлы с помощью VC ++ 6.0 (см. Мой первый комментарий ниже), я не знаю, был ли этот скопированный код изначально создан мастером VC ++ 6.0 или же этот редактор редактировал также эти файлы заголовков.
======== FILE: sigplus ================
// Attributes
public:
short GetImageFileFormat();
void SetImageFileFormat(short);
. . .
======== FILE: sigplus.cpp =============
// CSigPlus properties
short CSigPlus::GetImageFileFormat()
{
short result;
GetProperty(0x1, VT_I2, (void*)&result);
return result;
}
void CSigPlus::SetImageFileFormat(short propVal)
{
SetProperty(0x1, VT_I2, propVal);
}
. . .
Я не знаю, имеет ли это значение для мастера классов, но расположение методов несколько нетрадиционно в том смысле, что реализации методов элемента управления OCX разбросаны по нескольким файлам .cpp, а не находятся в файле SigPlusCtl.cpp.
Добавлено 3-20-18
После комментария Ганса 3-20 я попытался открыть файл ocx в Visual Studio 2013, чтобы проверить TYPELIB. Но когда я раскрываю папку TYPELIB, она показывает только дамп HEX.
Рассматривая интерфейс OCX TypeLib, используя OLE / COM Object Viewer Я вижу отсутствующие свойства, перечисленные в разделе «Свойства», но не вижу явных объявлений методов Get и Set. Например, есть свойство ImageFileFormat но нет GetImageFileFormat а также SetImageFileFormat. В источнике для элемента управления OCX есть явные определения этих методов Get / Set.
SigPlusCtl.cpp: DISP_PROPERTY_EX(CSigPlusCtrl, "ImageFileFormat", GetImageFileFormat, SetImageFileFormat, VT_I2)
SigPlusCtl.h: afx_msg short GetImageFileFormat();
SigPlusImage.cpp: short CSigPlusCtrl::GetImageFileFormat()
SigPlus.map: 0001:00012ed0 ?GetImageFileFormat@CSigPlusCtrl@@IAEFXZ 10013ed0 f SigPlusImage.obj
Должен ли я увидеть явный листинг в OLE Viewer для методов Get и Set под методы:?
dispinterface _DSigPlus {
properties:
[id(0x00000001)
]
short ImageFileFormat;
[id(0x00000002)
]
short ImageXSize;
[id(0x00000003)
]
short ImageYSize;
[id(0x00000004)
]
o o o
]
BSTR TabletGraphicFile;
[id(0x00000042)
]
long TabletTimer;
[id(0xfffffe0b), bindable, requestedit
]
OLE_COLOR BackColor;
[id(0xfffffdff), bindable, requestedit
]
OLE_COLOR ForeColor;
methods:
[id(0x00000043)]
void ClearTablet();
[id(0x00000044)]
o o o
Добавлено 3-20-18 17: 00PDT
Я посмотрел вверх #Импортировать упоминается @HansPassart в комментарии. Эта директива Microsoft является альтернативой использованию Class Wizard. Я удалил из проекта созданные Class Wizard файлы sigplus.h и sigplus.cpp и добавил
#import "file:SigPlus.tlb"
в основной файл заголовка. Когда скомпилировал #Импортировать директива генерирует файлы sigplus.TLH и sigplus.TLI (заголовок и реализация), а затем включает в себя файл sigplus.TLH, который затем явно включает файл TLI. После компиляции #import генерирует эти два файла, а затем включает сгенерированный «Release / sigplus.tlh». Эти сгенерированные файлы содержат отсутствующие методы Get / Set, однако они не компилируются. Файл TLH использует другое имя для класса OCX _DSigPlus и помещает его в пространство имен. Но даже после учета этих различий объявление класса в файле TLH использует IDispatch в качестве родительского класса, где Class Wizard использовал CWnd, и при компиляции существуют следующие неразрешенные чистые виртуальные методы, исходящие от IUnknown, который является родителем IDispatch.
c:\demoocx\DemoOCXDlg.h(24): error C2259: 'SIGPLUSLib::_DSigPlus' : cannot instantiate abstract class
due to following members:
'HRESULT IUnknown::QueryInterface(const IID &,void **)' : is abstract
C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwnbase.h(114) : see declaration of 'IUnknown::QueryInterface'
'ULONG IUnknown::AddRef(void)' : is abstract
C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwnbase.h(118) : see declaration of 'IUnknown::AddRef'
'ULONG IUnknown::Release(void)' : is abstract
C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwnbase.h(120) : see declaration of 'IUnknown::Release'
'HRESULT IDispatch::GetTypeInfoCount(UINT *)' : is abstract
c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2187) : see declaration of 'IDispatch::GetTypeInfoCount'
'HRESULT IDispatch::GetTypeInfo(UINT,LCID,ITypeInfo **)' : is abstract
c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2190) : see declaration of 'IDispatch::GetTypeInfo'
'HRESULT IDispatch::GetIDsOfNames(const IID &,LPOLESTR *,UINT,LCID,DISPID *)' : is abstract
c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2195) : see declaration of 'IDispatch::GetIDsOfNames'
'HRESULT IDispatch::Invoke(DISPID,const IID &,LCID,WORD,DISPPARAMS *,VARIANT *,EXCEPINFO *,UINT *)' : is abstract
c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2202) : see declaration of 'IDispatch::Invoke'
Задача ещё не решена.
Других решений пока нет …