News:

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

How to maintain color

Started by hotrod, January 03, 2010, 06:58:59 PM

Previous topic - Next topic

hotrod

This is a follow up to my previous post. I have 3 statics which I want to change the color on when clicked and maintain it until clicked a second time. The following code will change the color when clicked for each static and all 3 will have the same color until the window loses focus. When the window is restored, only the last clicked window will have the changed color while the others return to their original. Thanks...
.if uMsg==WM_INITDIALOG
invoke Create, hWin ; Creates 3 statics.

    invoke CreateSolidBrush, 000FFFFH ; Yellow
mov hBrNorm, eax
    invoke CreateSolidBrush, 000FF00h ; Green
    mov hBrClk, eax
ret
.elseif uMsg==WM_CTLCOLORSTATIC ; Set backcolor of all statics on load.
mov eax, lParam
.if eax==handle
mov pixel, 000FF00h
mov eax, hBrClk
    mov hBrush, eax
.else
invoke GetDC, lParam
invoke GetPixel, eax, 0, 0
cmp eax, pixel
je _bypass
mov eax, hBrNorm
mov hBrush, eax
.endif
invoke SetTextColor,wParam,0
    invoke SetBkMode,wParam,TRANSPARENT
mov eax, hBrush
ret
; This point is NEVER reached.
_bypass:
PrintText "Bypassed"
.elseif uMsg==WM_COMMAND
mov ebx, wParam
shr ebx, 16
.if bx==STN_CLICKED
mov eax, lParam
mov handle, eax
invoke InvalidateRect, lParam, NULL, TRUE
.endif


I removed the [SOLVED] from the title, this forum is not a help desk.

hotrod

I believe that the answer to my own question is that it cannot be done because WM_PAINT is calling WM_ERASEBKGND thereby clearing all but the most recent change. So, what has to happen is that the static has to be saved with its' color. In other words, if I want to maintain the color of more than 1 static, the second static's handle and color must be collected into an arrary (or something) and returned to WM_PAINT via InvalidateRect.

If any pros have a better answer, I would really be interested because this same issue seems to be true for FillRect also. Once the initial messaging is complete, everthing is basically temporary from that point forward. I have not read any documentation to confirm this, but I have made some practical attempts.

A work in progress...

MichaelW

"A static control sends the WM_CTLCOLORSTATIC message to its parent window when the control is about to be drawn". So whatever color your handler is setting should persist.

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================

IDC_ST1 equ 1001
IDC_ST2 equ 1002
IDC_ST3 equ 1003

;==============================================================================

    null EQU NULL

;==============================================================================
    .data

      hInst       dd          0
      hWnd        dd          0

      posx        dd          0
      posy        dd          0

      hwndStatic1 dd          0
      hwndStatic2 dd          0
      hwndStatic3 dd          0

      brush1      dd          WHITE_BRUSH
      brush2      dd          LTGRAY_BRUSH
      brush3      dd          GRAY_BRUSH

      wcx         WNDCLASSEX  <>
      msg         MSG         <>
      className   db          "test_class",0

    .code
;==============================================================================

;==============================================================================

