Given that CApplication
is a wrapper class generated by Visual Studio to interact with CATIA's COM objects, and it is derived from COleDispatchDriver
, you do not need to use __uuidof(CApplication)
directly. Instead, you should use the CApplication
class as it is designed, leveraging the COleDispatchDriver
functionalities provided by MFC (Microsoft Foundation Classes).
Understanding the COleDispatchDriver
Wrapper
COleDispatchDriver
is a class provided by MFC to simplify the use of COM IDispatch
interfaces, which are common in Automation objects like those exposed by CATIA. The COleDispatchDriver
class encapsulates the complexities of calling methods and accessing properties on IDispatch
-based COM objects.
When you use class CApplication : public COleDispatchDriver
, it provides a thin wrapper around the CATIA COM interface, allowing you to call methods and properties directly without dealing with low-level COM details like QueryInterface
or __uuidof
.
Correct Way to Use CApplication
with MFC
Here’s how to correctly instantiate and use the CApplication
class derived from COleDispatchDriver
:
Step-by-Step Solution
- Initialize COM and Obtain the CATIA Application Object:
You should first initialize COM and use GetActiveObject
to obtain the running instance of the CATIA application.
- Attach the COM Object to
CApplication
:
Instead of using QueryInterface
, use the AttachDispatch
method of COleDispatchDriver
to bind the IDispatch
pointer to the CApplication
object.
Updated Code Example
Here’s the correct way to use CApplication
:
cpp
#include <afxdisp.h> // Required for MFC OLE/COM support
#include <iostream>
#include <windows.h>
#include "CApplication.h" // Include the generated CApplication class
int main() {
// Initialize COM
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr)) {
std::cerr << "Failed to initialize COM." << std::endl;
return -1;
}
CLSID clsid;
hr = CLSIDFromProgID(L"CATIA.Application", &clsid);
if (SUCCEEDED(hr)) {
IDispatch* pDisp = nullptr;
hr = GetActiveObject(clsid, NULL, (IUnknown**)&pDisp); // Obtain the running CATIA instance
if (SUCCEEDED(hr) && pDisp != nullptr) {
CApplication q_pCatiaApp; // Create an instance of CApplication
q_pCatiaApp.AttachDispatch(pDisp); // Attach the IDispatch pointer to CApplication
// Now you can interact with the CATIA application through q_pCatiaApp
std::cout << "Connected to CATIA successfully." << std::endl;
// Example: Get the number of open documents
CDocuments documents = q_pCatiaApp.get_Documents();
long docCount = documents.GetCount();
std::cout << "Number of open documents in CATIA: " << docCount << std::endl;
// Detach and release the dispatch interface when done
q_pCatiaApp.ReleaseDispatch();
pDisp->Release(); // Release IDispatch when done
} else {
std::cerr << "Failed to connect to CATIA." << std::endl;
}
} else {
std::cerr << "Failed to get CLSID for CATIA.Application." << std::endl;
}
CoUninitialize(); // Uninitialize COM
return 0;
}
cpp
Explanation of Key Changes
-
Use
AttachDispatch
Method:- The
AttachDispatch
method fromCOleDispatchDriver
is used to attach theIDispatch
pointer obtained fromGetActiveObject
to yourCApplication
instance. This method binds the COM object to the MFC wrapper so that you can use the generated methods and properties.
- The
-
Do Not Use
QueryInterface
with__uuidof
:- Since
CApplication
is derived fromCOleDispatchDriver
and not a direct COM interface,__uuidof
is not necessary. TheCOleDispatchDriver
mechanism abstracts away the need for directly querying interfaces.
- Since
-
Release COM Objects Properly:
- Use
ReleaseDispatch()
to detach and release theIDispatch
pointer before callingRelease()
on the originalIDispatch
pointer (pDisp
).
- Use
Additional Tips
-
MFC Project Settings: Make sure your project is set up to use MFC (Microsoft Foundation Classes). If you are using an MFC application, this setup should already be configured.
-
Error Handling: Always check
HRESULT
values to handle any errors properly. UseSUCCEEDED(hr)
andFAILED(hr)
macros to determine success or failure.
Conclusion
By using AttachDispatch
with the CApplication
class derived from COleDispatchDriver
, you correctly bind the CATIA COM object to the generated MFC wrapper class, avoiding the need for direct QueryInterface
calls. This simplifies the use of COM objects and leverages the power of MFC to handle COM interactions more intuitively.