The MASM Forum

Projects => Easy Code IDE 32/64-bit => Topic started by: K_F on December 28, 2013, 07:22:30 PM

Title: Resizing background picture in MDI client ?
Post by: K_F on December 28, 2013, 07:22:30 PM
This is in the MDI WinMain proc.. where I pick up any size changes in the main window, then attempt to change/stretch the background picture.
This little sequence fails to resize (SetWidth and SetHeight) the bmp (resource) picture.
I'd assume the hBmp handle is valid ?

Is this the right way to do it (easycode) or, does one have to go the DC method route

Quote
   .elseif uMsg == WM_SIZE

      xor      eax, eax
      LoWord   lParam
      mov      iWidth, eax
      xor      eax, eax
      HiWord   lParam
      mov      iHeight, eax


      invoke   GetMDIClient, hWnd
      mov      hClient, eax
      .if   eax != NULL

         invoke   GetPicture, hClient
         .if   eax != NULL
            mov      hBmp, eax

            invoke   SetWidth, hBmp, iWidth
            .if   eax == FALSE
               mov      eax, iWidth
               invoke   dwtoa, eax, ADDR sz_DW1
               Invoke MessageBox, hWnd, ADDR sz_DW1, TextAddr("SetWidth Fail"), MB_OK
            .endif

            invoke   SetHeight, hBmp, iHeight
            .if   eax == FALSE
               mov      eax, iHeight
               invoke   dwtoa, eax, ADDR sz_DW1
               Invoke MessageBox, hWnd, ADDR sz_DW1, TextAddr("SetHeight FAIL"), MB_OK
            .endif

         .else
            invoke   dwtoa, eax, ADDR sz_DW1
            Invoke MessageBox, hWnd, ADDR sz_DW1, TextAddr("GetPicture Fail"), MB_OK
         .endif
      .else
            invoke   dwtoa, eax, ADDR sz_DW1
            Invoke MessageBox, hWnd, ADDR sz_DW1, TextAddr("GetMDIClient Fail"), MB_OK
      .endif

Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 28, 2013, 10:44:35 PM
i wouldn't change the size of anything   :P

1) during WM_SIZE, store width and height into a _SIZE structure
    you only need to update the structure if wParam is either SIZE_MAXIMIZED or SIZE_RESTORED
2) during WM_PAINT, StretchBlt the working image into a memory DC that is sized the same as the frame window client
    BitBlt from the memory DC to the window DC, only that portion that is requested by the RECT in PAINTSTRUCT

because you are always painting the entire client, use a NULL_BRUSH in the frame class background color

voila - no flicker
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 29, 2013, 03:08:05 AM
ah Ok :)
I tried 2) but with no results... maybe I'm not doing it right..

I'll carry on pluggin...
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 29, 2013, 04:41:57 AM
it's been a while, but i think there are 3 "tiers" in the MDI hierarchy, Frame, Client, Child
i think the Frame window is the one you want
let me see what i can do   :P
Title: Re: Resizing background picture in MDI client ?
Post by: rsala on December 29, 2013, 07:01:05 AM
Hi,

The SetWidth and SetHeight methods are for resizing windows and child controls. You can not resize a bitmap with them.

First of all, intercept the WM_ERASEBKGND and just return TRUE for no further processing:

.ElseIf uMsg == WM_ERASEBKGND
    Mov Eax, TRUE
    Ret


Then intercept the WM_PAINT message and draw any picture you like following the dendave instructions. Finally, also return TRUE for no further processing:

.ElseIf uMsg == WM_PAINT
    ; Draw the picture
    Mov Eax, TRUE
    Ret



Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 29, 2013, 08:11:11 AM
what is the color-depth (bits per pixel) of your BMP image ?
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 29, 2013, 05:31:24 PM
Hi, The SetWidth and SetHeight methods are for resizing windows and child controls. You can not resize a bitmap with them.
I thought it could as I was playing with the MDI picture property/object.. which is a bitmap ? Can I put a JPG (or other pic format) file there then ?

