Jump to content
  • Advertisement
Sign in to follow this  
dmatter

Unity Revisiting Win32 wrappers

This topic is 3632 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

    • Similar Content

      • By Alexander_Vovk
        Hello Guys!
        Please share your experience, where is it better to find sales manager  specialists for indie team of 6 + people(remotely)?
        Maybe someone has a good experience of cooperation with finding projects through sale managers(USA and Canada)?
        Thank you
        Best Regards
        Alex Vovk
        Co-Founder of Sixteen Squares
        Alexander_Vovk@outlook.com
         
      • By RoKabium Games
        Been a bit quiet recently, but we've been busy bug fixing and tweaking things... Now we have lots more 'Particle effects' in the game, specifically here the Flamethrower and Enemy attacks!
      • By JoshuaFraser
        Hi and thanks for reading, I have an issue with this reactive crosshair script, everything works fine until I start changing the offset. Give the script a go and you will see what I mean, when I do SetOffset(0f); it doesnt always set back to the origional state, if anyone can spot a fix I'd be super appreciative!
        using System.Collections; using System.Collections.Generic; using UnityEngine; public class ReactiveCrosshair : MonoBehaviour { [SerializeField] GameObject c_limb_prefab; private float center_offset = 0f; private float current_offset = 0f; private float max_offset = .5f; private int number_of_limbs = 4; private float limb_length = .05f; private float limb_width = .005f; private List<GameObject> c_limbs = new List<GameObject>(); public void SetupCrosshair(){ for (int i = 0; i < number_of_limbs; i++) { GameObject line_go = (GameObject)Instantiate (c_limb_prefab); line_go.transform.SetParent (this.transform); Vector3 limb_pos = new Vector3 (0f,0f,0f); //line_go.transform.position = limb_pos; line_go.transform.localPosition = limb_pos; LineRenderer line = line_go.GetComponent<LineRenderer>(); line.startWidth = limb_width; line.positionCount = 2; line.SetPosition (0, line_go.transform.localPosition + new Vector3(center_offset, 0f, 0f)); line.SetPosition (1, line_go.transform.localPosition + new Vector3(center_offset + limb_length, 0f, 0f)); line.useWorldSpace = false; c_limbs.Add(line_go.gameObject); } if (c_limbs != null) { OrientLimbs (); SetOffset (0f); } } public void OrientLimbs(){ for (int i = 0; i < c_limbs.Count; i++) { float rotation_step = 360f / (float)c_limbs.Count; c_limbs [i].transform.RotateAround (c_limbs[i].transform.position, c_limbs[i].transform.forward, 90f + (rotation_step * (float)i)); } } public void SetOffset(float _current_spread){ float offset = Mathf.Lerp (0f, max_offset, _current_spread); for (int i = 0; i < number_of_limbs; i++) { if (offset > current_offset) { Vector3 pos = c_limbs [i].transform.position + (c_limbs [i].transform.TransformDirection (Vector3.right) * offset); c_limbs [i].transform.position = pos; } if (offset < current_offset) { Vector3 pos = c_limbs [i].transform.position - (c_limbs [i].transform.TransformDirection (Vector3.right) * offset); c_limbs [i].transform.position = pos; } } Debug.Log ("SetOffset() offset: " + offset.ToString () + " _current_spread: " + _current_spread.ToString() + " localPos: " + c_limbs[1].transform.localPosition); current_offset = offset; } }  
      • By Erik Nivala
        So, as the title says i am trying to figure out a good way sync all that information with other players in Unity. My problem is that i can't come up with a good solution since i am used to creating classes for everything e.g. attachments are its own class and then the weapon would save a reference to that attachment. But since you can't send custom classes over [Command] & [ClientRPC] i am a little stuck. A solution for this would be giving each attachment for a slot a unique ID and then passing the ID to other player but i feel like that is very error prone if other ppl add a new attachment or the IDs get mixed up.
        Is there a "standard" way that this is usually done that i am missing?
        I am fairly new to programming so any help is appreciated!
      • By MintyLyton
        I'm looking for any team / people that need a programmer for their project. I'm looking to expand my portfolio which you can see Here. I'm more experienced with Unity but I can spend the time to learn new Engines if that's your preference. I have worked on Unreal Engine 4 before but I might take some time to re-learn it, if the project requires it. Feel free to DM here or use the contact info on my website. 
      • By ethancodes
        I'm working on a system for my game that will allow the player to stack pick ups in a queue. As one pick up expires, the next automatically activates. I'm having an issue though where if I pick up the first one, it activates fine, but if i pick up a second directly after it, it overrides the first one, activates the second one, and then once it has run it's course, everything goes back to normal gameplay, no first pick up. I'm not sure why this is happening. Hopefully someone can spot what I'm doing wrong in my code.
        Here is the code for the pick up manager:
        // Update is called once per frame void Update () { if (pickUpQueue.Count != 0 && !pickUpActive) { pickUpActive = true; pickUpQueue[0].ActivatePickUp(); } DeactivatePickUp(); } void DeactivatePickUp () { if (pickUpQueue.Count != 0 && pickUpActive) { Destroy (pickUpQueue [0]); pickUpQueue.RemoveAt (0); pickUpActive = false; } } And here is the PickUp:
        public override void ActivatePickUp () { ball.GetComponent<Ball>().Speed = 2.0f; //increase ball speed... ball.GetComponent<Ball>().StartCoroutine(timer); //...set time that power up is active }  
        There is also a Base Pick Up:
        public void OnCollisionEnter2D (Collision2D collision) { Vector2 tweak = new Vector2 (Random.Range(0f, 0.2f),Random.Range(0f, 0.2f)); this.gameObject.GetComponent<Rigidbody2D>().velocity += tweak; //if the pickup makes contact with the paddle or ball.... if (collision.gameObject.tag == "Paddle" || collision.gameObject.tag == "Ball") { GameObject.FindObjectOfType<GameManager>().GetComponent<PickUpManager>().pickUpQueue.Add(this); Destroy(gameObject); //...and finally destroy power up object } } As a side note, I am trying to find a solution to this that will work for all of my pickups. Some pickups are ammo based, some are timed. 
      • By D34DPOOL
        Edit Your Profile D34DPOOL 0 Threads 0 Updates 0 Messages Network Mod DB GameFront Sign Out Add jobEdit jobDeleteC# Programmer for a Unity FPS at Anywhere   Programmers located Anywhere.
        Posted by D34DPOOL on May 20th, 2018
        Hello, my name is Mason, and I've been working on a Quake style arena shooter about destroying boxes on and off for about a year now. I have a proof of concept with all of the basic features, but as an artist with little programming skill I've reached the end of my abilities as a programmer haha. I need someone to help fix bugs, optomize code, and to implent new features into the game. As a programmer you will have creative freedom to suggest new features and modes to add into the game if you choose to, I'm usually very open to suggestions :).
        What is required:
        Skill using C#
        Experience with Unity
        Experience using UNET (since it is a multiplayer game), or the effort and ability to learn it
        Compensation:
        Since the game currently has no funding, we can split whatever revenue the game makes in the future. However if you would perfer I can create 2D and/or 3D assets for whatever you need in return for your time and work.
        It's a very open and chill enviornment, where you'll have relative creative freedom. I hope you are interested in joining the team, and have a good day!
         
        To apply email me at mangemason@yahoo.com
      • By davejones
        Is there a way to automatically change the start position of an animation? I have a bunch of animations set up on 3D models in unity. The issue is that I need to move the 3D models, however when I do so the animation start positions are not updated and I have to do it manually.

        Changing the transform of key frames is time consuming with the amount of animations I have, so I was wondering if there was a way to do it automatically?
      • By MoreLion
        hey all! We are looking for members for our Unity horror game! 
        Here’s the story:
        After a deadly virus plunges the world into chaos killing 85% of the human population there are now what they call “zones” these zones are watched very closely by the surviving government, people are checked every day for the virus, even if you touch the spit or any human waste or fluids of the victim who is infected, you will die. But one day, people in the west zone start to go missing, 1 woman goes outside the walls to uncover the mystery, is there more to the virus than meets the eye?, That is where your story starts.
        This game is not a long development game, I have loads other game ideas,
        I will also allow you to have a bit of creative freedom if you wish to add or share a idea!
        And no, it’s not a zombie game lol I feel like zombie games are too generic, in this game you will encounter terrifying beasts!
        There is some concept art one of our concept artists have made
        If interested email liondude12@gmail.com
      • By Canadian Map Makers
        GOVERNOR is a modernized version of the highly popular series of “Caesar” games. Our small team has already developed maps, written specifications, acquired music and performed the historical research needed to create a good base for the programming part of the project.

        Our ultimate goal is to create a world class multi-level strategic city building game, but to start with we would like to create some of the simpler modules to demonstrate proof of concept and graphical elegance.

         

        We would like programmers and graphical artists to come onboard to (initially) create:

        A module where Province wide infrastructure can be built on an interactive 3D map of one of the ancient Roman Provinces.
        A module where city infrastructure can be built on a real 3D interactive landscape.
        For both parts, geographically and historically accurate base maps will be prepared by our team cartographer. Graphics development will be using Blender. The game engine will be Unity.

         

        More information, and examples of the work carried out so far can be found at http://playgovernor.com/ (most of the interesting content is under the Encyclopedia tab).

         

        This project represents a good opportunity for upcoming programmers and 3D modeling artists to develop something for their portfolios in a relatively short time span, working closely with one of Canada’s leading cartographers. There is also the possibility of being involved in this project to the point of a finished game and commercial success! Above all, this is a fun project to work on.

         

        Best regards,

        Steve Chapman (Canadian Map Makers)

         
    • Advertisement
    • Popular Now

    • Forum Statistics

      • Total Topics
        631396
      • Total Posts
        2999783
    ×

    Important Information

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

    Participate in the game development conversation and more when you create an account on GameDev.net!

    Sign me up!