Jump to content
  • Advertisement
Sign in to follow this  
dmatter

Unity Revisiting Win32 wrappers

This topic is 3756 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

After reading this Win32 related thread I was about to post a reply but then decided it would be better suited as a new thread to avoid hijacking the topic there. So here it is: It's a rather old concept now but I've begun thinking a little into this sort of thing again recently. Having looked at a few existing Win32 wrappers in C++, like Evil Steve's (from the other thread) as just one example of them, some things from most of these designs stand out to me generally:
  • People have a static routing wnd-proc as opposed to using a free function, I don't see why, it's perhaps just "over OO-ism"?
  • People register a new window class at the same as creating a new window, seems like Microsoft intended window classes to be reused between different windows yet that rarely seems to be supported by the design.
  • People give each new window class the same name - problematic? Perhaps not if Windows doesn't re-register the window class, but strikes me as a design smell anyway.
  • People have separate create/destroy functions from the constructors/destructors. If the class is meant to represent a win32 window then surely these things should be in the ctors/dtors? Otherwise, if the class is meant to represent a win32 window handle, then surely the handle shouldn't be the one creating and destroying windows?
  • There aren't always satisfactory examples of how people expect to use these classes in real applications - inherit from them for each window they want?
So, I wish my question was "What actually is the best way to go about this... really?" - but that's obviously subjective. I was doing some thinking whilst typing the above and I thought upon this:
  • A WindowFactory registers a WNDCLASSEX and can return Window objects associated with that window class and thus its wnd-proc. This allows sharing of the window class. I'm wondering whether this factory can be specialised to, for example, create windows for a given D3D device or OGL context? Basically anything that is sharable among windows at construction time?
  • A Window is a thin, auto_ptr style, wrapper around a HWND to support some RAII.
  • A Window needs to be convertible to a HWND so it can be passed to OGL/D3D/Win32/etc functions, but that's safe as far as I can think(?).
  • A Window object must not survive longer than the WindowFactory that created it in order not to out-live its WNDCLASSEX - that doesn't seem too evil, somewhat like an iterator must not survive longer than the container it's referencing.
  • The default wnd-proc would probably be like the static ones you see in other designs (except not a static function) but it wouldn't dispatch to the Window rather to an EventHandler that can be implemented in whatever way the client wants.