Easycode help file on SetWidth/SetHeight
Quote
REMARKS: The lHeight value is intepreted as pixels or twips units depending on the ScaleMode property. For Window, MDIWindow and Picture objects it depends on its own ScaleMode property, while for any other object it depends on the ScaleMode property of its parent (if its parent is a Window, MDIWindow or Picture), or its first ascendant having the ScaleMode property.

@Dave.. 8Bits at the moment..

 :t

Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 29, 2013, 06:53:18 PM
ok - i see where the issue is - lol

as i mentioned earlier, the MDI hierarchy looks like this
Code: [Select]
Frame
----MDIClient
    ----MDIChild
    ----MDIChild

the MDIClient is a predefined system class
the background brush color is always COLOR_APPWORKSPACE

in other words, whatever you paint into the client area of the Frame window is overdrawn by the MDIClient window

now, if we just wanted to change the color, we could probably do it with SetClassLong
but i think to paint an image, we have to subclass the MDIClient window

i hate subclassing system classes   :lol:
you're always leaving yourself vulnerable to changes in different versions of windows (especially win7 AeroGlass theme)
in fact, i have an app where i wanted special buttons
rather than subclassing the (damned) button class, i wrote my own "DaveButton" class/window procedure - lol
i don't want to get into that for the MDIClient, although it could be done
so, we'll try subclassing and test it on different OS versions   :(
Title: Re: Resizing background picture in MDI client ?
Post by: TWell on December 29, 2013, 08:35:47 PM
After downloading that MDI example, nothing to say to this topic :icon_confused:
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 29, 2013, 09:21:00 PM
that doesn't seem to work like i think it ought to   :P
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 30, 2013, 05:56:17 AM
I've reverted back to a simple visual window and have it working...
The Zip file (easycode project) is a bit large as I'm using a 800KB bmp file

I made a mistake in not using the hInstance on the LoadBitMap, and used hWnd instead  :icon_eek:
I also had to Invalidate the Client area as it was not BLT'ing to the whole area.
I'll now work backwards towards the MDI client background...
 :biggrin: :lol:

Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 30, 2013, 06:32:17 AM
it's big because it's a 24-bit image   :P

but - CPU usage is almost 50%
you may be replying to WM_PAINT without validating the rectangle (happens if BeginPaint/EndPaint aren't used)
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 30, 2013, 06:44:00 AM
Thanks.. I'll look at that
:)
Mine's sitting at 13%.. that's a bit high isn't it ??
What normal CPU usage for an idling application... ?
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 30, 2013, 07:19:45 AM
once the picture has been painted, it should go to near 0

there are a couple ways to deal with it
in the WM_PAINT code, call BeginPaint/EndPaint (if needed)
if those aren't needed, you can call ValidateRect with NULL as lpRect
another way is to pass to default proc after painting - it validates the rectangle, also
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 30, 2013, 07:28:49 AM
Found it..

It's this...
invoke   InvalidateRect ,hWnd, NULL, TRUE   ;Redraw the whole client area, instead of a portion


but without this, the background is not drawn properly !!
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 30, 2013, 08:06:34 AM
Solved.. added a WM_SIZE section
CPU usage doesn't even feature on idle, and around 1.5% max on full throttle -and when I'm whipping the mouse around like crazy it's about 5%
Quote
   ;------------------------------------------------
   ;
   ;------------------------------------------------
   .ElseIf uMsg == WM_ERASEBKGND
      Return   TRUE                        ;

   .ElseIf   uMsg ==   WM_PAINT
        invoke   BeginPaint, hWnd, ADDR ps
        mov      hDC,eax

      invoke   GetClientRect, hWnd, ADDR Rct

       invoke   StretchBlt, hDC,0,0,ps.rcPaint.right,ps.rcPaint.bottom,
                         memDC,0,0,700,390,SRCCOPY

        invoke   EndPaint, hWnd,ADDR ps
      Return   TRUE                        ;


   .Elseif uMsg == WM_SIZE
        invoke   GetDC, hWnd                     ;Lets get a Display Context for the
        mov      hDC, eax                     ;hWnd Client area.

      invoke   GetClientRect, hWnd, ADDR Rct

       invoke   StretchBlt, hDC,0,0,Rct.right,Rct.bottom,
                         memDC,0,0,700,390,SRCCOPY

      invoke   ReleaseDC,hWnd,hDC
      Return   TRUE                        ;
                        ;

