News:

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

Window help

Started by RuiLoureiro, November 16, 2007, 12:38:51 PM

Previous topic - Next topic

hutch--

Rui,

Unless you are using a predefined class like a control, you must create a class for your own window using the WNDCLASSEX structure and RegisterClassEx().

Create the windows with the "WS_POPUP or WS_CAPTION" styles for a windows with a titlebar and no buttons.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

RuiLoureiro

Quote from: hutch-- on November 19, 2007, 06:50:06 PM
Unless you are using a predefined class like a control, you must create a class for your own window using the WNDCLASSEX structure and RegisterClassEx().

Create the windows with the "WS_POPUP or WS_CAPTION" styles for a windows with a titlebar and no buttons.

Very Good !!!
Hutch, thanky so much ! I am going to work. Have a nice day or night !
RuiLoureiro

RuiLoureiro

#17
Hutch, what's wrong ? The window doesnt open or is closed before CloseExecMsg be called.
When i call SendExecMsg, the window doesnt appear.

.data
; Child Window
;
_ClassChild      db "WinChild", 0               ; class name
_NameChild       db "A executar ...", 0     ; title name
_hWndChild       dd 0                            ; handle
;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
.data?
align 4
_wcChild        WNDCLASSEX <?>
;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
.code
WinMain     proc hInst:DWORD, hPrevInst:DWORD, CmdLine:LPSTR, CmdShow:DWORD
             ;.................................................................
            ;
            ; Preencher a estrutura WNDCLASSEX para a janela CHILD
            ; ----------------------------------------------------
            mov   _wcChild.cbSize,      SIZEOF WNDCLASSEX
            mov   _wcChild.style,       WS_OVERLAPPED or WS_BORDER or WS_CHILD or     WS_POPUP   or   WS_CAPTION

             mov   _wcChild.lpfnWndProc, 0
             mov   _wcChild.cbClsExtra,  NULL
             mov   _wcChild.cbWndExtra,  NULL
             push  _hInstance
             pop   _wcChild.hInstance
             mov   _wcChild.hbrBackground, COLOR_BACKGROUND+1    ; COLOR_WINDOW+1       
             mov   _wcChild.lpszMenuName, 0                              ; menu name in resource file
             mov   _wcChild.lpszClassName, offset _ClassChild          ; name of windows class
            ;
            ; Registar a classe WNDCLASSEX da janela Child
            ; --------------------------------------------------------------
            invoke RegisterClassEx, addr _wcChild                           ; new
;.........................................
        ............................
        ............................
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««
SendExecMsg         proc   
                    pushfd
                    pushad
                    ;
invoke  CreateWindowEx, 300h, offset _ClassChild, offset _NameChild,\
                         WS_BORDER or WS_CHILD or WS_POPUP or WS_CAPTION, \
                         260, 100, 280,  80,\                  ; X,Y + Width, Height pixel
                         _hWndCur, 0h, _hInstance, 0
                    ;
                    mov     _hWndChild, eax
                    ;
                    ;invoke  ShowWindow, _hWndChild, SW_SHOWNORMAL
                    ;
                    popad
                    popfd
                    ret
SendExecMsg         endp
; ««««««««««««««««««««««««««««««««««««««««««««
CloseExecMsg        proc
                    pushfd
                    pushad
                    ;
                    invoke   DestroyWindow, _hWndChild
                    ;
                    popad
                    popfd
                    ret
CloseExecMsg        endp
;*******************************************************
New: CreateWindowEx  returns  0 . Why ? Need a processor ?
;*******************************************************

hutch--

Rui,

Here is a simple example of how to create a child window of the type you require. Look at the childwin code at the end of the source code.

