Adding an automation method to an existing MFC class - c++

I'm using Visual Studio 2019 and I have an MFC application with automation server support. There is an existing class with automation methods...
BEGIN_DISPATCH_MAP(CSizeToolDoc, CDocument)
//{{AFX_DISPATCH_MAP(CSizeToolDoc)
DISP_PROPERTY_EX(CSizeToolDoc, "ClientGetData", GetClientGetData, SetClientGetData, VT_BOOL)
DISP_FUNCTION(CSizeToolDoc, "SetActiveArea", SetActiveArea, VT_BOOL, VTS_VARIANT)
DISP_FUNCTION(CSizeToolDoc, "ShowWindow", ShowWindow, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CSizeToolDoc, "GetBoxes", GetBoxes, VT_VARIANT, VTS_NONE)
...
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
I simply need to add a new automation method but I can't locate any documentation describing how to do this and the Class Wizard doesn't seem to provide it either (if I try to add the code manually I'm worried it will break the app because I don't know all the files which would need to be updated).

Related

Can't use MFC CObject class in VS 2017 application

I need to use MFC Serialization mechanism to serialize objects of class Product:
class Product : public CObject
{
protected:
string name;
int expiring;
double price;
public:
Product();
~Product();
virtual void input_data();
virtual void print_data();
};
This is simple Windows Console Application. I got an error on CObject: not a class or struct name.
I tried to make MFC Console Application following the instruction in this comment: https://stackoverflow.com/a/50320168/6543699. Now I got a lot of errors (identifier not found or identifier not declared). The text of errors is in Russian, so I don't copy them here. This is how it looks:
I don't know anything about MFC using and can't find guide where it described clearly. My questions are:
1) Is it possible to use CObject in console application (non-MFC) and how?
2) If not, what should I do to be able to use MFC serialazation? Maybe include some headers or some components were just missing while installation?
You can just adjust a console app in a couple of steps to use MFC. First is to include afx.h, like:
#include <iostream>
#include <afx.h>
Then you will want to link with the MFC dynamic libraries.
Project Properties > Configuration Properties > Advanced > Use MFC
Select: Use MFC in a Shared DLL
It should now compile with CObject.
My note, I would not use MFC serialization, at the least use Boost Serialization I gave up using any serialization a long time ago because of the constant need to maintain versioning. I found it a night mare. Unless you see that your object structure will remain fairly static, I would recommend using XML to database your objects. It is a little more work to get going but way more often than not, you don't need to worry about versioning as you make changes.

SingleFileGenerator / Run Custom Tool does not run for new vs2017 project type

