MFC Ocx: Using ActiveX Controls in Nondialog Windows

来源:互联网 发布:歌手知乎 编辑:程序博客网 时间:2024/05/03 20:54
Using ActiveX Controls in Nondialog Windows
MFC and ClassWizard make it wonderfully easy to use ActiveX controls in dialogs, but what about nondialog windows? It turns out that MFC allows any CWnd object to host ActiveX controls. You can create ActiveX controls just about anywhere in an MFC application, but outside of dialog windows, you have to do some manual coding to make it happen.

Here's how to add the MFC calendar control to a view:

Insert the control into the project. Name the wrapper class CCalendar.
Add a CCalendar member variable named m_ctlCalendar to the view.
Add the following statement to the view's OnCreate handler:

m_ctlCalendar.Create (NULL, WS_VISIBLE,
   CRect (0, 0, 400, 300), this, IDC_CALENDAR);

When the view is created, the calendar control will be created in the view's upper left corner and assigned the control ID IDC_CALENDAR. Most of the work is done by CCalendar::Create, which calls the CreateControl function CCalendar inherits from CWnd. CWnd::CreateControl indirectly calls COleControlSite::CreateControl, which creates an ActiveX control and wires it up to its container.

So far, so good. But what if you want the view to process control events, too? This is where it gets tricky. ClassWizard will add event handlers to dialogs, but not to nondialogs. So you code the event sink map by hand. That wouldn't be too bad if it weren't for the fact that an event's parameter list has to be coded into the ON_EVENT statement in the form of VTS flags. Some programmers get around this by doing the following:

Add a dummy dialog to the application.
Insert the ActiveX control into the dialog.
Use ClassWizard to write event handlers into the dialog.
Copy the event sink map from the dialog to the view.
Delete the dummy dialog.

I didn't say it was pretty. But it works. If you use this technique, don't forget to copy the DECLARE_EVENTSINK_MAP statement from the dialog's header file to the view's header file. DECLARE_EVENTSINK_MAP declares an event sink map just as DECLARE_MESSAGE_MAP declares a message map.

All this assumes, of course, that you checked AppWizard's ActiveX Controls box when you created the project. If you didn't, you can add container support to the application after the fact by adding an

AfxEnableControlContainer ();

statement to InitInstance.
原创粉丝点击