flat assembler
Message board for the users of flat assembler.

Index > Windows > Drawing in child window.

Author
Thread Post new topic Reply to topic
barmentalisk



Joined: 06 Sep 2005
Posts: 36
barmentalisk 05 Feb 2009, 16:46
There are so many examples of drawing in client area of main window, but I need to draw bitmap in child window and have no idea how to do it.

This code is not all what I need, it is just a template for those, who can help.
On creation of main window, child window is created there. Bitmap now is on main window. How to put it on client area of child window?

Code:
format PE GUI 4.0
entry start

include 'win32a.inc'

  HTCAPTION = 2

section '.data' data readable writeable

  _class TCHAR 'FASMWIN32',0
  sclass TCHAR 'STATIC',0
  _title TCHAR 'Drawing in child window',0
  _error TCHAR 'error',0

  wc   WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE,NULL,_class

  msg  MSG
  ps   PAINTSTRUCT
  rect RECT
  hstatic  dd  ?
  hBitmap  dd  ?
  hdc      dd  ?
  hMemDC   dd  ?

section '.code' code readable executable

  start:

        invoke  GetModuleHandle,0
        mov     [wc.hInstance],eax
        invoke  LoadIcon,0,IDC_ICON
        mov     [wc.hIcon],eax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],eax
        invoke  RegisterClass,wc
        test    eax,eax
        jz      error

        invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,526,471,NULL,NULL,[wc.hInstance],NULL
        test    eax,eax
        jz      error


  msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp     eax,1
        jb      end_loop
        jne     msg_loop
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
        jmp     msg_loop

  error:
        invoke  MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK

  end_loop:
        invoke  ExitProcess,[msg.wParam]

proc WindowProc hwnd,wmsg,wparam,lparam
        push    ebx esi edi
        mov     eax,[wmsg]
        cmp     eax,WM_CREATE
        je      .wmcreate
        cmp     eax,WM_PAINT
        je      .wmpaint
        cmp     eax,WM_DESTROY
        je      .wmdestroy
        cmp     eax,WM_LBUTTONDOWN
        je      .wmlbuttondown
  .defwndproc:
        invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
        jmp     .finish
  .wmcreate:
        invoke  LoadBitmap,[wc.hInstance],37
        mov     [hBitmap],eax
        invoke  CreateWindowEx,0,sclass,0,WS_VISIBLE+WS_CHILD+WS_DLGFRAME,128,128,326,271,[hwnd],NULL,[wc.hInstance],NULL
        mov     [hstatic],eax
        jmp     .finish
  .wmpaint:
        invoke  BeginPaint,[hwnd],ps
        mov     [hdc],eax

        invoke  CreateCompatibleDC,[hdc]
        mov     [hMemDC],eax
        invoke  SelectObject,[hMemDC],[hBitmap]
        invoke  GetClientRect,[hwnd],rect
        invoke  BitBlt,[hdc],0,0,[rect.right],[rect.bottom],[hMemDC],0,0,SRCCOPY
        invoke  DeleteDC,[hMemDC]

        invoke  EndPaint,[hwnd],ps
        jmp     .finish
  .wmlbuttondown:
        invoke ReleaseCapture
        invoke SendMessage,[hwnd],WM_NCLBUTTONDOWN,HTCAPTION,0
        jmp     .finish
  .wmdestroy:
        invoke  PostQuitMessage,0
        xor     eax,eax
  .finish:
        pop     edi esi ebx
        ret
endp

section '.idata' import data readable writeable

  library gdi32,'GDI32.DLL',\
          kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\gdi32.inc'
  include 'api\kernel32.inc'
  include 'api\user32.inc'

section '.rsrc' resource data readable

  directory RT_BITMAP,bitmaps

  resource bitmaps,\
           37,LANG_NEUTRAL,pict

  bitmap pict,'bitmap.bmp'
    