WindowProc proc hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    SWITCH uMsg

        CASE WM_CREATE

            STYLE = WS_CHILD or WS_VISIBLE or SS_CENTER or SS_NOTIFY

            invoke CreateWindowEx, WS_EX_CLIENTEDGE,
                                   chr$("STATIC"),
                                   chr$("XXXXX"),
                                   STYLE,
                                   20,
                                   20,
                                   150,
                                   30,
                                   hWin,
                                   IDC_ST1,
                                   hInst,
                                   null

            mov hwndStatic1, eax

            invoke CreateWindowEx, WS_EX_CLIENTEDGE,
                                   chr$("STATIC"),
                                   chr$("XXXXX"),
                                   STYLE,
                                   20,
                                   70,
                                   150,
                                   30,
                                   hWin,
                                   IDC_ST2,
                                   hInst,
                                   null
            mov hwndStatic2, eax

            invoke CreateWindowEx, WS_EX_CLIENTEDGE,
                                   chr$("STATIC"),
                                   chr$("XXXXX"),
                                   STYLE,
                                   20,
                                   120,
                                   150,
                                   30,
                                   hWin,
                                   IDC_ST3,
                                   hInst,
                                   null
            mov hwndStatic3, eax

        CASE WM_CTLCOLORSTATIC

            SWITCH lParam

                CASE hwndStatic1

                    invoke SetTextColor, wParam, 0ff0000h
                    invoke SetBkMode, wParam, TRANSPARENT
                    invoke GetStockObject, brush1
                    ret

                CASE hwndStatic2

                    invoke SetTextColor, wParam, 0ff0000h
                    invoke SetBkMode, wParam, TRANSPARENT
                    invoke GetStockObject, brush2
                    ret


                CASE hwndStatic3

                    invoke SetTextColor, wParam, 0ff0000h
                    invoke SetBkMode, wParam, TRANSPARENT
                    invoke GetStockObject, brush3
                    ret

            ENDSW

        CASE WM_COMMAND

            mov eax, wParam
            movzx eax, ax
            SWITCH eax

                CASE IDCANCEL

                    invoke DestroyWindow, hWin

                CASE IDC_ST1

                    SWITCH brush1
                        CASE WHITE_BRUSH
                            mov brush1, LTGRAY_BRUSH
                        CASE LTGRAY_BRUSH
                            mov brush1, GRAY_BRUSH
                        CASE GRAY_BRUSH
                            mov brush1, WHITE_BRUSH
                    ENDSW
                    invoke InvalidateRect, hwndStatic1, null, TRUE

                CASE IDC_ST2

                    SWITCH brush2
                        CASE WHITE_BRUSH
                            mov brush2, LTGRAY_BRUSH
                        CASE LTGRAY_BRUSH
                            mov brush2, GRAY_BRUSH
                        CASE GRAY_BRUSH
                            mov brush2, WHITE_BRUSH
                    ENDSW
                    invoke InvalidateRect, hwndStatic2, null, TRUE

                CASE IDC_ST3

                    SWITCH brush3
                        CASE WHITE_BRUSH
                            mov brush3, LTGRAY_BRUSH
                        CASE LTGRAY_BRUSH
                            mov brush3, GRAY_BRUSH
                        CASE GRAY_BRUSH
                            mov brush3, WHITE_BRUSH
                    ENDSW
                    invoke InvalidateRect, hwndStatic3, null, TRUE

            ENDSW

        CASE WM_CLOSE

            invoke DestroyWindow, hWin

        CASE WM_DESTROY

            invoke PostQuitMessage, NULL
            return 0

        DEFAULT

            invoke DefWindowProc, hWin, uMsg, wParam, lParam
            ret

    ENDSW

    return 0

WindowProc endp

