• Advertisement
Sign in to follow this  

Unity Revisiting Win32 wrappers

This topic is 3482 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
    • Advertisement
    • Popular Tags

    • Advertisement
    • Popular Now

    • Similar Content

      • By 3dmodelerguy
        So I am building a turn based rogue-like (think CDDA). The game is going to have a very large map (up to 1000's x 1000's) however to alleviate most of that I obviously can't render everything so there will just be render a certain radius around the player and just load in and out data as the player moves.
        The next major system I am prototyping is making interactive tiles destructible and pretty much everything will be destructible besides basic landscape (cars, doors, windows, structures, etc. will be destructible)
        While I am only rendering a certain amount of tiles around the player, I want to keep the amount of colliders active at one time to be as small as possible for performance and currently the tilemap tool I use automatically merges colliders together.
        So instead of creating a separate colliders for each of these tiles and having the destructible behavior tied to that object (which my tilemap tool would allow me to do) I was thinking that I would store an array of all the X and Y locations for the interactive tilemap layer and let the tilemap manage the colliders. 
        Then when I hit a collider on the interactive tilemap layer, instead of of getting the behavior for how to deal with the destruction for that tile from that game object, I would pull it from the array I mentioned earlier based on the tile I attempt to interact with which I already have.
        Does this sound like a good approach? Any other recommendations would be welcomed.
      • By NDraskovic
        Hey guys,
        I have a really weird problem. I'm trying to get some data from a REST service. I'm using the following code:
         
        private void GetTheScores() { UnityWebRequest GetCommand = UnityWebRequest.Get(url); UnityWebRequestAsyncOperation operation = GetCommand.SendWebRequest(); if (!operation.webRequest.isNetworkError) { ResultsContainer rez = JsonUtility.FromJson<ResultsContainer>(operation.webRequest.downloadHandler.text); Debug.Log("Text: " + operation.webRequest.downloadHandler.text); } } The problem is that when I'm in Unity's editor, the request doesn't return anything (operation.webRequest.downloadHandler.text is empty, the Debug.Log command just prints "Text: "), but when I enter the debug mode and insert a breakpoint on that line, then it returns the text properly. Does anyone have an idea why is this happening?
        The real problem I'm trying to solve is that when I receive the text, I can't get the data from the JSON. The markup is really simple:
        [{"id":1,"name":"Player1"},{"id":2,"name":"Player2"}] and I have an object that should accept that data:
        [System.Serializable] public class ResultScript { public int id; public string name; } There is also a class that should accept the array of these objects (which the JSON is returning):
        [System.Serializable] public class ResultsContainer { public ResultScript[] results; } But when I run the code (in the debug mode, to get any result) I get an error: ArgumentException: JSON must represent an object type. I've googled it but none of the proposed solutions work for me.
        Also (regardless if I'm in the debug mode or not) when I try to do some string operations like removing or adding characters to the GET result, the functions return an empty string as a result
        Can you help me with any of these problems?
        Thank you
      • By nihitori
        The Emotional Music Vol. I pack focuses on beautiful and esoteric orchestral music, capable of creating truly emotive and intimate moods. It features detailed chamber strings, cello and piano as the main instruments, resulting in a subtle and elegant sound never before heard in video game royalty-free music assets.

        The pack includes 5 original tracks, as well as a total of 47 loops based on these tracks (long loops for simple use and short loops for custom / complex music layering).

        Unity Asset Store link: https://www.assetstore.unity3d.com/en/#!/content/107032
        Unreal Engine Marketplace link: https://www.unrealengine.com/marketplace/emotional-music-vol-i

        A 15 seconds preview of each main track is available on Soundcloud:
         
      • By RoKabium Games
        Another one of our new UI for #screenshotsaturday. This is the inventory screen for showing what animal fossils you have collected so far. #gamedev #indiedev #sama
      • By eldwin11929
        We're looking for programmers for our project.
        Our project is being made in Unity
        Requirements:
        -Skills in Unity
        -C#
        -Javascript
        -Node.js
        We're looking for programmers who can perform a variety of functions on our project.
        Project is a top-down hack-and-slash pvp dungeon-crawler like game. Game is entirely multiplayer based, using randomized dungeons, and a unique combat system with emphasis on gameplay.
        We have a GDD to work off of, and a Lead Programmer you would work under.
        Assignments may include:
        -Creating new scripts of varying degrees specific to the project (mostly server-side, but sometimes client-side)
        -Assembling already created monsters/characters with existing or non-existing code.
        -Creating VFX
        -Assembling already created environment models
        If interested, please contact: eldwin11929@yahoo.com
        This project is unpaid, but with royalties.
         
        ---
        Additional Project Info:
        Summary:
        Bassetune Reapers is a Player-verus-Player, competitive dungeon crawler. This basically takes on aspects of dungeon crawling, but with a more aggressive setting. Players will have the option to play as the "dungeon-crawlers" (called the 'Knights', or "Knight Class", in-game) or as the "dungeon" itself (literally called the 'Bosses', or "Boss Class", in-game). What this means is that players can choose to play as the people invading the dungeon, or as the dungeon-holders themselves.
        Key Features:
        -Intense, fast-paced combat
        -Multiple skills, weapons, and ways to play the game
        -Tons of different Bosses, Minibosses, creatures and traps to utilize throughout the dungeon
        -Multiple unique environments
        -Interesting, detailed lore behind both the game and world
        -Intricate RPG system
        -Ladder and ranking system
        -Lots of customization for both classes s of customization for both classes
    • Advertisement