Thread: Different approaches to making a Win32 wrapper

  1. #1
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630

    Different approaches to making a Win32 wrapper

    Ok, I have no problems making a working wrapper. Ive seen several ways of doing this and I was just wondering what the most common was of doing it is. Ive seen people use global WndProc's, ive also seen (and I do this) use a static WndProc and then have a virtual one for your class, that you call from the static WndProc.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    yep - that pretty much covers the simplest ways; and I use both, although I prefer the static wndproc that fwds msgs to a virtual wndproc just because I only have to write the damn thing once and forget about it.

    I understand that there are other ways to do this such as using some kind of 'class factory' object - unfortunately I know nothing about this technique. Functors (great word that ) apparently gives another option but the little i've read about them suggests to me that they may be no better than using the msg macros in windowsx.h ie you have to 'hard wire' the exact msg handler within your class hierarchy which gets called, breaking the advantage of polymorphism in this respect. I live in hope though, because I still tend to use the msg macros for simplicity and readability. Anyway there might be a way to implement a generic functor approach using template classes but again my knowledge here is very sketchy.

    I would love to know how you go about this yourself or what ideas you might have.

  3. #3
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Well Ive used both methods, right now im messing around with a differnt idea, where i dont even have to use the WndProc in the class. My Window classes have a default WNDPROC param of NULL, and in the base class where all the wndclass initialization is done it checks first to see if this is null, then if its not it uses the specified WNDPROC. This method has worked for the last few weeks ive been trying it in my projcet but I dont really like it b/c it seems like cheating b/c its defeating the purpose of polymorphism since the function cant be virtual.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  4. #4
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Do you have any information on these other methods? Id love to read anything on them b/c i love knowledge. Thanx in advance
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  5. #5
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    I found this link a couple of days ago that i've only skimmed, but superficially it seems detailed, well organised and reasonably explained.

    http://www.function-pointer.org/

    I think Stoustrup discusses functors a little in his 'C++ Programming Language 3rd ed.' book. I have another book 'The C++ Standard Library' by N.M. Josuttis that goes into a little more detail. So from these references I figure it must be something that's implemented in the c++ std library but unfortunately for me I have a knowledge set that is very narrowly confined to win32 API (and pretty shallow at that) so it's going to be a real uphill struggle to learn this stuff

    The 'class factory' method is something I have only seen referred to in passing but maybe a search may throw up a gem or two within the usual 400 Terabytes of silt. I think it uses template classes - and again my knowledge/experience here is extremely limited. It may be that 'functors' are used as part of a 'class factory' - I just do not know???

    >>My Window classes have a default WNDPROC param of NULL<<

    Ooooooh! Interesting....

  6. #6
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    That was an interesting read, I found this link the other day while just messing around on www.flipcode.com, here it is: http://www.flipcode.com/cgi-bin/msg....rum=cotd&id=-1 it uses STL and assiciative maps. Also I thought id mention the above method I was playing with. Well it works really well except it kinda defeats the purpose of polymorphism, b/c each derived class would then need its own static WndProc
    Last edited by xds4lx; 02-25-2002 at 01:27 PM.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  7. #7
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Thanks for the link which i've just had a quick look at. It doesn't seem to offer any immediate advantages and I tend to agree with the guy who suggested using the map container class just kind of adds unnecessary complication. Also have to agree with the point about not really bothering with every msg that comes in, although the only one I consistently fail to trap is WM_MEASUREITEM for dialogs; since mfc fails in this regard too then I know I must be at least as bad as microsoft Similarly no probs with mdi msg handling; but would disagree with anyone using anything other than a global wndproc with a classic 'switch' for games programming: any attempts (all simple!) i've done are always slower, as you would expect because of the extra fn calls and the processing of each msg prior to dispatch to the correct class object within the c++ class hierarchy.

    Still, it's all food for thought, so thanks heaps for feeding me!

    BTW, coincidentally, more info appeared in GD recently: Prelude provides some interesting pages full of links that may or may not be of interest (I haven't had more than a cursory glance):

    http://www.cprogramming.com/cboard/s...threadid=11682

  8. #8
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Ken, how were you setting it up? The basic structure I use is the base class has the static WndProc plus a virtual one for the class, then each derived class then overides the base class's behavior. In my testing so far this seems to work fine and all, but I really havent tested it with any kind of graphical engine yet. I just started messing around with wrapping this all up in a class about 2 weeks ago. Ive done Win32 for a few years though, and figured it was about time to clean things up.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  9. #9
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    That's exactly the way I do it. I have a non-instantiable base class with the static wndproc from which I derive various classes for dialogs, wnds (inc. mdi's) and controls (ie sub/super classed would use the wndproc).

    The static wndproc determines which type ie mdi,dialog, wnd etc the msg is intended for prior to dispatch to the individual class handler.

    The tricky bit is a 'normal' wnd where 3 msgs have to be handled a little differently - WM_NCCREATE,WM_CREATE and WM_NCCALCSIZE. Since I use a static ptr to the base class, I just call the fn directly with the ptr in WM_NCCALCSIZE, using the WM_CREATE||WM_NCCREATE to fetch initialise and store (SetWindowLong) the this ptr from the CREATESTRUCT lParam. The same ptr is used in normal fashion to call the relevant class virtual wndproc fn for all other msgs.

    The only graphics thing i've played around with is a little openGL and even less directX but my reasoning is based more on the number of steps required to handle the msg than anything else
    ie it seems reasonably for me to assume that having a global wndproc with a switch statement to handle/crack messages in place is really only one step while having a static wndproc requires that the msg is sent to the static wndproc (one step) and is forwarded via class polymorphism to a derived class handler (two steps). In my case the class wndproc then cracks the msgs and forwards them to individual handler functions which obviously adds another step. This is perfectly ok for normal windows 'gdi' type apps but probably isn't for something that requires better performance - although perhaps it might work ok with multiple-threads? Also, since i'm an amateur, there are probably optimisations and improvements that pro's and those with formal training would be able to apply that would never occur to a simpleton like me in a million years.

    Anyway you could use the multimedia timer timeGetTime fn (or QueryPerformanceCounter for improved precision), to time the handling/cracking process of your own global v's static c++ approaches. Just to clarify I mean a C type linear screed with a global wndproc rather than a c++ global wndproc that forwards msgs to a class wndproc virtual fn.

  10. #10
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    I see what you mean about the overhead in forwarding to different message handlers, but I only do that for gui apps. Although, you can get a little better performance if you use passing by constant references in your virtual WndProc. When im working with an OpenGL app, I like using My OO framework but not use seperate message handlers except for initialization and deinitialization, instead I just put all the message handling code directly into the virtual WndProc.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  11. #11
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Are you talking about how the code on your web page is using the globally defined MainWndProc? I considered going with that approach but I really have using global variables b/c it is often a sign of bad program design. With the framework that im working on ive totaly gotten rid of the need for global variables (almost w/ the exception of a few #defines but they are hidden in namespaces to avoid the global namespace pollution that Microsoft likes to fill up with unused crap. Also Ive tried a slight modification to your approach, still using the global MainWndProc but not using the global CppWnd instance. You make the base class how your normally do, excluding the static WndProc, but with the virtual one, then in your constructor take a WNDPROC param and pass the address of your global proc to it. ex:

    Code:
    CWind::CWind(HINSTANCE hInstance, int xpos, int ypos, int xsize, int ysize, WNDPROC WindowProc)
    {     hInst = hInstance;
          cXPos = xpos;
          cYPos = ypos;
          cXSize =xsize;
          cYSize =ysize;
          // You can set up your WNDCLASS or WNDCLASSEX struct here or in 
          // helper func
          WNDCLASSEX wnd;
          ZeroMemory(&wnd, sizeof(WNDCLASSEX));
          wnd.lpfnWndProc = &WindowProc;
          ....
          //rest of initialization
    }
    Then your derived class should atleast take the HINSTANCE and WNDPROC params. and you just have to call the base class constructor. When I was trying this it worked just about the same as having the static WndProc in a class, but when I tried profiling both approaches i get mixed results. If only I could get my hands on a good profiler (not one in MSVC Pro) .
    Last edited by xds4lx; 02-26-2002 at 09:46 AM.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  12. #12
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Nothing against you Ken, but I entended this thread to be getting input from more than just me and you. I see that it has so many hits but noone wants to contribute. So someone else please throw in your 2 cents!
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  13. #13
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>Nothing against you Ken<<

    Don't worry, for the purposes of this post you may call me, 'Someone Else'

    >>about how the code on your web page is using the globally defined MainWndProc<<

    Yes and no. Those examples are simplified (I hope) to permit someone who knows a bit of c++ but maybe not so much win32 to see the 'evolution' of my design. Unfortunately, being both lazy and easily distracted I still haven't got round to describing the full blown static wndproc approach yet

    When I use the static wndproc I only have one global which is the minimum necessary to run a win32 app. The global is of course, WinMain. A class object is instantiated within a try...catch block to ensure memory for class object is released in case of error, and a class->Run function called; it's return value is used as the return from WinMain. Each instance of a window class would store the application instance by using GetModuleHandle(0), although using that fn as necessary would probably save me the HINSTANCE variable.

    I just define the static wndproc once and it's used either explicitly within a WNDCLASSEX struct, as the DLGPROC for CreateDialog or DialogBox or I have an AssignWndProc class function that uses SetWindowLong for subclassed controls.

    ie:

    WNDCLASSEX wcx;
    .
    .
    wcx.lpfnWndProc=(WNDPROC)StaticWndProc;
    .
    .

    I have never tried actually passing in a WNDPROC in the way you have; it looks interesting.

  14. #14
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Well there a few tricks to using that method, first if your passing a WNDPROC to the base class, you can do it in your derived class like this:

    Code:
    CAppWindow::CappWindow(HINSTANCE hInstance, int xpos, int ypos, int xsize, int ysize, WNDPROC WndProc)
    : CWindow(hInstance,xpos,ypos,xsize,ysize,WndProc)
    {
    }
    thats 1 way of doing it if you want to use a global WndProc, its nicer than actually setting up the WNDCLASSEX struct to use the Globaly defined name, b/c 1 if you use these classes again, you dont have to worry about the name of the global WndProc, where as if you go with your approach on your site you would have to make sure you have the global name the same every time you use that class. 2nd you can also construt an object like this:

    Code:
    CAppWindow::CAppWindow(HINSTANCE hInstance, int xpos, int ypos, int xsize, int ysize)
    : CWindow(hInstance, xpos, ypos, xsize, ysize, &this->WIndowProc)
    {
    }
    Now this second method requires you to define a new static WindowProc in your derived class. Which is defeating the purpose of polymorphism, but it works extreamly well (dont know about speed compared to other methods but everything ive tried this way has worked). With this second method you can use just like the origional static WndProc in the main base class, but you can omit using a virtual WndProc function. I liked this at first but I think its cheating so I stay with the static WindowProc in the base class, and use virtual WndProc's in all my derived classes.
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

  15. #15
    Registered User xds4lx's Avatar
    Join Date
    Nov 2001
    Posts
    630
    Another thing thats bugging me, if youve seen my other thread: Problems processing WM_NCCREATE, is which WM_ message is better to trap, WM_NCCREATE or WM_CREATE, i know that I can grab my this from either, but what's the difference?
    "only two things are infinite, the universe and human stupidity, and im not sure about the former." - albert einstein

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. FILES in WinAPI
    By Garfield in forum Windows Programming
    Replies: 46
    Last Post: 10-02-2003, 06:51 PM
  2. confusion win32 -console app
    By GanglyLamb in forum C Programming
    Replies: 2
    Last Post: 06-11-2003, 10:12 AM
  3. Win32 Programming - Intructor or Book?
    By dark_fusion in forum Windows Programming
    Replies: 6
    Last Post: 02-05-2003, 07:59 PM
  4. Help with Direct X and Win32......:D
    By incognito in forum Windows Programming
    Replies: 1
    Last Post: 04-16-2002, 07:59 PM
  5. About Unix Programming - Making a career desision
    By null in forum C Programming
    Replies: 0
    Last Post: 10-14-2001, 07:37 AM