I used a simple 320x240 bitmap, if something not clear...
Post 05 Feb 2009, 16:46
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 06 Feb 2009, 02:39
Subclass the STATIC and grab its WM_PAINT messages. I like to use WM_ERASEBKGND if the image is the background - no sense in Windows painting a background and then overwriting it - not to mention the fact windows provides hDC, so (BEGIN/END)PAINT aren't needed.
Post 06 Feb 2009, 02:39
View user's profile Send private message Visit poster's website Reply with quote
barmentalisk



Joined: 06 Sep 2005
Posts: 36
barmentalisk 09 Feb 2009, 10:47
bitRAKE, thanks for idea of subclassing! Check, please, if I did it right, - here working code which I get:
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'

  HTCAPTION = 2

section '.data' data readable writeable

  _class TCHAR 'FASMWIN32',0
  sclass TCHAR 'STATIC',0
  _title TCHAR 'Drawing in child window',0
  _error TCHAR 'error',0

  wc   WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE,NULL,_class

  msg        MSG
  ps         PAINTSTRUCT
  rect       RECT
  OldWndproc dd  ?
  hstatic    dd  ?
  hBitmap    dd  ?
  hdc        dd  ?
  hMemDC     dd  ?

section '.code' code readable executable

  start:

        invoke  GetModuleHandle,0
        mov     [wc.hInstance],eax
        invoke  LoadIcon,0,IDC_ICON
        mov     [wc.hIcon],eax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],eax
        invoke  RegisterClass,wc
        test    eax,eax
        jz      error

        invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,526,471,NULL,NULL,[wc.hInstance],NULL
        test    eax,eax
        jz      error


  msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp     eax,1
        jb      end_loop
        jne     msg_loop
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
        jmp     msg_loop

  error:
        invoke  MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK

  end_loop:
        invoke  ExitProcess,[msg.wParam]

proc WindowProc hwnd,wmsg,wparam,lparam
        push    ebx esi edi
        mov     eax,[wmsg]
        cmp     eax,WM_CREATE
        je      .wmcreate
        cmp     eax,WM_PAINT
        je      .wmpaint
        cmp     eax,WM_DESTROY
        je      .wmdestroy
        cmp     eax,WM_LBUTTONDOWN
        je      .wmlbuttondown
  .defwndproc:
        invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
        jmp     .finish
  .wmcreate:
        invoke  LoadBitmap,[wc.hInstance],37
        mov     [hBitmap],eax
        invoke  CreateWindowEx,0,sclass,0,WS_VISIBLE+WS_CHILD+WS_DLGFRAME,128,128,320,240,[hwnd],NULL,[wc.hInstance],NULL
        mov     [hstatic],eax
        ;subclassing
        invoke  SetWindowLong,eax,GWL_WNDPROC,StatWndproc
        mov     [OldWndproc],eax
        jmp     .finish
  .wmpaint:
        invoke  BeginPaint,[hwnd],ps
        mov     [hdc],eax

        invoke  CreateCompatibleDC,[hdc]
        mov     [hMemDC],eax
        invoke  SelectObject,[hMemDC],[hBitmap]
        invoke  GetClientRect,[hwnd],rect
        invoke  BitBlt,[hdc],0,0,[rect.right],[rect.bottom],[hMemDC],0,0,SRCCOPY
        invoke  DeleteDC,[hMemDC]

        invoke  EndPaint,[hwnd],ps
        jmp     .finish
  .wmlbuttondown:
        invoke ReleaseCapture
        invoke SendMessage,[hwnd],WM_NCLBUTTONDOWN,HTCAPTION,0
        jmp     .finish
  .wmdestroy:
        invoke  PostQuitMessage,0
        xor     eax,eax
  .finish:
        pop     edi esi ebx
        ret
endp