Thanks for the help..
 :t :t :t
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 30, 2013, 09:14:02 AM
perhaps you misunderstood me
you use InvalidateRect/InvalidateRgn to cause all or a portion of the client to be added to the update region

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145003%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145003%28v=vs.85%29.aspx)

ValidateRect/ValidateRgn do the opposite - they remove a portion from the update region
in other words, they tell the OS that part is ok as is, or has been updated

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145194%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145194%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145195%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145195%28v=vs.85%29.aspx)

the problem with the CPU running like that is that it continually sends WM_PAINT messages
because it thinks it still needs to be updated
so - when you draw it, you want to use ValidateRect   :t
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 30, 2013, 09:18:19 AM
as for WM_SIZE....
because it's an MDI window, some messages that are sent to the frame proc must exit via DefFrameProc,
even if you have handled them - this is so that the MDIClient proc will also get a chance to work it's magic

WM_SIZE is one of those messages
so, do not RET with EAX = 0 when done processing WM_SIZE
instead, pass it to DefFrameProc (the value in EAX doesn't matter)

WM_COMMAND is similar
if you process a menu click - fine, return 0
but, if it's a menu click that is not one of your menu ID's, send it to DefFrameProc
otherwise, the menu that handles MDIChildren won't be updated or allowed to select different windows
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 30, 2013, 11:32:58 AM
this one seems to work under XP
we need someone to test it under Windows 7, with and without Aero Glass theme

rather than processing WM_PAINT, i set the MDIClient class background to NULL and process WM_ERASEBKGND   :P
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 30, 2013, 04:47:10 PM
perhaps you misunderstood me
you use InvalidateRect/InvalidateRgn to cause all or a portion of the client to be added to the update region

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145003%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145003%28v=vs.85%29.aspx)

ValidateRect/ValidateRgn do the opposite - they remove a portion from the update region
in other words, they tell the OS that part is ok as is, or has been updated

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145194%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145194%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145195%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145195%28v=vs.85%29.aspx)

the problem with the CPU running like that is that it continually sends WM_PAINT messages
because it thinks it still needs to be updated
so - when you draw it, you want to use ValidateRect   :t
I'm with that..  :biggrin:
I got rid of the Invalidate... but the Validate's didn't work properly either, so with WM_SIZE I didn't have to use any of them.
This is with the simple window though... I'll start back on the MDI window later today..
 :t
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 30, 2013, 04:57:10 PM
New wndProc.. (simple window)
Quote
;------------------------------------------------------------------------------
;
;------------------------------------------------------------------------------
Window1Procedure Proc hWnd:HWND, uMsg:ULONG, wParam:WPARAM, lParam:LPARAM



   ;------------------------------------------------
   ;Call me Lord Creator
   ;------------------------------------------------
   .If uMsg == WM_CREATE

      invoke   GetModuleHandle, NULL            ;Need the App Instance for the
      mov      hInst, eax                     ;Bitmap load, Otherwise the
        invoke   LoadBitmap, hInst, IDB_BMP         ;BMP does not appear.
        mov      hBmp, eax                     ;BMP handle

        invoke   GetDC, hWnd                     ;Lets get a Display Context for the
        mov      hDC, eax                     ;hWnd Client area.

        invoke   CreateCompatibleDC, hDC             ;Lets also get a 'duplicate' DC in memory
        mov    memDC,eax                     ;You BLT from here to the window

        invoke   SelectObject, memDC, hBmp           ;'put' the bitmap into the 'back' DC

        invoke   ReleaseDC, hWnd, hDC                ;release the window's dc again


   ;------------------------------------------------
   ;
   ;------------------------------------------------
   .ElseIf   uMsg ==   WM_PAINT
        invoke   BeginPaint, hWnd, ADDR ps
        mov      hDC,eax

      invoke   GetClientRect, hWnd, ADDR Rct

       invoke   StretchBlt, hDC,0,0,Rct.right,Rct.bottom,
                         memDC,0,0,700,390,SRCCOPY

        invoke   EndPaint, hWnd,ADDR ps
