How to create an ATL class that implements CDialogImpl and IPreviewFrameHandler - c++

I'm trying to create a dialog that hosts a file preview handler. I started by creating an ATL dialog (through the Visual Studio menu), which derives from CDialogImpl, so that part was pretty straightforward.
But I've now learned that hosting a preview handler involves implementing IPreviewHandlerFrame. So I guess I have to derive from that, implement its methods, and implement IUnknown as well. And then I guess that the dialog needs to be created via CoCreateInstance? (Not sure about that part.)
So I'm not sure if I should go back and start over, instead creating an ATL Object that derives from CDialogImpl and IPreviewHandlerFrame. That would involve all of the ATL registration and everything, and I'm not sure if that's necessary . Or is it better just to add the IUnknown methods? But even so, how would the class be instantiated? I'm not sure I want to interfere in the ref-counting or anything like that.
Thanks for any guidance on how to do this.
Or maybe another approach would be to implement IPreviewHandlerFrame in its own ATL class, and then instantiate it in the CDialogImpl?

Related

Deleting / Editing ATL COM DLL properties / methods

I have created a COM ATL DLL in VS2012.
Adding events and properties is very easy.
However, I see no easy way to edit or delete an event or a property.
VS2012 automatically creates a lot of code for the event or property when I use the Add Wizard, and I am not sure if I should really delete or change this automatically created code manually when I made a mistake and want to replace or delete something.
Is there a way to edit and delete them in a clean way?
Perhaps there is a property / event manager somewhere in VS2012, but I did not find it.
Thank you!
You edit declaration of the methods/properties of your interest on IDL, and then the project stops building until you respectively fix it by reflecting changes on your C++ implementation - that's it.
IDL changes along with implementation updated respectively builds you updated DLL.
Be aware that applications which are already built against earlier method/property set might be in trouble after the update. Related earlier questions you might be interested in (you might, however be not - which I sense is the case at the moment, if your question is about updates while you are developing, and not updates on released module):
COM: If I change the parent of an Interface do I need to create a new Interface?
Would adding a new function to the existing COM interface break its binary compatibility?
Why is it necessary to add new events to the *end* of an IDL interface?

Creating a DialogBar with MFC with my own controls

I'm turning mad with a little problem with Visual Studio 2008 and MFC. I'm working on a project actually and I'm trying to create an SDI Application. Right, now I want to add a dockable DialogBar. Well, the first time I added it with the resource view, I could create the bar without problems.
But... I want to add some controls like a couple of ListBox, buttons and so on. The program doesn't allows me to create member variables for these controls. The option appears in grey.
Searching a little, I found that it's mandatory to create a new class derived from CDialogBar and "enhance" it with the Message handler and so on. I've been reading some tutorials and it didn't work for me.
Can you please help me? I'm starting to get nervous, the use of dialogbars is mandatory in my design and I've never implemented them before.
Thank you very much, and sorry for my poor english.
You can add a control member variable by hand instead of using the wizard. All it takes is a call to DDX_Control in the dialog bar's DoDataExchange function.
But CDialogBar-derived classes do not handle control clicks. The CDialogBar class forwards all of those messages to the dialog bar's parent window. So be prepared to add the message handlers to the parent (usually CMainFrame).
For learning purposes you might try creating your dialog bar as a CDialog first, to see the proper code lines and message map entries supplied by the wizard. Then you can copy/move these details as appropriate into your actual code project.

Convert simple MFC CView/CDocument/CSingleDocTemplate app to ActiveX control

I have a fairly simple MFC app that just defines its own sub-classes of CDocument, CView and CFrameWnd and uses them via a CSingleDocTemplate to display the read-only contents of the document in a tree on the view. All very standard MFC MVC.
I now need to convert this app so that it works as an ActiveX control that I can then embed it within a larger application.
How should I go about this?
Is it possible to use the COleControl sub-class in place of the CFrameWnd sub-class in the CSingleDocTemplate? Or do I need to place the CFrameWnd sub-class within the COleControl some how?
Failing that, how can I use my existing CDocument\CView sub-classes within an ActiveX control?
Answering my own question: I found quite a few references to an old article about this, which used to be at http://www.microsoft.com/mind/0497/mfc.asp but has long since disappeared. :(
Fortunately though, the Wayback Machine still has a complete copy of it:
"Designing ActiveX Components with the MFC Document/View Model" by Steve Zimmerman, Microsoft Interactive Developer (April 1997)
Steve presents source code for two new classes:
CActiveXDocTemplate : a sub-class of CSingleDocTemplate
CActiveXDocControl : a sub-class of COleControl
which allowed me to use my existing CView and CDocument sub-classes in an ActiveX control.
(Thanks Steve wherever you are now)

Unable to get ATL Connection Points working

