To the Ineffable All,

    Here is a nice problem.  The program snippet below shows code for drawing a rectangle around the client area and filling it with a color.  Works fine, except when the window is maximized by the size box.  Then it only paints up to the limits of the previous size.  Dragging the window to the full size works fine.  See the enclosed ZIP for an executable of this program.  Works OK on Windows ME, doesn't work on Windows XP.  I swapped monitors between a LCD and a CRT type screen to no avail.  I am open to revelation.  Ratch


;*****WINDOW MESSAGES***********************************************************
;-------------------------------------------------------------------------------
CREATE_WM:

XOR EAX,EAX
JMP MAINCBRET

;-------------------------------------------------------------------------------
SIZE_WM:
MOVZX EAX,DX
SHR EDX,16
MOV ,EAX ;LOWORD (lParam)
MOV ,EDX ;HIWORD (lParam)


MOV EDI,EAX

INVOKE CreateSolidBrush,RGB(0,255,0)
MOV ,EAX

 
INVOKE CreateRectRgn,EBP,EBP,,
MOV ,EAX

INVOKE GetDC,ESI        ;ESI=hwnd
MOV ,EAX

INVOKE FillRgn,,,

INVOKE UpdateWindow,ESI

INVOKE DeleteObject,
INVOKE DeleteObject,
INVOKE ReleaseDC,ESI,

XOR EAX,EAX
JMP MAINCBRET

;-------------------------------------------------------------------------------
DESTROY_WM:
INVOKE PostQuitMessage,EBP    ;EBP=0

XOR EAX,EAX
JMP MAINCBRET
;-------------------------------------------------------------------------------
Attachments:
Posted on 2005-11-16 16:44:34 by Ratch
Have you tried running it in a debugger and putting a breakpoint on the WM_SIZE code, step through and see what happens?
Posted on 2005-11-17 00:50:32 by f0dder
f0dder,
    I certainly have done so.  The WM_SIZE message comes through with all the right numbers  in lParam. All the API calls are returned without error.  But when control is returned back to the O/S, bad things happen in Windows XP, and correct results come about when executed on a Windows ME box.  Did you try the executable on your machine?  What O/S are you running?  Ratch