;      Return   TRUE                        ;


   .Elseif uMsg == WM_SIZE
        invoke   GetDC, hWnd                     ;Lets get a Display Context for the
        mov      hDC, eax                     ;hWnd Client area.

      invoke   GetClientRect, hWnd, ADDR Rct

       invoke   StretchBlt, hDC,0,0,Rct.right,Rct.bottom,
                         memDC,0,0,700,390,SRCCOPY

      invoke   ReleaseDC,hWnd,hDC
;      Return   TRUE                        ;


   ;------------------------------------------------
   ;
   ;------------------------------------------------
   .ElseIf uMsg == WM_CLOSE

      Invoke IsModal, hWnd
      .If Eax
         Invoke EndModal, hWnd, IDCANCEL
         Mov Eax, TRUE ;Return TRUE
         Ret
      .EndIf
   .EndIf

   Xor Eax, Eax   ;Return FALSE
   Ret
Window1Procedure EndP
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 30, 2013, 09:30:16 PM
did you try the program i posted ?
Title: Re: Resizing background picture in MDI client ?
Post by: six_L on December 31, 2013, 03:00:55 AM
Quote
we need someone to test it under Windows 7, with and without Aero Glass theme
i tested that it's ok under windows 7 p.
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 31, 2013, 03:43:16 AM
did you try the program i posted ?
Yes it worked .. very neat,

I looked at it and used similar methods to come up with this.. which works 'so far'  :biggrin:
 :t
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 31, 2013, 06:56:58 AM
Goto thinking... miracles happen  :icon_mrgreen:

MSDN says that uMsg==WM_ERASEBKGND is sent by WM_PAINT or something similar.

So I thought.. I'm painting the background 2x... So I deleted the WM_PAINT section.. and all works the same...so far

Wierd ??
an old dog can still learn new tricks

Just comment out the WM_PAINT section..
Quote
;   .ElseIf   uMsg ==   WM_PAINT
;        invoke   BeginPaint, hClient, ADDR ps      ;MDI Client as usual
;        mov      hDC,eax                        ;

;      invoke   GetClientRect, hClient, ADDR Rct   ;We want to redraw the whole client
;                                       ;area so we use the RECT parameters
;                                       ;instead of the PAINTSTRUCT rect.
;                                       ;The PS rect sometimes does not give
;                                       ;you the whole client area.

;       invoke   StretchBlt, hDC,0,0,Rct.right,Rct.bottom,   ;Scale the original bitmap
;                         memDC,0,0,560,316,SRCCOPY         ;into the MDI client area

;        invoke   EndPaint, hClient,ADDR ps         ;Goodbye to MDI cleint DC

Although it's not clear in MSDN.. it seems that uMsg==WM_ERASEBKGND is sent whenever a window portion is 'Invalidated'.
Placing the draw client under the  uMsg==WM_ERASEBKGND section  seems to work OK..
Anybody got other ideas on this ?
Title: Re: Resizing background picture in MDI client ?
Post by: dedndave on December 31, 2013, 07:11:22 AM
if you look at my code.....
subclass the MDIClient control (window)
use SetClassLong to set the MDIClient background brush to NULL (up to you to erase the background)
in the ClientProc, i handle the WM_ERASEBKGND message, not WM_PAINT

advantages....
no BeginPaint/EndPaint
no PAINTSTRUCT (the hDC for WM_ERASEBKGND is in wParam)

i also set the background brush to NULL in the frame class - not sure if it really matters, though

if you notice, there is no flicker when sizing the window
Title: Re: Resizing background picture in MDI client ?
Post by: K_F on December 31, 2013, 07:29:11 AM
Funny enough.. although I didn't intend it.. I think I ended up doing 'exactly' what you've done .. maybe adapted to easycode without subclassing.
Well.. that's at least what i think I've done  :P

But I couldn't have done it without your example..
I picked up on the WM_ERASEBKGND here
Thanks
 :t