I think that is perhaps a better design than before, though still not ideal. It's certainly an improvement over my last attempt at any Win32 stuff, which always seems to be the most brittle part of my initialisation code, although I don't find it too much of a problem in practice. So any thoughts, ideas, suggestions, critique or abuse? [smile] Or if anyone has anything they consider to be better?

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by dmatter
  • People have a static routing wnd-proc as opposed to using a free function, I don't see why, it's perhaps just "over OO-ism"?
  • By making the static window proc a static function, it can access private functions in the class. That allows the non-static window proc to be private.

    Quote:
    Original post by dmatter
  • People register a new window class at the same as creating a new window, seems like Microsoft intended window classes to be reused between different windows yet that rarely seems to be supported by the design.
  • A single window class is designed to cope with all windows that behave in the exact same way,. If you have E.g. 4 views in a model editing program that are 4 windows, then you'd probably use the same class. In a game, there's usually only one window, and if there's a different one, you'll usually want to use a different window proc for it - and that requires a different window class.

    Quote:
    Original post by dmatter
  • People give each new window class the same name - problematic? Perhaps not if Windows doesn't re-register the window class, but strikes me as a design smell anyway.
  • Window class names cannot clash in one process. I'm not sure what happens if you try to register two classes with the same name, I suspect the second will fail. If you have two EXEs though, you can have the same class name in each.

    Quote:
    Original post by dmatter
  • People have separate create/destroy functions from the constructors/destructors. If the class is meant to represent a win32 window then surely these things should be in the ctors/dtors? Otherwise, if the class is meant to represent a win32 window handle, then surely the handle shouldn't be the one creating and destroying windows?
  • True. I usually have a create and destroy function, it just allows me to clean up the window without deleting it. Admittedly I can't think of a time that I've needed to do this, but it's handy anyway. I suppose it's just a matter of choice.

    Quote:
    Original post by dmatter
  • There aren't always satisfactory examples of how people expect to use these classes in real applications - inherit from them for each window they want?
    So, I wish my question was "What actually is the best way to go about this... really?" - but that's obviously subjective.
  • In my apps, I used to have the same window (C++) class and then inherit from it. The only thing that needed changed was that the non-static window proc became virtual. However, in most apps I write, I only need one window so I just put the functionality in the base class and don't bother with a derived class. It'd be trivial to use the former method though.

    Quote:
    Original post by dmatter
    I was doing some thinking whilst typing the above and I thought upon this:

    • A WindowFactory registers a WNDCLASSEX and can return Window objects associated with that window class and thus its wnd-proc. This allows sharing of the window class. I'm wondering whether this factory can be specialised to, for example, create windows for a given D3D device or OGL context? Basically anything that is sharable among windows at construction time?

    • A Window is a thin, auto_ptr style, wrapper around a HWND to support some RAII.

    • A Window needs to be convertible to a HWND so it can be passed to OGL/D3D/Win32/etc functions, but that's safe as far as I can think(?).

    • A Window object must not survive longer than the WindowFactory that created it in order not to out-live its WNDCLASSEX - that doesn't seem too evil, somewhat like an iterator must not survive longer than the container it's referencing.

    • The default wnd-proc would probably be like the static ones you see in other designs (except not a static function) but it wouldn't dispatch to the Window rather to an EventHandler that can be implemented in whatever way the client wants.

    I think that is perhaps a better design than before, though still not ideal.
    It's certainly an improvement over my last attempt at any Win32 stuff, which always seems to be the most brittle part of my initialisation code, although I don't find it too much of a problem in practice.

    So any thoughts, ideas, suggestions, critique or abuse? [smile]
    Or if anyone has anything they consider to be better?
    To be honest, it all sounds a little over the top. When do you really need multiple window classes?

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by dmatter
  • A Window object must not survive longer than the WindowFactory that created it in order not to out-live its WNDCLASSEX - that doesn't seem too evil, somewhat like an iterator must not survive longer than the container it's referencing.

    So any thoughts, ideas, suggestions, critique or abuse? [smile]
    Or if anyone has anything they consider to be better?


  • Once you have registered your window class, the lifetime of the WNDCLASSEX is not relevant. For example, my class registering function uses a local variable WNDCLASSEX that is destroyed when the function returns.


    int Register(HINSTANCE HIn)
    {
    WNDCLASSEX Wc;

    Wc.cbSize=sizeof(WNDCLASSEX);
    Wc.style=0;
    Wc.lpfnWndProc=WndProc;
    Wc.cbClsExtra=0;
    Wc.cbWndExtra=0;
    Wc.hInstance=HIn;
    Wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    Wc.hCursor=LoadCursor(NULL,IDC_ARROW);
    Wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
    Wc.lpszMenuName=NULL;
    Wc.lpszClassName="WhateverWin";
    Wc.hIconSm=LoadIcon(NULL,IDI_APPLICATION);

    return RegisterClassEx(&Wc);
    }


    After that, the window class is accessible in CreateWindow* by its lpszClassName.

    Not in anyway meant as a criticism of your ideas - just thought it might save you some work.

    I agree with Steve that for a D3D/OGL game requiring a single window, there is far too much engineering going on here, but for a Win32 wrapper for writing windows apps (if anyone is still masochistic enough to do such a thing post-.NET), you raise some interesting points.

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Evil Steve
    By making the static window proc a static function, it can access private functions in the class. That allows the non-static window proc to be private.
    Ah good point, I'd overlooked that, and a private non-static window proc is usually better than a public one, so yes.

    Quote:
    A single window class is designed to cope with all windows that behave in the exact same way,. If you have E.g. 4 views in a model editing program that are 4 windows, then you'd probably use the same class.
    Yeah this is exactly the sort of thing I had in mind actually. If we said each such window is a "window view" then I'd have a factory for creating them:

    WindowFactory windowViewFactory(/*params*/);

    Quote:
    Window class names cannot clash in one process. I'm not sure what happens if you try to register two classes with the same name, I suspect the second will fail. If you have two EXEs though, you can have the same class name in each.
    In your link, you create a window class with the same name each time. If you attempted to create two windows with your code then you would be registering a window class with the same name more than once. I'd think the same as you, that it would fail, but that the window would be created with the first registered window class - I don't really feel comfortable with the idea of failing registering overally.

    Quote:
    To be honest, it all sounds a little over the top. When do you really need multiple window classes?
    Well I'd need multiple window classes when I want a different type of window, for example an application window and a panel window in a model editing program. The panel window views could then have a shared window class. I can see the uses, but I can see your point to.

    Some people make a window class per window, others have one window class for all of them - by introducing the window factory you get the flexibility of the middle ground but without the hassle of building icky win32 structures yourself.

    Keep in mind that the factory is not just limited sharing window classes, there are other resources that can be more easily shared like brushes, toolbars, API contexts/devices and so on.

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by EasilyConfused
    Once you have registered your window class, the lifetime of the WNDCLASSEX is not relevant. For example, my class registering function uses a local variable WNDCLASSEX that is destroyed when the function returns.

    <snip>

    Ooh, I wasn't very clear at all about that.
    I have in mind that the window factory would not only register the window class but also unregister it too, in it's destructor. If the factory is destructed then the window class is unregistered and pulled out from under the feet of any outstanding windows.

    Quote:
    I agree with Steve that for a D3D/OGL game requiring a single window, there is far too much engineering going on here, but for a Win32 wrapper for writing windows apps (if anyone is still masochistic enough to do such a thing post-.NET), you raise some interesting points.

    Yeah .Net is the way forward, but thinking more along the lines of properly abstracting the windowing code in general (so win32 or not) I think it is 'more correct' to use a factory here and not a fat do-it-all-in-one window class. I do still use some Win32 stuff though so I can at least stand to benefit; and the main reason I brought in OGL/D3D was to fire off peoples' synapses so they can see how it all fits in [smile]

    Share this post


    Link to post
    Share on other sites
    Sign in to follow this  

    • Advertisement
    ×

    Important Information

    By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

    We are the game development community.

    Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

    Sign me up!