A WLL is an add-in for Microsoft Word that you can build with any compiler
that supports building DLLs (dynamic link libraries). This article is
designed to get you started building WLLs with Microsoft Visual C++. To
follow the steps outlined in this article, you should have some experience
building DLLs and you should have the Microsoft Word Developer's Kit, which
contains the necessary files to build a WLL.
For information about how to obtain the Word Developer's Kit, see the
Microsoft Press Web site at the following address:
// DocId of WLL session...
short g_docId;
// General-purpose variables...
static char buf[8192];
int err;
// Routine to report errors encountered...
void ReportError(char *msg) {
static char errBuf[1024];
sprintf(errBuf, "%s, Error = %d", msg, err);
::MessageBox(NULL, errBuf, "WLL Error", MB_SETFOREGROUND);
}
// Table of functions that we will register...
struct {
char *name; // Function name...
char *desc; // Function description...
} g_funcTbl[] =
{
{"MyMotd", "Message of the day"},
{"InsertTime", "Insert Time"},
{0, 0} // List is null-terminated
};
// Menu name
UCHAR *g_menuName = (UCHAR *)"&Custom Menu";
// wdAutoOpen() - entry point for WLLs...
short __stdcall wdAutoOpen(short DocID) {
// Some diagnostic output, remove from your final code ...
::MessageBox(NULL, "In wdAutoOpen()!", "Msg", MB_SETFOREGROUND);
// Store the docId for later use...
g_docId = DocID;
// Register our functions...
int i;
for(i=0; g_funcTbl[i].name; i++) {
err = CAPIRegister(
DocID, (UCHAR *)g_funcTbl[i].name,
(UCHAR*)g_funcTbl[i].desc
);
if(err) {
sprintf(buf, "CAPIRegister(%s, %s)",
g_funcTbl[i].name, g_funcTbl[i].desc);
ReportError(buf);
}
}
// Add our menu...
err = CAPIAddMenu(DocID, g_menuName, 1, 0);
if(err) ReportError("CAPIAddMenu()");
// Add our menu items...
for(i=0; g_funcTbl[i].name; i++) {
err = CAPIAddMenuItem(
DocID, g_menuName, (UCHAR *)g_funcTbl[i].name,
(UCHAR *)g_funcTbl[i].desc, -2, 0
);
if(err) {
sprintf(buf, "CAPIAddMenuItem() for %s",
g_funcTbl[i].name);
ReportError(buf);
}
}
// Initialize crt pseudo-random number generator...
srand(time(0));
return TRUE;
}
// Displays a message of the day (MOTD)...
short __stdcall MyMotd(void) {
char *name[] = {
"Rebekah",
"Brent",
"Michael",
"Joseph",
"Bob",
0
};
char *quote[] = {
"An apple a day, keeps the doctor away!",
"Carpe Diem: Seize the Day!",
"What you dare to dream, dare to do!",
"I think, therefore I am.",
"A place for everything, and everything in its place.",
"Home is where the heart is.",
0
};
int nNames, nQuotes;
for(nNames=0; name[nNames]; nNames++);
for(nQuotes=0; quote[nQuotes]; nQuotes++);
sprintf(buf, "%s says '%s'",
name[rand()%nNames], quote[rand()%nQuotes]
);
::MessageBox(NULL, buf, "XLL MOTD", MB_SETFOREGROUND );
return 0;
}
// Inserts time at current document location...
void __stdcall InsertTime(void) {
WCB wcb;
InitWCB(&wcb, TypeShort, NULL, 0);
_strtime(buf);
AddStringParam(&wcb, (UCHAR *)buf);
err = wdCommandDispatch(
wdInsert, CommandAction, wcb.cArgs, wcb.wdoprArgs, lpwdoprNil
);
if(err) {
ReportError("wdInsert");
}
}
You will see a ANewWLL.DEF file in your project. Open that and add the names of the functions your .wll will export, so that the file looks like the following:
; ANewWLL.def : Declares the module parameters for the DLL.
LIBRARY "ANewWLL"
DESCRIPTION "ANewWLL Windows Dynamic Link Library
EXPORTS
; Explicit exports can go here
wdAutoOpen
MyMotd
InsertTime
Compile and rename your ANewWLL.dll to ANewWLL.wll.
On the Tools menu, click Templates and Add-ins. Add ANewWLL.wll and click OK. Notice that when you click OK, the wdAutoOpen() function runs, and your new menu is created.
On the Custom Menu, click Message of the day. When your menu item is clicked, the MyMotd() function runs and displays a MessageBox with a quote such as "Rebekah says 'An Apple a day, keeps the doctor away!'."
On the Custom Menu, click Insert Time. When you select this menu item, the InsertTime() function runs and inserts the current time into your document.