0

I have used Visual Basic 6 in the past (LOONG ago), and it had a control called PictureBox where you could just draw stuff to, get a device context if you wanted, etc. I'm now trying to find out how to have a similar "control" in pure GDI/WinApi (no MFC, .net, atl, gdi+, etc). I was using an owner-draw button control, but you can't (easily) get the mouse coords when it is clicked, so I figured I needed some other control. I tried a static control, but that one has no owner-draw support. I tried handling WM_PAINT, but, as far as I know (after googling for hours), there is no way to use it to update just one area of the client or just a single HWND.

So, what I'm asking is, how do people animate or blit select areas of a window, be it a control or whatever, using pure GDI and Windows API? I know MFC has something called subclassing, but since MFC is just a wrapper for Windows API there MUST BE a way to do this without it (also as I said earlier, MFC is not an option).

stelonix
  • 716
  • 1
  • 5
  • 24
  • Just create a child window and do its painting in its WM_PAINT. Call `InvalidateRect()` when you want to force a re-paint. – David Heffernan May 20 '11 at 11:13
  • I'm sorry, but I don't know much about GDI. How do I handle WM_PAINT just for a single child window? – stelonix May 20 '11 at 11:19
  • You handle the WM_PAINT message in your window procedure. – David Heffernan May 20 '11 at 11:27
  • If I add a child window using CreateWindow, it'll still have its WM_PAINT handled by the parent window. If I handle WM_PAINT, as far as I know, there is no way to just handle the WM_PAINT of the child window. If I am wrong, can you post an example of how to do this? AFAIK the only way to set what window procedure a window uses is by using RegisterClass, which I have no idea how to do it for child windows. – stelonix May 20 '11 at 11:32
  • 1
    @knuck No, all windows get WM_PAINT messages. You can handle just WM_PAINT by doing exactly that. All other messages should be passed to DefWindowProc. Window procedures can be changed by calling SetWindowLongPtr. I think you need to brush up your knowledge of how Windows works before tackling this. Also, why do you need to do the project without the help of a GUI framework? That's just making life hard for yourself, especially if you have limited experience of low-level Win32. – David Heffernan May 20 '11 at 11:40

2 Answers2

2

Create a child window and do its painting in its WM_PAINT. Call InvalidateRect() when you want to force a re-paint.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

In all honesty, i think this may be a bit of a big project for you to take on right now. You may want to try a few simpler projects using the windows api before trying this, but i'll give you a bit of an explanation anyway.

You're going to need to create a custom control. Using an existing control for this is bad practice because that's not how they were intended to be used. To create a custom control, you first need to create a window class with WNDCLASSEX or WNDCLASS.

WNDCLASS: http://msdn.microsoft.com/en-us/library/ms633576
WNDCLASSEX: http://msdn.microsoft.com/en-us/library/ms633577

Once you do that and set all the member values that you need to, you have to register the class with either RegisterClass or RegisterClassEx.

One of the members of the WNDCLASS(EX) objects takes a window procedure function pointer. Any window created with this window class will use this window procedure.

Once you have registered your window class, you can create a window using the window class you have made. Just do CreateWindow(..., "YOUR WINDOW CLASS HERE", ...);

Now, your window procedure should look something like this:

LRESULT CALLBACK MyDrawProcedure(HWND hwnd, UMSG uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
      case WM_PAINT:
      {
        // Handle painting your control here.
      }
      break;

      default:
         return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    return 0;
}

Well, i hope this helps a bit.

Gogeta70
  • 881
  • 1
  • 9
  • 23