Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Object orienting the win32 API

Status
Not open for further replies.

CodingNovice

Programmer
Dec 30, 2003
108
GB
Hi. I have been programming for windows in C for a few years now but would like in future to use C++. I originally learnt API programming with Petzold's excellent 4th edition of programming windows. Now when I program in C++ at the moment im really only using it as a better C and not fully OOP. I have played with MFC a little ( i have Prosise) but find it not much easier to work in than pure API except you have to write less code. I haven't got into ATL or WTL yet so dont suggest those. What im looking for is the best way to avoid the C style wndproc. I know that a wndproc has to be a static member or a non-member function but a virtual wndproc would make more sense so its just a case of forwarding to a virtual from a static wndproc. Now how on earth do you pass the needed this pointer. I have one way of doing this but like MFC it relies on a global app object. There must be a better way. I have tried searching the web but come up with very little real information on this. There is and their model-view-controller approach and an article on that uses a std::map to map windows messages to member functions but that im sure will be a bottleneck due to std::maps logarithmic lookup speed. Any ideas. Im just looking for a sensible and extendable way to write the common code thats common to most all window progs.... winmain,wndproc,message loop etc.
Any decent ideas gratefully recieved.
Thanks.
 
>find it not much easier to work in than pure API except you have to write less code

Yes, but since all SW developers (myself included) are lazy, I'd say that is quite an advantage.

>a virtual wndproc would make more sense
Indeed. Check out the CWnd::WindowProc method.

>Any ideas. Im just looking for a sensible and extendable way to write the common code thats common to most all window progs.... winmain,wndproc,message loop etc.

Although not 100% OO (but then, C++ isnt really 100% OO either) MFC provides a lot of this in a quite easy-to-use, extendible way.

winmain: Objectified with the CWinApp class
wndproc: Overridable in the CWnd::WindowProc
message loop: Map message to methods via the AFX_MSG_MAP macros


/Per

"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."
 
I do not like MFC. I have played with MFC and discounted it. Im looking for something similar to the sites I posted. Basically im looking for a way to pass a this pointer to a static wndproc to allow me to forward to a virtual wndproc. Anyone done this without a global object or MFC. The only things I wish to use are C++ and win32 API.
 
Hi all,

I am stuck on the same problem as coding novice, have you found a soltion that works? CodingNovice could you please send me the link where it shows the solution using std::map or something please, I just need a solution that works, asap, I would be very grateful thanks.
 
Should have read that article more carefully.... I still dont like std::map and may look at Loki::AssocVec instead but look at the simplicity of this.....

The Window Class
Windows in Win32 are represented by window handles, so the logical first object to encapsulate is the window handle. Anybody who has tried to wrap window classes knows that you can not initialize the window class with a class method as the window procedure unless it is a static method, so the class also needs a static "message router" that determines which instance of the class is the recipient of the message and calls that instance's window procedure. So how exactly do we determine which instance should receive the message?

Every window has a 32-bit value associated with it intended for use by the application. This value can be set via the SetWindowLong function and retrieved with the GetWindowLong, and this is the core of the message routing technique.

LRESULT CALLBACK Window::MsgRouter(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
Window *wnd = 0;

// retrieve associated Window instance
wnd = reinterpret_cast<Window *>:):GetWindowLong(hwnd, GWL_USERDATA));

// call the windows message handler
wnd->WndProc(message, wparam, lparam);
}

While this looks perfect, where and when was this value stored? At first I stored it during my Window::Create routine, but I ran into problems. You see, some messages are sent before CreateWindowEx returns - WM_NCCREATE, WM_NCCALCSIZE and WM_CREATE (in that order). If the value does not exist by the time WM_NCCREATE is called then, by some mysterious Windows behavior that I still don't understand, the value never gets inserted. The solution? The WM_NCCREATE message must be handled explicitly within the message router, with the object pointer being stored at this point instead. Okay, but where do we get the value from? The CreateWindowEx function allows the passing of a (void) pointer to window creation data. This data is made available to the window procedure as the lparam parameter in the form of an LPCREATESTRUCT. As an added precaution, we go ahead and store the window handle at this point.

LRESULT CALLBACK Window::MsgRouter(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
Window *wnd = 0;

if(message == WM_NCCREATE)
{
// retrieve Window instance from window creation data and associate
wnd = reinterpret_cast<Window *>((LPCREATESTRUCT)lparam)->lpCreateParams;
::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(wnd));

// save window handle
wnd->SetHWND(hwnd);
}
else
// retrieve associated Window instance
wnd = reinterpret_cast<Window *>:):GetWindowLong(hwnd, GWL_USERDATA));

// call the windows message handler
wnd->WndProc(message, wparam, lparam);
}

Beautiful, isn't it. Strange I never considered explicitly handling WM_NCCREATE in the static. Was originally thinking ALL messages should be handled by the virtual wndproc. Oh well, thank god I don't do this for a living and are instead just a hobbyist programmer cause I would have been fired for taking this long to think up something so simple!!!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top