Search code examples
c++-cliunmanagedhwnd

Bind window handle (HWND) to class name/ component type in unmanaged code



I would like to find out the top level component name of a window from knowing its window handle.
This is done like so in managed C++ code:

//handle is the window handle as int
System::Windows::Forms::Control^ c = Control::FromHandle((System::IntPtr)System::Convert::ToInt32(handle));
System::Type^ t= c->GetType();
Console::WriteLine(t->FullName);//This is the top level name of the component.

However, I cannot use managed code for the solution that I have to develop.
I have tried to use GetClassName() as an equivalent, but this just gives me WindowsForms10.STATIC. [...] mumbo jumbo :)
Does anyone have any idea how this can be done in unmanaged code?
I know that C++ does not natively offer any support for WinForms, but I am hoping to get a pointer in the right way. I've seen it done in some solutions, but have been unable to get my code working :(
Thank you in advance.


Solution

  • This is probably what the WinForms code is doing:

    1. When a window is created, use SetWindowLongPtr (handle, GWL_USERDATA, value) to store a reference to the object owning the window.
    2. The Control::FromHandle calls GetWindowLongPtr (handle, GWL_USERDATA) to retrieve the managed object reference which you can then do managed stuff with (GetType(), etc)

    To do this in native Win32 and C++, create an interface class like:

    class IControl
    {
    public:
      virtual const string &GetTypeName () = 0;
    };
    

    and then derive controls from it:

    class TextBoxControl : public IControl
    {
      virtual const string &GetTypeName () { return "TextBox"; }
    }
    

    and then in the control constructor:

    TextBoxControl::TextBoxControl ()
    {
       handle = CreateWindowEx (parameters to create a text box);
       SetWindowLongPtr (handle, GWL_USERDATA, this);
    }
    

    and finally, given a window handle:

    string GetWindowTypeName (HWND handle)
    {
      IControl *control = GetWindowLongPtr (handle, GWL_USERDATA);
      return control->GetTypeName ();
    }