I am trying to create a COM component using ATL, and I'd like to raise events for my VB client. I've found numerous tutorials, all of which seem to vary in details, and none of them appear to generate a working solution. Here is what I am doing:
(Using Visual Studio 2008):
Create a new ATL DLL Project. I've called it ATLEventTest.
Class View: Right clicked on ATLEventTest, Added a new ATL Simple Object class.
I called this MyObject, which generated CMyObject, IMyObject, etc...
This object was created with:
a) Apartment Threading
b) Aggregation
c) Dual Interface
d) ISupportErrorInfo
e) Connection points
Right clicked on CProxy_IMyObjectEvents<T>, clicked 'Add Function'
Function is of void return type, named someEvent, and takes an int testParam.
Rebuild.
(At this point, I should be able to see an 'Implement Connection Point' somewhere. I do not...)
Right clicked on CMyObject. 'Add Connection Point'
Moved '_IMyObjectEvents' over into the list.
Did a code search in my solution. Can't find someEvent anywhere!
Added the someEvent function again. Now, it is found in ATLEventTest_i.h
Should be able to call fire_someEvent(...) in my code, but can't.
This has been driving me insane trying to get this to work. If anyone can see what I'm doing wrong, I'd appreciate any corrections, tips, hacks, etc.
At this point, I'm tempted to say screw the wizards, and just try to modify the c++ and idl directly, but I've got a feeling that might not fair much better :(
Try using the method outlined at this location:
Adding an Event (ATL) # MSDN
With the example names you have given above, in your MyObject.idl file, you should see a declaration for your outbound even under the section for dispinterface _IMyObjectEvents. Since you right clicked on CProxy_IMyObjectEvents<T> and not on _IMyObjectEvents under the library, your IDL is probably missing the definition. The auto-generated file _IMyObjectEvents_CP.h file should be present in your project header files and should contain the Fire_someEvent() method as a result of adding the method correctly. If not, you may find that it just created a method named someEvent() instead.
Here is an outline you can try in a test project.
Create a new ATL DLL Project. I've called it ATLEventTest1.
Build Project.
Class View: Right clicked on ATLEventTest1, Add a new ATL Simple Object class. Call it MyObject.
Create the definition with a) Apartment Threading b) Dual Interface c) Connection points and whatever else you need.
Rebuild Project.
Class View: Locate the ATLEventTest1Lib library, right click on _MyObjectEvents, and "Add Method".
Method is of void return type, named someEvent, and takes an int testParam with parameter attribute [in].
You should see "[in] int testParam" as a result of adding the parameter.
On the IDL Attributes tab, change the id if necessary. Click Finish.
Class View: Right click on CMyObject, go to Add... , go to Implement Connection Point.
Select _IMyObjectEvents and click ">" to move it to the implemented connection points list. Click Finish.
Rebuild.
Now, in your CMyObject class, you should be able to call Fire_someEvent(). You will see a new method in your ATLEventTest1.idl file under the dispinterface _IMyObjectEvents; the header file _IMyObjectEvents_CP.h file will be created and will create the broadcast code for Fire_someEvent().
Does you class have an implementation of IProvideClassInfo/IProvideClassInfo2? If I recall for non-control objects, VB requires this to locate the event source interface.
Try this:
public IProvideClassInfo2Impl<&CLSID_MyClass NULL, &LIBID_ATLEventTest, 1, 0>,
and then in the interface map
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
Maybe you have a problem with apartment threading.
Do you write console application on VB?
It requires a classic message pump to work properly (for example classic windows application).
Try different apartment mode on your COM object (MTA).
Ok. So after a new system rebuild, I have installed both Visual Studio 2005 and Visual Studio 2008. I can get this working in 2005 perfectly. Still can't get the thing working in 2008. Looks like I'm just going to have to work on VS2005 for my ATL stuff...
Thanks again to all who helped.
I was having the same issue. Kept reading the MSDN documents and searched online. Finally, I figured it out.
The main thing that the wizard isn't doing is putting the declaration in the IDL file. I manually added it, and in my class, theres a "Fire_".
Hope this helps you.
I was able to fix similar issue by deleting all _I***Events references from control's .h file

How can I place a MFC CFormView inside a CDockablePane?

How can I place a MFC CFormView inside a CDockablePane which was introduced in the VS 2008 MFC Feature Pack?
Check the BCGSoft Samples for doing this with a cview. The class names are a little different but its more or less the same stuff since they provided CDockablePane to Microsoft.
I couldn't find such samples in MFC Feature Pack samples.
All projects containing CFormView are :
TasksPane
TabControl
TabbedView
StatusBarDemo
SetPaneSize
MenuSubSet
But in any of the projects, CFormView is not embedded in CDockablePane.
There is a sample of the feature pack that does this.
However, what I do is the following: I made a CDialog-derived class that I put in the DockablePane. Then I make a CFormView-derived class and make an instance of that a member variable of the dockable pane. Every function that I'm interested in (most likely UpdateView() or whatever it's called), I forward to the CDialog-derived class. That way I can sidestep the difficulties of shoehorning the doc/view structure into my application and still get the benefits.
Actually there are a few ways of doing this.
If you derive your own CFameWnd class and then put an instance of that class in the CDockable pane you now can put whatever type of framework that you want inside of that CFrameWnd derived class.
The trick is to make sure that you are doing the creation in the correct order. If you try to call it to early then your internal views will never be created.
Probably this cab be a clue.
http://www.codeproject.com/KB/toolbars/sizecbar.aspx
Although it doesn't use CDockablePane, concept behind it is same.
I didn't try CDockablePane and CFormView work like the one explained in the page yet, but by taking a glance at it, I feel that things are similar.