News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Force background erase of a static control

Started by jj2007, October 28, 2011, 09:27:14 PM

Previous topic - Next topic

jj2007

I am working on an image viewer (here) and stumbled over something strange: When I display icons, they sometimes do not erase the background of the static control that I use as a canvas. It works fine for jpg, png, gif etc, but the icons are stubborn.

Question: How would you force a background erase on a static control? I tried various options in the WM_PAINT handler but no success :(

  CASE WM_PAINT
   invoke GetClientRect, hWnd, addr rc
   invoke MoveWindow, hStatic, 0, 0, rc.right, rc.bottom, 0
   invoke InvalidateRect, hStatic, 0, 0

dedndave

icons have transparent pixels, no ?

GIF and PNG images can also have transparent pixels - maybe you're not testing with such an image


jj2007

Quote from: dedndave on October 28, 2011, 09:38:36 PM
icons have transparent pixels, no ?

I guess so, yes, but that is not a good excuse for not erasing the background after an InvalidateRect... ::)

What's that cute globe about?

dedndave

oh - ok
how about the BkMode for the DC ?
what value are you using for the hrgbBackground of WNDCLASSEX when you register the window ?
or - if it's a system class - GetWindowLong

sounds like NULL_BRUSH is in there someplace

the globes are GIF/PNG transparencies   :P

jj2007

Quote from: dedndave on October 28, 2011, 09:44:37 PM
how about the BkMode for the DC ?

Sounds promising, thanks. Will test it when I wake up tomorrow :8)

qWord

Quote from: jj2007 on October 28, 2011, 09:27:14 PM invoke InvalidateRect, hStatic, 0, 0
Have you tried this one:
Quoteinvoke InvalidateRect, hStatic, 0, 1
:bg

BTW: If you want to draw an image, whereas one color should be transparent, you can use image attributes:
Quote.if rv(GdipCreateImageAttributes,ADDR imgAttr) != GpStatusOk
    ; error
.endif
.if rv(GdipSetImageAttributesColorKeys,imgAttr,ColorAdjustTypeDefault,1,Color,Color) != GpStatusOk
    invoke GdipDisposeImageAttributes,imgAttr
    ; error
.endif
;...
invoke GdipDrawImageRectRectI,graphics,image,destX,destY,destWidth,destHeight,srcX,srcY,SrcWidth,SrcHeight,UnitPixel,imgAttr,0,0
;...
invoke GdipDisposeImageAttributes,imgAttr
FPU in a trice: SmplMath
It's that simple!

jj2007

Quote from: qWord on October 28, 2011, 11:05:40 PM
Quote from: jj2007 on October 28, 2011, 09:27:14 PM invoke InvalidateRect, hStatic, 0, 0
Have you tried this one:
Quoteinvoke InvalidateRect, hStatic, 0, 1
:bg
Yes, no effect :toothy

Quote
BTW: If you want to draw an image, whereas one color should be transparent, you can use image attributes:
Quote.if rv(GdipCreateImageAttributes,ADDR imgAttr) != GpStatusOk
    ; error
.endif
.if rv(GdipSetImageAttributesColorKeys,imgAttr,ColorAdjustTypeDefault,1,Color,Color) != GpStatusOk
    invoke GdipDisposeImageAttributes,imgAttr
    ; error
.endif
;...
invoke GdipDrawImageRectRectI,graphics,image,destX,destY,destWidth,destHeight,srcX,srcY,SrcWidth,SrcHeight,UnitPixel,imgAttr,0,0
;...
invoke GdipDisposeImageAttributes,imgAttr
Nice find, qWord. For the time being, I will leave this tricks to the macro haters, although adding two paras would not bloat the code excessively, either: The whole GdiPlus part stands currently at 253 bytes :wink

dedndave

Jochen - give this a try...

        INVOKE  InvalidateRgn,hWnd,NULL,TRUE
        INVOKE  UpdateWindow,hWnd


you may not need UpdateWindow   :P

fearless

Not sure if this would work:
.elseif eax == WM_CTLCOLORSTATIC
invoke GetWindowLong,lParam,GWL_ID       
.if eax == IDC_ICON ; static holder for icon
invoke SetBkMode,wParam,HOLLOW_BRUSH
invoke GetStockObject,HOLLOW_BRUSH
ret
.endif


or even just:
.elseif eax == WM_CTLCOLORSTATIC
invoke GetWindowLong,lParam,GWL_ID       
.if eax == IDC_ICON ; static holder for icon
ret
.endif
ƒearless

ToutEnMasm


jj2007

Thanks, Dave, Fearless & ToutEnMasm. The problem is that the message never arrives...

Quote      invoke InvalidateRect, edi, 0, 1   ; prepare for painting, erase background
      sub esp, PAINTSTRUCT   ; create a local ps
      invoke BeginPaint, edi, esp
      invoke GdipCreateFromHDC, eax, esi  ; create graphics object
      sub esp, RECT   ; create a slot of paras for GdipDrawImageRectI
      invoke GetClientRect, edi, esp   ; use full control
      push [ebx]   ; imageObj
      push [esi]   ; graphicsObj; now stretch or draw image - see GdiPlus error codes
      call GdipDrawImageRectI   ; invoke GdipDrawImageRectI, [esi], [ebx], [eax.RECT.left, top, right, bottom]
      invoke GdipDeleteGraphics, [esi]   ; release graphics object
      invoke EndPaint, edi, esp
      add esp, PAINTSTRUCT   ; release local ps
[/color]

The code works absolutely fine, no error messages, except that the background apparently does not get erased. However, if I disable the snippet above, the WM_CTLCOLORSTATIC message is there (and, well, the image is lost :bg).

Apparently, it is not the GdiPlus stuff but rather the BeginPaint/EndPaint sequence itself that blocks the background message :(

dedndave

i have never seen InvalidateRect used inside the WM_PAINT handler
that makes no sense
generally, the function is used to cause a WM_PAINT (and erase bg) sequence

QuoteThe invalidated areas accumulate in the update region until the region is processed when the next
WM_PAINT message occurs or until the region is validated by using the ValidateRect or ValidateRgn function.

The system sends a WM_PAINT message to a window whenever its update region is not
empty and there are no other messages in the application queue for that window.

If the bErase parameter is TRUE for any part of the update region, the
background is erased in the entire region, not just in the specified part.

jj2007

Quote from: dedndave on October 29, 2011, 05:41:04 PM
i have never seen InvalidateRect used inside the WM_PAINT handler
that makes no sense
generally, the function is used to cause a WM_PAINT (and erase bg) sequence

Thanks, Dave. I had erroneously thought that the WM_PAINT handler of the main window can be used to force a paint message on the children. Wrong...
FillRect is one solution, but for non-transparent images it means flicker, so it is probably better to keep it outside the wrapper.

dedndave

you got me thinking - here is how i think it works   :P
WM_PAINT is first sent to the parent window
it is then sent "upwards" in the Z-order chain to the child windows, which i guess would include controls
maybe the problem you are experiencing is related to the value you return in EAX

and - what do you do for WM_ERASEBKGND ?
if it does not exit with the correct return value or does not go to DefWindowProc, you may have troubles