Thread: WM_PAINT my wagon

  1. #1
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273

    Exclamation WM_PAINT my wagon

    Hello,

    I'm trying to display a bitmap (Well, DIB in Microsoft-speak) in a window using the WM_PAINT message. This works fine when it initially loads up, but if I drag another window over it and then drag it back it gets all corrupted. I'm using:-
    Code:
    // g_lpData is a pointer to the image data
    // g_lpBi is a pointer to the image's BITMAPINFO
    // g_iScrollX, g_iScrollY are offsets set by the scroll bars
    case WM_PAINT:
    {
    	PAINTSTRUCT ps;
    
    	if (g_lpData) // We have something to draw
    	{
    		BeginPaint(hwnd, &ps);
    		ps.rcPaint.right -= ps.rcPaint.left;
    		ps.rcPaint.bottom -= ps.rcPaint.top;
    		if (ps.rcPaint.right > g_lpBi->bmiHeader.biWidth)
    			ps.rcPaint.right = g_lpBi->bmiHeader.biWidth;
    
    		if (ps.rcPaint.bottom > -g_lpBi->bmiHeader.biHeight)
    			ps.rcPaint.bottom = -g_lpBi->bmiHeader.biHeight;
    
    		if (ps.rcPaint.left < g_lpBi->bmiHeader.biWidth && ps.rcPaint.top < -g_lpBi->bmiHeader.biHeight)
    			StretchDIBits(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom, ps.rcPaint.left + g_iScrollX, ps.rcPaint.top + g_iScrollY, ps.rcPaint.right, ps.rcPaint.bottom, g_lpData, g_lpBi, DIB_RGB_COLORS, SRCCOPY);
    
    		EndPaint(hwnd, &ps);
    	}
    
    	break;
    }
    I know most people just draw the entire bitmap all at once, but I think that's a bit of a waste doing that every time a window is moved a pixel over the bitmap. Can anyone solve this for me please?

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    the rect returned by the call to BeginPaint() will contain the update region.

    Why are you changing it?

    "ps.rcPaint.right -= ps.rcPaint.left;
    ps.rcPaint.bottom -= ps.rcPaint.top;"

    If the rect is say 1/2 the width to the whole width ie the right half of the screen, then you will draw nothing

    ie left = Width/2;
    right = Width;

    therefore

    right -= left -> width - width/2 = width/2

    now left and right == width/2

    PS
    Stretch'ing the image is slow and costly to the quality of the image. It would be better to select the BMP into a temp DC (on init) and use that to BitBlt() the correct area (free on close).
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User lobo's Avatar
    Join Date
    Oct 2001
    Posts
    71
    I think he's changing it because he wants size of that region (for StretchDIBits()), no?

    SMurf, try testing validity of those params you pass to StretchDIBits(), to be sure they are right . Are your memory buffer & BITMAPINFO still valid when subsequent calls to WM_PAINT happen?

  4. #4
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    novocain, StretchDIBits needs x y width height, not left top right bottom as the RECT is used, so I decrement the right by the left to give the width (And the same with the bottom and top). From your given logic, the DIB would be drawn starting from width/2 to a width of width/2, and there is nothing wrong with that.

    I'm not actually stretching the image either, as source width and height are the same as dest width and height. I just didn't want to bother with actual bitmaps and DCs beyond the window's DC (This will be an image editing program, one day...).

    lobo, all of the params do seem to be valid, and neither of the pointers change until the program is closed, so the problem doesn't lie there. There must be something about the co-ordinates that differs when redrawing (As I've said, when the invalidated region is the entire window, it draws fine).

  5. #5
    Registered User lobo's Avatar
    Join Date
    Oct 2001
    Posts
    71
    Sorry to repeat myself: did you check both src and tgt position and size parameters of StretchDIBIts() call when wrong data were drawn? If whole bitmap is painted fine when entire window region is invalidated, as you said, they must be wrong somehow and best method to see is to output them directly...to log perhaps...or to watch them in debugger.

    Ps. is StretchDIBits() call successfull at all??? Try checking returned value, it provides number of lines drawn, i think..

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    OK. Fair enough.
    Though I would bewary of modifing the update region in a paint struct, as windows may still use it later in the EndPaint(). (more important in other functions)

    ps.rcPaint.left + g_iScrollX,
    ps.rcPaint.top + g_iScrollY, // not sure but I would check the scale is correct ie size on screen is same as size in image.

    Is g_iScrollX in logical units or a percentage of the scrollable area?
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  7. #7
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    Never mind. There appears to be some internal "feature" of DIB functions that prevent them from being used for active redrawing (I changed my code so the DIB was put into a bitmap and then BitBlted and it worked without problems).

    With larger images I could see the redraw with the DIB functions, whereas with BitBlting it was smooth. Oh well.

Popular pages Recent additions subscribe to a feed