1

I want to create a simple C++ class for transparent WinAPI labels (implemented using the standard "static" class). To accomplish this, I create a static control and override its Window Procedure to the following one:

LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
    if (Message == WM_PAINT)
    {
        RECT rc;
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rc);
        SetBkMode(hdc, TRANSPARENT);
        DrawText(hdc, Text, strlen(Text), &rc, DT_CENTER | DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0;
    }

    return CallWindowProc(WndProc_Original, hwnd, Message, wparam, lparam);
}

The code was taken from Edward Clements' excellent answer to this question: C++ Win32 Static Control Transparent Background

I wanted to wrap it up in a C++ class so I don't have to create a new Window Procedure for each label I want to use in my program. I wanted the overridden Window Procedure to be a member function which would then use this to use the label instance's stored data (the text to display, like so: DrawText(hdc, this->Text, strlen(this->Text), &rc, DT_CENTER | DT_VCENTER);)

However, member functions require that this be passed as the first parameter, whereas since this is a callback, I have no control over how Windows calls the function.

Is there any other way I can wrap it up in a compact class, so that I don't have to create a separate Window Procedure for each label?

Community
  • 1
  • 1
user4520
  • 3,401
  • 1
  • 27
  • 50
  • Yes there is. Did you tried search? – Ivan Aksamentov - Drop Mar 13 '15 at 18:23
  • Callback methods can be declared as `static` so they don't require a `this` parameter, but you'll need another method of getting a `this` pointer if you need access to the object's data. – Mark Ransom Mar 13 '15 at 18:25
  • @MarkRansom Exactly my thought, but I can't think of any method of accessing the data in a static function here. – user4520 Mar 13 '15 at 18:29
  • @Drop Search for what, exactly? It is a rare, conceptual issue. If you happened to find a site where this question is answered, please do be so kind and share it with us. – user4520 Mar 13 '15 at 18:29
  • Check out the sourcecode of WTL/ATL or MFC. I guess wxWidgets will use the same magic. In short: Map the window handle to the C++ object. – Ulrich Eckhardt Mar 13 '15 at 19:14
  • @UlrichEckhardt Could you elaborate? Do you mean storing the window handle in the object? How would that help? – user4520 Mar 13 '15 at 19:27
  • 1
    `It is a rare, conceptual issue` Are you kidding? http://stackoverflow.com/search?q=wndproc+class Unique problem, indeed. How comes it receives upvotes? – Ivan Aksamentov - Drop Mar 14 '15 at 08:35
  • @Drop Please read the question before you attempt to answer, and please don't be rude and unpleasant for no reason. The question has received two upvotes before you downvoted it, which proves others thought it was good. – user4520 Mar 14 '15 at 08:38
  • @Drop Reading the accepted answer might aid in understanding the problem as well. – user4520 Mar 14 '15 at 08:41
  • I didn't try to answer anything. I'm just saying your question already has tons of answers and you haven't demonstrated any wish to find them. The accepted answer is a rephrase of any of those answers. – Ivan Aksamentov - Drop Mar 14 '15 at 08:41
  • @Drop - Okay, I have to give it to you, one of the results of the search does answer it - I didn't think of that search phrase. You were right, sorry. I thought my problem was more isolated. – user4520 Mar 14 '15 at 08:46
  • @szczurcio There are much more questions like that on SO and plenty on whe web. Each time user thought his problem is unique. Okay, moving on. If you really want to get your `WndProc` to work perfectly, take a look at the source code of any major widget library as Qt, wxWidgets etc as @Ulrich suggested. Those are containers of wisdom. I would also avoid doing same thing for windows, labels, buttons etc. and would rolled out a generic solution that works for any control. ...or just used Qt, wxWidgets etc. ;) – Ivan Aksamentov - Drop Mar 14 '15 at 08:59
  • @Drop Yes, normally I would've done that, but I'm working on a small project and I've decided to go for pure WinAPI just to practice. – user4520 Mar 14 '15 at 09:00

1 Answers1

4

You can store a pointer in the textfield's user data:

myTextField->hWnd = CreateWindow( /*parameters*/ );
SetWindowLongPtr(myTextField->hWnd, GWLP_USERDATA, (LONG_PTR)myTextField);

And inside of your window proc:

LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
    MyTextFieldClass * myTextField = (MyTextFieldClass *)GetWindowLongPtr(hWnd,GWLP_USERDATA);
    /* rest of method */
}

And if you need to have access to your class during the window construction, you can do it this way:

HWND myTextField = CreateWindow( /*normal parameters*/, myTextField);

And retrieve it during WM_CREATE like this:

LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
     if (WM_CREATE == Message)
     {
          LONG_PTR myPtr = (LONG_PTR)((CREATESTRUCT *)lparam)->lpCreateParams;
          SetWindowLongPtr(hwnd, GWLP_USERDATA, myPtr);
          MyTextfieldClass * myTextField = (MyTextfieldClass *)myPtr;
     }
}
IronMensan
  • 6,761
  • 1
  • 26
  • 35