Posted on 2005-11-17 01:11:48 by Ratch
WinXP SP2... and I get the same errors here. Could you attach the full source so I can assemble and play around?
Posted on 2005-11-17 01:36:03 by f0dder
The weird thing is that it works fine on my Win xp..
Posted on 2005-11-17 02:23:43 by roticv
Do you remember register preservation? I see ESI,EDI,EBP all used in the code...
Posted on 2005-11-17 02:27:44 by f0dder
You should probably be doing the drawing in WM_PAINT and calling InvalidateRect from the WM_SIZE messages. I "believe" thats a more correct way.
Posted on 2005-11-17 06:41:08 by Eóin
Eoin is right, UpdateWindow is actually pretty useless, in most cases it will do nothing. Not validating your window is problematic, too (you'll get 99% cpu usage for nothing).
I recommend having CS_HREDRAW and CS_VREDRAW in the wndclassex's style, also having hbrBackground=0.


;*****WINDOW MESSAGES***********************************************************
;-------------------------------------------------------------------------------
CREATE_WM:

XOR EAX,EAX
JMP MAINCBRET

;-------------------------------------------------------------------------------
SIZE_WM:
MOVZX EAX,DX
SHR EDX,16
MOV ,EAX ;LOWORD (lParam)
MOV ,EDX ;HIWORD (lParam)
invoke InvalidateRect,esi,0,0
xor eax,eax
jmp MAINCBRET

PAINT_WM:
lea eax,ps ; a local PAINTSTRUCT var
invoke BeginPaint,esi,eax

;-----[ create pen and brush ]------------------------\
INVOKE CreateSolidBrush,RGB(0,255,0)
MOV ,EAX
invoke CreatePen,PS_SOLID,1,RGB(255,0,0) ; red pen
mov ,eax

; select them into this DC, preserve previous ones
invoke SelectObject,,
mov ,eax
invoke SelectObject,,
mov ,eax
;-----------------------------------------------------/ 

; draw the rectangle
invoke Rectangle,,0,0,,

;-----[ restore pen and brush ]---------------------\
invoke SelectObject,,
invoke SelectObject,,
invoke DeleteObject,
invoke DeleteObject,
;---------------------------------------------------/

lea eax,ps
invoke EndPaint,esi,eax

XOR EAX,EAX
JMP MAINCBRET

;-------------------------------------------------------------------------------
DESTROY_WM:
INVOKE PostQuitMessage,EBP    ;EBP=0

XOR EAX,EAX
JMP MAINCBRET
;-------------------------------------------------------------------------------

Posted on 2005-11-17 09:01:38 by Ultrano
f0dder,

WinXP SP2... and I get the same errors here. Could you attach the full source so I can assemble and play around?

     I would have to include all my MACROS used in this prog.  The code snippet is simple enough for you drop into your test bed with only a slight amount of modification.


Do you remember register preservation? I see ESI,EDI,EBP all used in the code...


     Yes, I preserve and restore EBX,EBP,ESI,EDI. Ratch

Eóin,

You should probably be doing the drawing in WM_PAINT and calling InvalidateRect from the WM_SIZE messages. I "believe" thats a more correct way.


     That is what I finally did.  Strange that this code works on my previous Win ME box and goes belly up on my new XP box.  One other tip.  If you modify the stack pointer directly, for instance subtracting the ESP to make some local variable space, make sure that you do it in DWORD increments.  The text metric structure TEXTMETRIC is 73 bytes in size.  If one subtracts 73 from ESP, you are in for a rough ride with XP.  One needs to subtract 76 instead.  Off DWORD stack manipulations work fine with Win ME, however.  Ratch

     




Posted on 2005-11-17 09:15:20 by Ratch
Another thought is that if you specify the CS_OWNDC style when registering the Windows Class then the DC should be valid always and not just during the WM_PAINT message between BeginPaint and EndPaint.
Posted on 2005-11-17 09:24:00 by Eóin

One other tip.  If you modify the stack pointer directly, for instance subtracting the ESP to make some local variable space, make sure that you do it in DWORD increments.

Yup, and not just with XP - afaik all flavours of NT require DWORD aligned stack.
Posted on 2005-11-17 09:31:33 by f0dder
Ultrano,

Eoin is right, UpdateWindow is actually pretty useless, in most cases it will do nothing. Not validating your window is problematic, too (you'll get 99% cpu usage for nothing).
I recommend having CS_HREDRAW and CS_VREDRAW in the wndclassex's style, also having hbrBackground=0.


    Eóin is correct about painting the window within the WM_PAINT routine instead of the WM_SIZE routine.

    UpdateWindow is useful.  It causes Windows to call the Win Proc immediately with a WM_PAINT message, instead of putting it on the lower priority message queue.  Whether that solves the problem is another matter.

    Since scrolling is not an issue,  CS_HREDRAW and CS_VREDRAW are not necessary or needed.

    I use COLOR_WINDOW+1 for my background.  When I tried 0, the program hung up.  Ratch

   
Posted on 2005-11-17 09:55:14 by Ratch
Eóin,


Another thought is that if you specify the CS_OWNDC style when registering the Windows Class then the DC should be valid always and not just during the WM_PAINT message between BeginPaint and EndPaint


    Hmm. I believe that is a solution in search of a problem.  Obtaining the device constant for the window is not an issue.  Ratch
Posted on 2005-11-17 10:01:42 by Ratch
o_O CS_H/VREDRAW and scrolling ?!
These two flags specify that when your window is RESIZED, its whole window gets invalidated. Which is actually what you need. And which will save you handing the WM_SIZE...

hbrBackground=0 doesn't hang your app, your test app was wrong. It simply skips drawing the background - which is the first step to flicker-free user interface.
Posted on 2005-11-17 11:26:19 by Ultrano
Ultrano,
    You are right about CS_H/VREDRAW pertaining to window movement and sizing, and not scrolling.  I was thinking about WS_V/HSCROLL.  However, my prob code did contain CS_H/VREDRAW, so that did not solve anything.
    I was letting Windows process the WM_PAINT messages by default.  Therefore when  hbrBackground=0 was coded, no background was painted.  I mistook that to be a program hang.  If hbrBackground is specified with a color, then the background does get painted even when Windows processes the WM_PAINT message by default.
    Anyway, all the problems go away if the user does the painting within the WM_PAINT processing instead of WM_SIZE.  Still, it's strange that WinME gets away with WM_SIZE screen painting, and WinXP does not.  Ratch
Posted on 2005-11-17 16:49:21 by Ratch
Yeah, such differences between Win OSes are funny :). Fortunately, they all obey the rules, explained in MSDN/Platform SDK ^^
Posted on 2005-11-18 01:51:41 by Ultrano