;==============================================================================
start:
;==============================================================================

    mov   hInst, rv(GetModuleHandle, NULL)
    mov   wcx.cbSize,        sizeof WNDCLASSEX
    mov   wcx.style,         CS_HREDRAW or CS_VREDRAW \
                              or CS_BYTEALIGNWINDOW
    mov   wcx.lpfnWndProc,   offset WindowProc
    mov   wcx.cbClsExtra,    NULL
    mov   wcx.cbWndExtra,    NULL
    m2m   wcx.hInstance,     hInst
    mov   wcx.hbrBackground, COLOR_BTNFACE + 1
    mov   wcx.lpszMenuName,  NULL
    mov   wcx.lpszClassName, offset className
    mov   wcx.hIcon,         rv(LoadIcon, NULL, IDI_APPLICATION)
    mov   wcx.hCursor,       rv(LoadCursor, NULL, IDC_ARROW)
    mov   wcx.hIconSm,       0

    invoke RegisterClassEx, addr wcx

    ;--------------------------------------------------------------
    ; Specify the window width and height and calc the coordinates
    ; necessary to center the window on the screen.
    ;--------------------------------------------------------------

    WW = 200
    WH = 200
    invoke GetSystemMetrics, SM_CXSCREEN
    shr eax, 1
    sub eax, WW / 2
    mov posx, eax
    invoke GetSystemMetrics, SM_CYSCREEN
    shr eax, 1
    sub eax, WH / 2
    mov posy, eax

    invoke CreateWindowEx,  WS_EX_OVERLAPPEDWINDOW,
                            addr className,
                            chr$("Test"),
                            WS_OVERLAPPED or WS_SYSMENU,
                            posx, posy, WW, WH,
                            null, null,
                            null, null
    mov   hWnd, eax

    invoke ShowWindow, hWnd, SW_SHOWDEFAULT
    invoke UpdateWindow, hWnd

  msgLoop:

    invoke GetMessage, addr msg, NULL, 0, 0
    .if eax != 0
        invoke IsDialogMessage, hWnd, addr msg
        .if eax == 0
            invoke TranslateMessage, addr msg
            invoke DispatchMessage, addr msg
        .endif
        jmp   msgLoop
    .ENDIF

    exit msg.wParam

;==============================================================================
end start

eschew obfuscation

hotrod

Thanks again MichaelW. Apparently I keep getting my ducks out of line. Looks like I was trying to make things happen to quickly and failed to notice that I had to be working with single objects instead of a group. MASM is not VB and I have to remember that. Don't go anywhere, I will be back in the ditch again.

hotrod

Thanks to MichaelW, this is the final code I came up with. The controls are not spelled out in the code thereby making it possible to add more without modification. This code can be condensed more if desired by making a loop to create the statics and puting the handles and IDs into arrays. Any and all comments welcome.
.386
;.model flat,stdcall
option casemap:none

include \masm32\include\masm32rt.inc

WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD

.const
styleex dd WS_EX_CLIENTEDGE or WS_EX_DLGMODALFRAME
style dd WS_OVERLAPPEDWINDOW

IDC_STC1 equ 1 ; Value is used to index aColor array,
IDC_STC2 equ 2 ; just keep adding in succession.
IDC_STC3 equ 3

.data
ClassName db 'DLGCLASS',0
AppName db 'Change color',0
AboutMsg db 'MASM32 RadASM Dialog as main',13,10,'Copyright © MASM32 2001',0

.data?
hInstance dd ?
CommandLine dd ?
posx        dd ?
posy        dd ?

hIDC_STC1 HWND ?
hIDC_STC2 HWND ?
hIDC_STC3 HWND ?

hBrushBlue dd ?
hBrushGreen dd ?
hBrushRed dd ?
hBrushYellow dd ?
hDC dd ?
color dd ?
aColor dd 4 dup (?) ; Increase by 1 for each static.
index dd ? ; Keeps track of esi.

.code

start:
invoke GetModuleHandle,NULL
mov    hInstance,eax
invoke GetCommandLine
invoke InitCommonControls
mov CommandLine,eax
invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
invoke ExitProcess,eax

;=====================================================================================
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov   wc.cbSize,SIZEOF WNDCLASSEX
mov   wc.style, CS_HREDRAW or CS_VREDRAW
mov   wc.lpfnWndProc, OFFSET WndProc
mov   wc.cbClsExtra,NULL
mov   wc.cbWndExtra,NULL
push  hInst
pop   wc.hInstance
mov   wc.hbrBackground,COLOR_WINDOW+1
mov   wc.lpszMenuName,NULL
mov   wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov   wc.hIcon,eax
mov   wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov   wc.hCursor,eax
invoke RegisterClassEx, addr wc

; Code by MichaelW...
    WW = 200
    WH = 200
    invoke GetSystemMetrics, SM_CXSCREEN
    shr eax, 1
    sub eax, WW / 2
    mov posx, eax
    invoke GetSystemMetrics, SM_CYSCREEN
    shr eax, 1
    sub eax, WH / 2
    mov posy, eax

