I don't know if this will help anyone, but I found the string tables to be the hardest part of learning this process. VC++ seems very picky and didn't like some of the additions that ResEdit (a free resource file editing tool) was making.
I've created a very simple example that is almost identical to the TESTCOMMANDS project, but stripped down to the bare essentials. This is more an example than a tutorial, but I will share a few things I encountered along the way.
All the files were edited in VC++. To edit a resource (.rc) file simply add a new file. You can select .h or .cpp as the file type it doesn't matter, just make sure to add the .rc extension when you name it. Once you've created your first .rc file, drag it into the code editing window and a pop-up should appear. You can select the default code editor as your resource file editor if you like and then you'll be able to edit them from within VC++ with minimal fuss.
Once that is done you're ready to go. Most of what you'll find in my example is already found in the DBPro help (look under Technical Documents->Third Party Commands they'll explain things better than I can). My reason for posting was simply to provide a complete working example that used VC++ Express and was as short and sweet as possible.
Here's what I came up with.
resource.h
#define IDS_STRING1 1
#define IDS_STRING2 2
MyFirstDLL.rc
#include <windows.h>
#include "resource.h"
STRINGTABLE
{
IDS_STRING1 "GET VALUE[%L%?GetValue@@YAHXZ%Valid calling formats:\ninteger get value()\ninteger get value(integer, integer)"
IDS_STRING2 "GET VALUE[%LLL%?GetValue@@YAHHH@Z%Valid calling formats:\ninteger get value()\ninteger get value(integer, integer)"
}
MyFirstDLL.cpp
#include <windows.h>
#define MYCOMMAND __declspec (dllexport)
MYCOMMAND int GetValue(void);
MYCOMMAND int GetValue(int a, int b);
int GetValue(void) {
return 42;
}
int GetValue(int a, int b) {
return a + b;
}
One thing I didn't notice in the DBPro help files was an example of function overloading. There's nothing difficult about doing it, but I figured it couldn't hurt to show just how easy it really is. I also had an interesting idea for the optional data in the string table (which I've never actually paid attention to before). Namely the parts that read:
Valid calling formats:\ninteger get value()\ninteger get value(integer, integer)
If you call the function with an incorrect parameter list, you can use that method to have the compiler report valid command lists to the user. (For anyone not familiar with C/C++ the "\n" informs the system to step to the next line.)
So if we supplied an invalid parameter list to our get value() function the compiler error would actually look something like the following:
Parameter for 'get value' do not match 'Valid calling formats:
integer get value()
integer get value(integer, integer)' at line #
Anyway, I hope this helps somebody. Also, if I'm overlooking something or spreading any misinformation, please let me know.
Cheers,
-Frank