I have a SingleFileGenerator that works correctly for old-style Visual Studio C# projects, but not at all for the new-style VS2017 C# projects. I've added the new guid to registration attributes and to the packagedef, but still no joy. For reference, this code generator acts on xml files with the extension .3schema, which is an xml file of our own invention...
[Guid("0BC6C7FE-28F7-4A64-A8F8-714FFC0F8FB4")]
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("TrilogySchemaGenerator", "Trilogy C# Schema Generator", "5.9")]
[CodeGeneratorRegistration(typeof(TrilogySchemaGenerator), "Trilogy C# Schema Generator", "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}", GeneratesDesignTimeSource = true)]
[CodeGeneratorRegistration(typeof(TrilogySchemaGenerator), "Trilogy C# Schema Generator", vsContextGuids.vsContextGuidVCSProject, GeneratesDesignTimeSource = true)]
[ProvideObject(typeof(TrilogySchemaGenerator))]
public class TrilogySchemaGenerator : BaseCodeGeneratorWithValidation // base class implements IVsSingleFileGenerator
{
…
}
And the pkgdef:
[$RootKey$\Generators\{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}\.3schema]
#="TrilogySchemaGenerator"
[$RootKey$\Generators\{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\.3schema]
#="TrilogySchemaGenerator"
What step am I missing? Is there an additional registration required? Ideas of other things to try?
I've looked in the wrong place to solve my problem. It was not a problem with my SingleFileGenerator at all! But if you are building a SingleFileGenerator, please look to this answer for details of how to register it properly:
How to register "custom tool" with Visual Studio 2017 to make it work?
I used this excellent tool to convert my old projects to the new VS2017. I highly recommend:
https://www.nuget.org/packages/Project2015To2017.Migrate2017.Tool/
However, this tool does not deal well with custom build steps, of which my code generation is one. In my case, when I hand coded the custom build steps, I missed a reference to the noted line of XML:
<ItemGroup>
<XmlResource Include="Schema\T1TY2019.3schema">
--> <Generator>TrilogySchemaGenerator</Generator> <--
<LastGenOutput>T1TY2019.cs</LastGenOutput>
</XmlResource>
</ItemGroup>

Getting the replica ID of Access database using DAO

I've recently ported an MFC project form VS6 to VS2005. The VS6 project linked ddao35d.lib (DAO 3.5) which is no longer compatible with the 'new' MFC used in VS2005. To get around this I'm now including afxdao.h and changing my database classes from CdbDatabase to CDaoDatabase as recommended by other posts : -
http://www.experts-exchange.com/Programming/Languages/CPP/Q_22465486.html
However, there was a member function in CdbDatabase called GetReplicaID() which is no longer in CDaoDatabase. Does anyone know how to get the replica ID of an Access database using the CDaoDatabase class or otherwise?
Here are the important exerpts from that post: -
"As of Visual C++ .NET, the Visual C++ environment and wizards no longer support DAO (although the DAO classes are included and you can still use them). Microsoft recommends that you use OLE DB Templates or ODBC for new projects. You should only use DAO in maintaining existing applications.
The DAO MFC libraries, including ddao35d.lib, are part of PlatformSDK and are not compatible with the new MFC. You are expected to #include and it will link daouuid.lib."
...
"Adding the and daouuid.lib was the trick. PLUS: changing the declaration of CdbLastOLEError TO CDaoErrorInfo. The CdbLastOLEError is still in , but apparently no longer in the ddao35.lib. Changing to CDaoErrorInfo and linking with the addition of daouuid.lib has corrected the linker error."
I've found the solution.. You can access the DAO directly through the m_pDAODatabase member in the CDaoDatabase class. EG: -
CDaoDatabase dbDatabase;
COleVariant varReplicaID( "", VT_BSTRT );
HRESULT hr;
hr = dbDatabase.m_pDAODatabase->get_ReplicaID(& V_BSTR(&varReplicaID) );
For more details see
http://msdn.microsoft.com/en-us/library/1s0dx3s7.aspx

Problems accessing uccapi.dll COM interface C++

I'm working on a project involving the Microsoft Unified Communications Client API; uccapi.dll. I'm also using Codegear C++Builder 2010, not Visual Studio. After registering the dll with regsvr32 and importing it as type library into C++Builder 2010, uccapi_tlb- and uccapi_ocx-files were generated. When having imported these into my new project I'm trying to follow the msdn guideline for creating a Office Communicator Client able of signing into the Office Communication server.
In this regard I have two questions:
What is the correct way of accessing the com-interfaces made available through the ocx?
I've so far found several ways of creating access points, such as.
TCOMIUccPlatform plat;
plat = CoUccPlatform::Create();
and
IUccPlatformPtr im;
im = CreateComObject(CLSID_UccPlatform);
and
IUccPlatform* pIUccPlatform;
hr = CoCreateInstance(CLSID_UccPlatform,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IUccPlatform),
(void**)&pIUccPlatform);
and
IUccPlatformPtr pIPlat;
pIPlat.CreateInstance(__uuidof(IUccPlatform));
The three first seem to work well. The latter will give me an Assertion failed: intf!=0 error with 0×40000015 exception. Using any of the three top ones I can access methods and initialize the platform interface.
However when trying any of the same tactics to access any other interface, such as IUccContext, IUccUriManager or IUccUri, all of which have a clsid defined in the _tlb.h file, I either get a "class not registered" error in the first two cases, or a hresult failure in the third case. Which brings me to my next question.
Using ole-viewer all interfaces are registered as they should. Why wouldn't all co-creatable classes in the dll be registered when registering the dll? And what could be the reasons why don't they act similarly?
Edit1 from UCCAPILib_tlb.h:
//
// COCLASS DEFAULT INTERFACE CREATOR
// CoClass : UccPlatform
// Interface: TCOMIUccPlatform
//
typedef TCoClassCreatorT<TCOMIUccPlatform, IUccPlatform, &CLSID_UccPlatform, &IID_IUccPlatform> CoUccPlatform;
//
// COCLASS DEFAULT INTERFACE CREATOR
// CoClass : UccUriManager
// Interface: TCOMIUccUriManager
//
typedef TCoClassCreatorT<TCOMIUccUriManager, IUccUriManager, &CLSID_UccUriManager, &IID_IUccUriManager> CoUccUriManager;
This issue is already being discussed in detail in the Embarcadero forums.

regenerating connection point methods

I've created a connection point interface _IPlayerEvents.
I've added a couple of methods
OnConnect()
OnDisconnect()
I've built the project, and VS2008 has generated code in the CProxy_IPlayerEvents class:
HRESULT Fire_OnConnect(){...}
HRESULT Fire_OnDisconnect() {...}
Now I've added a further method to the _IPlayerEvents interface
OnMessage([out, retval]BSTR* pbstrMessage)
When I build, no code is added to the CProxy_IPlayerEvents class for the OnMessage function - I'd expected that VS2008 would generate:
HRESULT Fire_OnMessage(BSTR* pbstrMessage){...}
I'd prefer to avoid having to update the CProxy_IPlayerEvents manually if I could.
How can I force VS2008 to regenerate the CProxy_IPlayerEvents class?
I found an answer!
Open Class View in VS2008, right-click your COM object and from its context menu, select Add -> Add Connection Point... Move the source interface from the list on the left over to the right, then click Finish.
This will generate or regenerate proxy class when you next build your project.
This step is crucial - and a real pain if you haven't done connection points in a while!