invoke CreateWindowEx,styleex,ADDR ClassName,ADDR AppName,\
           style,posx,\
           posy,WW,WH,NULL,NULL,\
           NULL,NULL
mov   hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.while TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .break .if (!eax)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
.endw
mov eax,msg.wParam
ret
WinMain endp
;=====================================================================================

CreateStatics proc hWin:DWORD
; Code by MichaelW...
; Keep adding statics here:
    STYLE = WS_CHILD or WS_VISIBLE or SS_CENTER or SS_NOTIFY
    invoke CreateWindowEx, WS_EX_CLIENTEDGE, chr$("STATIC"), chr$("XXXXX"), STYLE,\
                           20, 20, 150, 30, hWin,  IDC_STC1, hInstance, NULL
    mov hIDC_STC1, eax
   
    invoke CreateWindowEx, WS_EX_CLIENTEDGE, chr$("STATIC"), chr$("XXXXX"), STYLE,\
                           20, 70, 150, 30, hWin,  IDC_STC2, hInstance, NULL
mov hIDC_STC2, eax

    invoke CreateWindowEx, WS_EX_CLIENTEDGE, chr$("STATIC"), chr$("XXXXX"), STYLE,\
                           20, 120, 150, 30, hWin,  IDC_STC3, hInstance, NULL
    mov hIDC_STC3, eax
ret
CreateStatics endp
;=====================================================================================

WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
SWITCH uMsg
CASE WM_CREATE

invoke CreateStatics, hWin
mov hIDC_STC1, rv(GetDlgItem, hWin, IDC_STC1)
mov hIDC_STC2, rv(GetDlgItem, hWin, IDC_STC2)

mov hBrushBlue, rv(CreateSolidBrush, 0FF0000h)
mov hBrushGreen, rv(CreateSolidBrush, 000FF00h)
mov hBrushRed, rv(CreateSolidBrush, 00000FFh)
mov hBrushYellow, rv(CreateSolidBrush, 000FFFFh)

mov esi, offset aColor ; 1 based array to hold the color.
push esi
pop index ; Index to colors for individual statics.
mov eax, hBrushYellow ; Going to initialize all statics to yellow.

mov ecx, 3 ; Number of statics to initialize.
_addStatic:
add esi, 4 ; Static IDs are 1 based.
mov [esi], eax
loop _addStatic
ret

CASE WM_COMMAND
invoke GetDlgCtrlID, lParam
mov ebx, 4
mul ebx
mov esi, offset aColor
add esi, eax
mov index, esi
sub index, 4

; Required because the statics are not defined in the code.
mov hDC, rv(GetDC, lParam)
invoke GetPixel, hDC, 10, 10

; Rotate the colors.
SWITCH EAX
CASE 0FF0000h
push hBrushGreen
pop color
CASE 000FF00h
push hBrushRed
pop color
CASE 00000FFh
push hBrushYellow
pop color
CASE 000FFFFh
push hBrushBlue
pop color
ENDSW

mov eax, color
mov [esi], eax
invoke InvalidateRect, lParam, NULL, TRUE
ret
CASE WM_SETFOCUS ; Need to point the statics to the user colors;
mov esi, offset aColor ; otherwise they revert to system colors.
mov index, esi
CASE WM_CTLCOLORSTATIC ; Colors all statics on load.
invoke SetBkMode, wParam, TRANSPARENT
add index, 4 ; Set esi for 1 based index.
mov esi, index
mov eax, [esi]
ret

CASE WM_CLOSE
invoke DeleteObject, hBrushBlue
invoke DeleteObject, hBrushGreen
invoke DeleteObject, hBrushRed
invoke DeleteObject, hBrushYellow
invoke DestroyWindow,hWin
CASE WM_DESTROY
invoke PostQuitMessage,NULL
DEFAULT
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
ENDSW
xor eax,eax
ret

WndProc endp
;=====================================================================================
end start