Sign in to follow this  
sbayeta

WIN32 wrapper classes

Recommended Posts

Hi, I wrote a little set of WIN32 API wrapper C++ classes, just as a way to learn the API and to maintain my code organized. My Window class is supposed to be used like this:
#include <windows.h>
#include "wrappers.h"

Window *wn;
ProcedureBag *pb;
Button *bt;

void on_create(WPARAM, LPARAM);
void on_destroy(WPARAM, LPARAM);
void on_command(WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) {
	pb = new ProcedureBag();
	pb->addProcedure(WM_CREATE, on_create);
	pb->addProcedure(WM_DESTROY, on_destroy);
	pb->addProcedure(WM_COMMAND, on_command);
	wn = new Window(hInst, "My window", pb);
	return wn->processEvents();	//this function enters the messageloop
}


void on_create(WPARAM wParam, LPARAM lParam) {
	//do something
}

void on_destroy(WPARAM wParam, LPARAM lParam) {
	//do something
}

void on_command(WPARAM wParam, LPARAM lParam) {
	//do something
}
The ProcedureBag class is basically a wrapper for an STL map, holding (message-procedure) pairs. It only has two methods:
/*
 * Add a procedure to the bag, associating it to a particular message
 */
void ProcedureBag::addProcedure(UINT msg, PROCPTR procedure) {
	(*bag)[msg] = procedure;
}

/*
 * Executes the procedure associated to msg, passing to it wParam and lParam
 */
bool ProcedureBag::executeProcedure(UINT msg, WPARAM wParam, LPARAM lParam) {
	if(bag->find(msg) != bag->end()) {
		(*bag)[msg](wParam, lParam);
		return true;
	}
	return false;
}
The latter is called by the Window class in its window procedure, shown below:
LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT msg, WPARAM wParam,LPARAM lParam) {
/*
	if(pBag->executeProcedure(msg, wParam, lParam)) return 0;
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

The problem is that I have to declare Window::WndProc as static in order for the file to compile (I don't know why), and hence I also need to declare pBag (a private ProcedureBag in Window class) also as static. And when I do this, the program compiles but doesn't link because of an unresolved reference to this pBag. I'd like to make Window::WndProc an instance method and pBag an instance variable. How can I do this ? If you need more code tell me and I'll post it. Thanks in advance. Any other suggestion about the approach I'm taking will be appreciated.

Share this post


Link to post
Share on other sites
Quote:
Original post by sbayeta
The problem is that I have to declare Window::WndProc as static in order for the file to compile (I don't know why), and hence I also need to declare pBag (a private ProcedureBag in Window class) also as static.


Hi the reason is that WNDPROC is function pointer which isn't the same as member function pointer, so basically a static/class function is simillar to a normal function, it doesn't need an instance so you can assign the address of it

Quote:
Original post by sbayeta
And when I do this, the program compiles but doesn't link because of an unresolved reference to this pBag.


When you have a class/static data member you need to define in your source file thats why your getting link errors so you would need to do:

header file .h

struct a {
static int f;
};


source file .cpp

#include "some_header.h"
int a::f(4); //construct it with what ever value you wont


Quote:
Original post by sbayeta
I'd like to make Window::WndProc an instance method and pBag an instance variable. How can I do this ?


Sorry it won't work that way.

Share this post


Link to post
Share on other sites
In addition to snk_kid's response, There is another flaw in your approach. That flaw is that when you do the
wn = new Window(hInst, "My window", pb);
messages will immediately be sent to your window before the
return wn->processEvents();
executes. You will have to perform some interesting dance steps to have the correct procedures executed in the Window constructor. Because of this, you don't even really need to wrap the WM_CREATE message if you go your way.

Also, because of your map approach you cannot override a message procedure for a single Window class. You would have to make it a multimap and then perform more paperwork in your forwarding function.

I recommend that you look at some other ways of doing it. The following links should help.

http://www.gamedev.net/reference/articles/article1810.asp
http://www.relisoft.com/Win32/generic.html
http://www.randommonkeyworks.com/Programming/WinAPI_ver2/Project_Begin.html

Enjoy your learning!

David

Share this post


Link to post
Share on other sites
Quote:
Original post by sbayeta

The problem is that I have to declare Window::WndProc as static in order for the file to compile (I don't know why), and hence I also need to declare pBag (a private ProcedureBag in Window class) also as static. And when I do this, the program compiles but doesn't link because of an unresolved reference to this pBag.

I'd like to make Window::WndProc an instance method and pBag an instance variable. How can I do this ?


WndProc must be a static because Windows can't call it any other way. Windows wouldn't have a reference to the object that owned WndProc (either an instance of your "Window" or "ProcedureBag" classes)... so, how would it call it? WndProc is a C-language, MS-specific API.

Luckily, since it IS a static function, that means if you play your cards right, you only have to code it once.

The relisoft.com tutorial shows a good way to use WndProc... you'll have to store a pointer to your "ProcedureBag" instance in the user-param field in "CreateWindowEx" and retrieve it inside WndProc. GetWindowLong() and SetWindowLong() will become your new favorite Win32 APIs :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this