HOWTO: Use OLE Automation from a C Application Rather Than C++ID: Q181473
|
If you need to program in C, rather than C++, OLE Automation can be difficult, because the Component Object Model (COM), the building blocks of OLE, was designed around the binary layout of a C++ class. The header files included by WINDOWS.H, however, have built-in support for C compilations; therefore, you can mimic the behavior of a C++ object and make OLE Automation calls. This article describes how to build a Win32 console application, using C, that starts up Microsoft Excel and makes it visible via OLE Automation.
Use the following method:
#include <stdio.h>
#include <windows.h>
void main(void) {
IDispatch *pDisp; // Main IDispatch pointer.
unsigned short *ucPtr; // Temporary variable to hold names.
DISPID dispID; // Temporary variable to hold DISPIDs.
CLSID clsid; // Holds CLSID of server after CLSIDFromProgID.
HRESULT hr; // General error/result holder.
char buf[8192]; // Generic buffer for output.
// IDispatch::Invoke() parameters...
DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
VARIANT parm1;
DISPID dispidNamed = DISPID_PROPERTYPUT;
// Initialize OLE Libraries.
OleInitialize(NULL);
{
// Get CLSID for Excel.Application from registry.
hr = CLSIDFromProgID(L"Excel.Application", &clsid);
if(FAILED(hr)) {
MessageBox(NULL, "Excel not registered.", "Error",
MB_SETFOREGROUND);
return;
}
// Start Excel97 and get its IDispatch pointer.
hr = CoCreateInstance(&clsid, NULL, CLSCTX_LOCAL_SERVER,
&IID_IDispatch, (void **)&pDisp);
if(FAILED(hr)) {
MessageBox(NULL, "Couldn't start Excel.", "Error",
MB_SETFOREGROUND);
return;
}
// Get the 'visible' property's DISPID.
ucPtr = L"Visible";
pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, &ucPtr, 1,
LOCALE_USER_DEFAULT, &dispID);
sprintf(buf, "DISPID for 'Visible' property = 0x%08lx",
dispID);
MessageBox(NULL, buf, "Debug Notice", MB_SETFOREGROUND);
// Initiate parameters to set visible property to true.
VariantInit(&parm1);
parm1.vt = VT_I4;
parm1.lVal = 1; // true
// One argument.
dispParams.cArgs = 1;
dispParams.rgvarg = &parm1;
// Handle special-case for property-puts!
dispParams.cNamedArgs = 1;
dispParams.rgdispidNamedArgs = &dispidNamed;
// Set 'visible' property to true.
hr = pDisp->lpVtbl->Invoke(pDisp,
dispID, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT | DISPATCH_METHOD,
&dispParams, NULL, NULL, NULL
);
if(FAILED(hr)) {
sprintf(buf, "IDispatch::Invoke() failed with %08lx", hr);
MessageBox(NULL, buf, "Debug Notice", MB_SETFOREGROUND);
}
// All done.
MessageBox(NULL, "done.", "Notice", MB_SETFOREGROUND);
}
// Uninitialize OLE Libraries.
OleUninitialize();
}
For more general information regarding OLE, COM, and Automation, consult
the book "Inside OLE" by Kraig Brockschmidt (Microsoft Press).
For more information about IDispatch, consult the Microsoft Visual C++
online help.
For more information about COM, OLE, and automating Microsoft Excel using
Microsoft Visual C++, see Chapters 23-27 of the book "Inside Visual C++" by
David J. Kruglinski (Microsoft Press).
(c) Microsoft Corporation 1998, All Rights Reserved. Contributions by Joe Crump, Microsoft Corporation.
Keywords : kbcode kbVC400 kbVC500 kbVC600
Version : WINDOWS:97; WINNT:4.0,5.0
Platform : WINDOWS winnt
Issue type : kbhowto
Last Reviewed: July 23, 1999