HOWTO: Use Microsoft Word's CAPI Messaging Interface (CMI)ID: Q190057
|
As an alternative to automation using COM, you can use the CAPI Messaging Interface (CMI) to control Microsoft Word. CMI uses the same structures and functions as a Microsoft Word DLL add-in (WLL), but allows cross-process and asynchronous calls. To use CMI, you should have a copy of the latest Microsoft Word Developer's Kit (ISBN: 1-55615-880-7), and a 32-bit version of Microsoft Visual C++. This article lists the steps you need to take to build a CMI project, and demonstrates using CMI.
Q183758 WD: Build a Microsoft Word Add-in (WLL) Using Visual C++
#include "capilib.h"
#include "wdcmds.h"
#include "wdfid.h"
extern "C" {
_declspec(dllimport) short WINAPI cmiCommandDispatch(short
CommandID, short DlgOptions, short cArgs, LPWDOPR lpwdoprArgs,
LPWDOPR lpwdoprReturn);
}
// Start Word.
STARTUPINFO si;
::ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
if(::CreateProcess(
NULL, "c:/progra~1/micros~1/office/winword.exe", NULL, NULL,
FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
// Wait for Word to become Idle.
WaitForInputIdle(pi.hProcess, 3000);
}
else {
::MessageBeep(0);
::MessageBox(
NULL, "CreateProcess() failed.\nCheck Path for WinWord.Exe.",
"Error", MB_SETFOREGROUND);
return;
}
// Put your window back in the foreground.
SetForegroundWindow();
WCB wcb; // Your local WCB structure.
int err; // Error/result.
// Call wdDrawLine - Creates a graphical line object in the document.
InitWCB(&wcb, 0, 0, 0);
err = cmiCommandDispatch(
wdDrawLine, 0, wcb.cArgs, wcb.wdoprArgs,
(LPWDOPR)&wcb.wdoprReturn);
if(err) { ShowCMIError(err); return; }
// Call wdFormatDrawingObject - Changes shape & position of the line.
InitWCB(&wcb, 0, 0, 0);
AddShortDlgField(&wcb, 40, fidHorizontalPos, INPUT);
AddShortDlgField(&wcb, 40, fidVerticalPos, INPUT);
AddShortDlgField(&wcb, 180, fidHeight, INPUT);
AddShortDlgField(&wcb, 80, fidWidth, INPUT);
err = cmiCommandDispatch(
wdFormatDrawingObject, 2, wcb.cArgs, wcb.wdoprArgs,
(LPWDOPR)&wcb.wdoprReturn);
if(err) { ShowCMIError(err); return; }
// *** Draw another line with opposite height & width.
// Call wdDrawLine - Creates a graphical line object in the document.
InitWCB(&wcb, 0, 0, 0);
err = cmiCommandDispatch(
wdDrawLine, 0, wcb.cArgs, wcb.wdoprArgs,
(LPWDOPR)&wcb.wdoprReturn);
if(err) { ShowCMIError(err); return; }
// Call wdFormatDrawingObject - Changes shape & position of the line.
InitWCB(&wcb, 0, 0, 0);
AddShortDlgField(&wcb, 40, fidHorizontalPos, INPUT);
AddShortDlgField(&wcb, 40, fidVerticalPos, INPUT);
AddShortDlgField(&wcb, 80, fidHeight, INPUT);
AddShortDlgField(&wcb, 180, fidWidth, INPUT);
err = cmiCommandDispatch(
wdFormatDrawingObject, 2, wcb.cArgs, wcb.wdoprArgs,
(LPWDOPR)&wcb.wdoprReturn);
if(err) { ShowCMIError(err); return; }
// Sleep for a little bit so user can see what happened.
::Sleep(1000);
::MessageBox(NULL, "Cmi-Test: Click me to continue...",
"Notice", MB_SETFOREGROUND);
// Close Word.
::PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0);
// Wait for Word to exit.
::WaitForSingleObject(pi.hProcess, 2000);
// Release handles to the process (these come from CreateProcess).
// Note: The process will not close later, unless these are closed.
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
// Done.
SetForegroundWindow();
::MessageBox(NULL, "Cmi-Test: All Done.", "Notice",
MB_SETFOREGROUND);
void ShowCMIError(int err)
{
static char txt[1024];
char *msg;
// Check for general CMI errors.
if((err >= 5001) && (err <= 5034)) {
msg = "General CAPI error.\n"
"More information: This code is defined and described in
WdError.h\n"
"Suggestion: Lookup error in WdError.h, and modify
parameters to cmiCommandDispatch().";
}
// Check for Win32Cmi.dll errors.
else {
switch (err) {
case 0: msg = "Success"; break;
case -1: msg = "Microsoft Word is invisible, not running, or"
" hasn't completly loaded.\n"
"Suggestion: Start Microsoft Word before"
"executing.";
break;
case -2: msg = "Win32Cmi.dll's shared memory block not big"
" enough.\n"
"More Information: The default size is 131072.\n"
"Suggestion: Recompile the win32cmi project with"
" a bigger buffer.";
break;
case -3: msg = "Cannot obtain Microsoft Word's thread Id.";
break;
case -4: msg = "Win32Cmi.dll could not install its
WH_GETMESSAGE"
" hook.";
break;
case -5: msg = "The current instance of Microsoft Word was not"
" the original instance hooked by Win32Cmi.dll.\n"
"More Information: Win32Cmi.dll's hooked thread"
" id doesn't match the current Microsoft Word\n"
" thread id. Win32Cmi.dll is only designed to"
" work with a specific instance of Microsoft"
" Word.\n"
"Suggestion 1: Use CMI with only one Microsoft"
" Word instance.\n"
"Suggestion 2: Use OLE Automation as an"
" alternative to CMI.\n"
"Suggestion 3: Modify the Win32Cmi project"
" yourself to support multiple instances of"
" Microsoft Word.";
break;
case -6: msg = "Win32Cmi.dll's call to CreateEvent() failed.";
break;
case -7: msg = "Win32Cmi.dll's call to CreateFileMapping()"
" failed.";
break;
case -8: msg = "Win32Cmi.dll's call to MapViewOfFile()
failed.";
break;
case -9: msg = "Timeout (default=60s).
Win32Cmi.dll's call to"
" WaitForSingleObject() did not return "
"WAIT_OBJECT_0.\n"
"Suggestion 1: Try calling on a separate "
" thread.\n"
"Suggestion 2: Increase time-out value if "
"applicable.\n"
"Suggestion 3: Win32Cmi uses hooks for its "
"implementation. If you also use hooks, or \n"
" synchronization objects, watch out for deadlock"
" scenarios.";
break;
default: msg = "Unknown error.\n"
"More Information: Error was not a CMI error.\n"
"Suggestion: Check for error and description in "
"WdError.h";
break;
}
}
sprintf(txt, "CMI Error %d\n%s", err, msg);
::MessageBox(NULL, txt, "CMI Error", MB_SETFOREGROUND);
}
Microsoft Word Developer's Kit: ISBN:1-55615-880-7
For additional information, please see the following
article(s) in the Microsoft Knowledge Base:
Q183165 What Do the cmiCommandDispatch() Errors Mean?
© Microsoft Corporation 1998, All Rights Reserved.
Contributions by Joe Crump, Microsoft Corporation
Additional query words: wdCommandDispatch wordbasic
Keywords : kbnokeyword kbVC500 kbWord kbGrpDSO kbOffice2000
Version : WINDOWS:95,97; winnt:5.0
Platform : WINDOWS winnt
Issue type : kbhowto
Last Reviewed: June 1, 1999