[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

RuiLoureiro

#19
Hutch,
Thank you for the example. I dont know where was the problem but now it works. I have my Child window.
The problem, now is that i print the message, but the system erase the client area and we dont see the message.
Here is my last version. I think you understand in a few seconds what im doing.
Another problem is with the background color of the text  (new: it is solved )
;.................................................................
Amarelo         equ 00FFFFh
;.....................................
.data
_pMsgToSend     dd 0
_hWndChild        dd 0

.data?
_WidthChr           dd ?
                          dd ?
_wcChild        WNDCLASSEX <?>
.code
;..................................................
WinMain     proc hInst:DWORD, hPrevInst:DWORD, CmdLine:LPSTR, CmdShow:DWORD
            ;.................................................................
            ;
            ; Preencher a estrutura WNDCLASSEX para a janela CHILD
            ; ----------------------------------------------------
   Â      mov   _wcChild.cbSize,      SIZEOF WNDCLASSEX
                      mov   _wcChild.style,       CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW
       Â      mov   _wcChild.lpfnWndProc, offset WndProcB
           Â      mov   _wcChild.cbClsExtra,  NULL
   Â      mov   _wcChild.cbWndExtra,  NULL
   Â      push  _hInstance
   Â      pop   _wcChild.hInstance
           Â      mov   _wcChild.hbrBackground, COLOR_BACKGROUND+1  ; COLOR_WINDOW+1       
   Â      mov   _wcChild.lpszMenuName, 0                      ; menu name in resource file
   Â      mov   _wcChild.lpszClassName, offset _ClassChild    ; name of windows class
            ; --------------------------------------------
            ; Registar a classe WNDCLASSEX da janela Child
            ; --------------------------------------------
            invoke RegisterClassEx, addr _wcChild
;....................................
;      other
;--------------------------------------------------------------------
; ««««««« for CHILD WINDOW «««««««««««««««««««««««««««««««««««««
WndProcB        proc    hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
                      pushad                                 
                      ;
                      mov     eax, uMsg
                      cmp     eax, WM_PAINT
                      jne     _eWndProcB
                     ;
                     ; imprime a mensagem
                     ; ----------------------------
                     call       PrPasMsg           
                     ;
_eWndProcB:  popad
                      ;
                      invoke  DefWindowProc, hWnd, uMsg, wParam, lParam
                      ret
WndProcB        endp

;»»»»» In the file saved to a LIB i have »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
SendExecMsg         proc    NMsg:DWORD   
                            pushfd
                            pushad
                            ;
                            cmp     _hWndChild, 0
                            jne     _eSendExecMsg
                   
                            invoke  CreateWindowEx, WS_EX_LEFT,
                                    offset _ClassChild, offset _NameChild,
                                    WS_POPUP or WS_CAPTION,
                                    260, 380, 280,  80,                                 ; X,Y + Wid,Hei pixel
                                    _hWndCur, 0h, _hInstance, 0
                           ;
                           mov     _hWndChild, eax
                           ;
                           invoke  ShowWindow, _hWndChild, SW_SHOW         
;...........................................................................
                    ;
                    ; Get Message from the table
                    ; --------------------------------------
                           mov     esi, offset _TblExecMsg             ; message table   
                           mov     ebx, NMsg
                           cmp     ebx, 0
                            je      _eSendExecMsg
                            ;
                           cmp     ebx, dword ptr [esi - 4]            ; number of messages
                            ja      _eSendExecMsg
                            ;
                            dec     ebx
                            shl       ebx, 2
                            mov     eax, dword ptr [esi + ebx]        ; eax =message pointer
                            mov     _pMsgToSend, eax
                            ;
                            call       PrPasMsg
                            ;
_eSendExecMsg:     popad
                            popfd
                            ret
SendExecMsg         endp
; ----------------------------------------------------------------------------------------------
PrPasMsg        proc 
                    pushad   
                     ;
                     invoke  HideCaret, _hWndChild               ; never show caret
               
                     invoke  GetDC, _hWndChild
                     mov     _hdcChild, eax
                    ;
                    ; calcula comprimento da string
                    ; ----------------------------------------
                    mov      ebx, _pMsgToSend
                    movzx    ecx, byte ptr [ebx - 1]                   
                    invoke   GetTextExtentPoint32, _hdcChild, ebx, ecx, addr _WidthChr
                    ;
                    mov      edx, 280
                    sub       edx, _WidthChr
                    shr        edx, 1
                    mov      _WidthChr, edx
                    ;
                    ; Cor Foreground
                    ; ---------------------
                    invoke   SetTextColor, _hdcChild, Amarelo
                    ;
                    ; Cor Background
                    ; ---------------------
                    invoke  GetSysColor, COLOR_BACKGROUND        ; window background color
                    invoke   SetBkColor, _hdcChild, eax                     
                    ;
                     ; Print Test
                     ; -------------
                     mov      ebx, _pMsgToSend 
                     movzx    ecx, byte ptr [ebx - 1]
                     invoke   TextOut, _hdcChild, _WidthChr, 20, ebx , ecx               

                     invoke  ReleaseDC, _hWndChild, _hdcChild
                     ;
                     popad
                     ret
PrPasMsg        endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««
CloseExecMsg        proc
                           pushfd
                           pushad
                           ;
                          cmp     _hWndChild, 0
                           je      _eCloseExecMsg                  ; is closed -> exit !
                   
                           invoke   DestroyWindow, _hWndChild
                           ;
                           mov     _hWndChild, 0                     
                           ;
_eCloseExecMsg:    popad
                           popfd
                           ret
CloseExecMsg        endp
;.................. END

NEW: the first time i call SendExecMsg, it doesnt show the message. The second and so forth it shows
         How to give the text the same background color as the background of the window ? Can you help me ? (NEW: now, it works. Thank you Hutch)

hutch--

Rui,

If you want to draw the text on the child window yourself you must do it from the WM_PAINT message for the child window so that it will remain visible when other windows have overlapped it. In most instances it would be easier for you to use a control like a text edit control or a static control as either will handle large amounts of text without display problems.

The basic code you are using does not appear to have been written by someone who properly understands how a window and its messaging works. I would ensure that all messages processed are done according to the documentation in either the old winhelp file win32.hlp or the later MSDN/SDK style help.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

RuiLoureiro

Quote from: hutch-- on November 20, 2007, 09:16:15 PM
... you must do it from the WM_PAINT message for the child window so that it will remain visible when other windows have overlapped it. In most instances it would be easier for you to use a control like a text edit control or a static control as either will handle large amounts of text without display problems.
Hutch,
Thanks for the reply.
I have not problems with documentation. I corrected the last version. As you know, it is my first window program. And, many times (!) I forget some details (like many people). And there are details i dont know and i ask for help. Isnt it correct ?
In this case (printing a msg), i am seeing that it is easier to use a text edit control.
Thank you, Hutch (and all that want to help me )
Rui Loureiro

Mark Jones

Hi Rui, consider going through the Iczelion tutorials at:

http://win32assembly.online.fr/tutorials.html

This should give you many ideas for your program. :U
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

MichaelW

#23
Rui,

This example is an attempt to answer your recent questions.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    .data

        hInst     dd          0
        hWnd      dd          0

        fTextOut  dd          not 0
        fWhite    dd          not 0

        wcx       WNDCLASSEX  <>
        msg       MSG         <>

        className db "test_window_class", 0

        txt       db 13,10
                  db "Press F1 to toggle this text between "
                  db "on and off.",13,10,13,10
                  db "Press F2 to toggle the window background "
                  db "color between white and light gray.", 13,10,13,10
                  db "Press Escape to close this window.", 0

    .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

WndProc proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

    LOCAL ps:PAINTSTRUCT
    LOCAL rc:RECT
    LOCAL hdc:HDC

    SWITCH uMsg

      CASE WM_CREATE

      CASE WM_KEYDOWN

        SWITCH wParam

          CASE VK_ESCAPE

            invoke PostQuitMessage, NULL

          CASE VK_F1

            ; --------------------------------------------------------
            ; Invalidating the client area causes it to be repainted.
            ; --------------------------------------------------------

            not fTextOut
            invoke GetClientRect, hwnd, ADDR rc
            invoke InvalidateRect, hwnd, ADDR rc, TRUE

          CASE VK_F2

            .IF fWhite
              invoke GetStockObject, LTGRAY_BRUSH
            .ELSE
              invoke GetStockObject, WHITE_BRUSH
            .ENDIF
            not fWhite
            invoke SetClassLong, hwnd, GCL_HBRBACKGROUND, eax
            invoke GetClientRect, hwnd, ADDR rc
            invoke InvalidateRect, hwnd, ADDR rc, TRUE

       ENDSW

      CASE WM_PAINT

        ; --------------------------------------------------
        ; For the text to persist it must be redrawn each
        ; time the client area of the window is repainted.
        ; --------------------------------------------------

        invoke BeginPaint,hwnd,ADDR ps

        .IF fTextOut

          ; ------------------------------------------------------
          ; Setting the background mix mode to TRANSPARENT causes
          ; DrawText to write the foreground pixels and leave the
          ; background pixels untouched.
          ; ------------------------------------------------------

          invoke SetBkMode, ps.hdc, TRANSPARENT

          invoke GetClientRect, hwnd, ADDR rc
          invoke szLen, ADDR txt
          mov ecx, eax
          invoke DrawText, ps.hdc, ADDR txt, ecx, ADDR rc,
                           DT_WORDBREAK

        .ENDIF

        invoke EndPaint,hwnd,ADDR ps

      CASE WM_CLOSE

        ;invoke PostQuitMessage,NULL    ; ERROR IN ORIGINAL POSTING

        invoke DestroyWindow, hwnd

      CASE WM_DESTROY

        invoke PostQuitMessage,NULL

      DEFAULT

        invoke DefWindowProc, hwnd, uMsg, wParam, lParam

        ret

    ENDSW

    return 0

    ret

WndProc endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    invoke GetModuleHandle, NULL
    mov hInst, eax

    mov wcx.cbSize,        sizeof WNDCLASSEX
    mov wcx.style,         CS_HREDRAW or CS_VREDRAW \
                            or CS_BYTEALIGNWINDOW
    mov wcx.lpfnWndProc,   OFFSET WndProc
    mov wcx.cbClsExtra,    NULL
    mov wcx.cbWndExtra,    NULL
    m2m wcx.hInstance,     hInst
    invoke GetStockObject, WHITE_BRUSH
    mov wcx.hbrBackground, eax
    mov wcx.lpszMenuName,  NULL
    mov wcx.lpszClassName, OFFSET className
    invoke LoadIcon, NULL, IDI_APPLICATION
    mov wcx.hIcon,         eax
    invoke LoadCursor, NULL, IDC_ARROW
    mov wcx.hCursor,       eax
    mov wcx.hIconSm,       0

    invoke RegisterClassEx,ADDR wcx

    ; -------------------------------------------------------------
    ; The WS_POPUP style will produce a fixed-size window with no
    ; title bar. The WS_BORDER style can be combined with WS_POPUP
    ; to create a wider border. The WS_CAPTION style will add a
    ; title bar with no buttons, and increase the width of the
    ; border. Using the WS_OVERLAPPEDWINDOW style instead will
    ; produce a normal application window.
    ; -------------------------------------------------------------

    invoke CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,
                          ADDR className,
                          chr$("Test"),
                          WS_POPUP or WS_CAPTION,
                          0,0,400,300,
                          NULL,NULL,
                          hInst,NULL
    mov hWnd, eax

    invoke ShowWindow, hWnd, SW_SHOWNORMAL
    invoke UpdateWindow, hWnd

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

  msgLoop:

    invoke GetMessage, ADDR msg, NULL, 0, 0
    .IF (eax != 0)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
        jmp msgLoop
    .ENDIF
    exit msg.wParam

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start


If you were doing this as an exercise almost anything would be reasonable. But if your goal is to create a window that can display debug messages, then displaying the messages directly on the client area of the window is doing it the hard way. Using an appropriate control to display the messages would be much easier. In my previous example I used a list box because I felt it was the best choice for displaying short messages. Another possibility for displaying longer messages would be an edit control. And another possibility would be a static text control, but for displaying multiple messages it has the drawback of not being user scrollable.
eschew obfuscation

RuiLoureiro

Hi MichaelW,
Isnt there another direct method to clear the screen ? InvalidateRect doesnt send WM_PAINT immediatly.
Thank you
Rui

Tedd

InvalidateRect.. then UpdateWindow..

But do you really need to update immediately?
No snowflake in an avalanche feels responsible.

RuiLoureiro

Tedd,
I think i need, but i need to see how it works in my program.

RuiLoureiro

Quote from: Tedd on November 27, 2007, 01:23:20 PM
But do you really need to update immediately?

Hi
           At some point of my prog i have one screen drawn. And then i press a key and i want to draw another screen before openning a commom control dialog box to get some data.
           To draw the new screen i need to clear the screen (client area).

           It is something like this:

1º  - i have screen drawn
2ª  - press a key
3ª  - clear the screen and draw another ( this proc is under WM_PAINT too )
4ª  - open a commom control dialog box and wait for data
5ª  - Return to DefWindowProc

         How to clean the screen ?

Rui

Tedd

InvalidateRect will cause the contents of your window to be repainted - that means you will get a WM_PAINT message, with the whole client area to be redrawn. Just redraw the contents of your window according to the state changed by the keypresses. The dialog can be created on the keypress (after invalidate) - it's a separate window, so it shouldn't stop the main window from being redrawn.
No snowflake in an avalanche feels responsible.

RuiLoureiro

Quote from: Tedd on December 10, 2007, 01:00:53 PM
The dialog can be created on the keypress (after invalidate) - it's a separate window, so it shouldn't stop the main window from being redrawn.

Hi Tedd,
              I am learning this little questions of windows. Thank you so much

Rui