;paint static window
proc StatWndproc hwnd,wmsg,wparam,lparam
        push    ebx esi edi

        cmp     [wmsg],WM_PAINT
        jne     .finish

        invoke  BeginPaint,[hwnd],ps
        mov     [hdc],eax

        invoke  CreateCompatibleDC,[hdc]
        mov     [hMemDC],eax
        invoke  SelectObject,[hMemDC],[hBitmap]
        invoke  GetClientRect,[hwnd],rect
        invoke  BitBlt,[hdc],0,0,[rect.right],[rect.bottom],[hMemDC],0,0,SRCCOPY
        invoke  DeleteDC,[hMemDC]

        invoke  EndPaint,[hwnd],ps

  .finish:
        invoke  CallWindowProc,[OldWndproc],[hwnd],[wmsg],[wparam],[lparam]
        pop     edi esi ebx
        ret
endp

section '.idata' import data readable writeable

  library gdi32,'GDI32.DLL',\
          kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\gdi32.inc'
  include 'api\kernel32.inc'
  include 'api\user32.inc'

section '.rsrc' resource data readable

  directory RT_BITMAP,bitmaps

  resource bitmaps,\
           37,LANG_NEUTRAL,pict

  bitmap pict,'bitmap.bmp'
    


But I didnot understand anything else, what you wrote. I even didnot understand should I sent or get WM_ERASEBKGND message =).
Could you describe this better, or put some short example?
Post 09 Feb 2009, 10:47
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 09 Feb 2009, 11:45
Essentially, the difference is:
Code:
   .wmerasebkgnd:
        invoke  CreateCompatibleDC,[wparam]
        mov     [hMemDC],eax
        invoke  SelectObject,[hMemDC],[hBitmap]
        invoke  GetClientRect,[hwnd],rect
        invoke  BitBlt,[wparam],0,0,[rect.right],[rect.bottom],[hMemDC],0,0,SRCCOPY
        invoke  DeleteDC,[hMemDC]
       mov     eax,1 ; background updated
        jmp     .finish
    
Windows provides hDC in wparam. Non-zero return indicates background has been updated.

...verses:
Code:
  .wmpaint:
        invoke  BeginPaint,[hwnd],ps
        mov     [hdc],eax

        invoke  CreateCompatibleDC,[hdc]
        mov     [hMemDC],eax
        invoke  SelectObject,[hMemDC],[hBitmap]
        invoke  GetClientRect,[hwnd],rect
        invoke  BitBlt,[hdc],0,0,[rect.right],[rect.bottom],[hMemDC],0,0,SRCCOPY
        invoke  DeleteDC,[hMemDC]

        invoke  EndPaint,[hwnd],ps
        jmp     .finish    
...this works on the main window, but WM_ERASEBKGND doesn't appear to be sent to the static control - instead WM_CTLCOLORSTATIC would need to be handled by the parent (hDC is available here as well). Your sub-classing works well. I would like to draw attention to the three message handling techniques with sub-classing:

1) process without calling OldWndproc
2) process and then call OldWndproc
3) call OldWndproc and then change result

When sub-classing it's important to choose the approach which is appropriate (or a combination of 2 and 3).

I have an example posted:
http://board.flatassembler.net/topic.php?t=7983


This works, too:
Code:
_37 TCHAR '#37',0
...
invoke  CreateWindowEx,0,sclass,_37,WS_VISIBLE+WS_CHILD+SS_BITMAP,128,128,0,0,[hwnd],0,[wc.hInstance],0    
Smile
Post 09 Feb 2009, 11:45
View user's profile Send private message Visit poster's website Reply with quote
barmentalisk



Joined: 06 Sep 2005
Posts: 36
barmentalisk 09 Feb 2009, 14:08
Aha, I catch the idea. You tell about the way to paint window faster, but only if it is the main window and only if the bitmap is background.
Thanks for this, it is rather usefull !

And about sub-classing message handling you mean that, after painting in my proc, there is no reason to call default system procedure?
Post 09 Feb 2009, 14:08
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 09 Feb 2009, 19:24
barmentalisk wrote:
And about sub-classing message handling you mean that, after painting in my proc, there is no reason to call default system procedure?
In this specific instance it doesn't do anything. Yet, we can imagine a simple program about box which consists of a graphic, and we don't want to edit the program version number in the graphic every time a change happens. So, the static default handler would display the version number on top after the sub-classing handler.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 09 Feb 2009, 19:24
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.