News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Just stuck on coloring hyperlink

Started by Don57, December 07, 2012, 02:55:45 AM

Previous topic - Next topic

Don57

I was getting a failure on all call in WM_CTLCOLORSTATIC so i added a call to get the DC for the window, now the calls succeed but no color on the text. I am having trouble understanding the paradigm.

   WndProc PROC hWnd:HWND, uMsg:UINT, wParam, lParam

      LOCAL hdc:HDC                                                           ; handle to hyperlink dc
      LOCAL hdcStatic:HDC                                                     ; handle to device context
      LOCAL ps:PAINTSTRUCT                                                    ; pointer to paint structure

      .IF uMsg==WM_CREATE

          CALL Check_Admin                                                      ; check if program is being run as administrator
          invoke CreateWindowEx,NULL, ADDR sz_Button,ADDR sz_ButtonText,\       ; create window for button
                                WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
                                130,110,140,25,hWnd,BUTTON_ID,hInstance,NULL
       mov  hwndButton,eax                                                   ; save handle to button window

          invoke SendMessage, hWnd, WM_SETTEXT,0, ADDR sz_AppName               ; send event to event handler

          invoke CreateWindowEx, NULL, addr sz_AppLink, 0, WS_CHILD or WS_VISIBLE or SS_NOTIFY,\
                               10, 147, 110, 20, hWnd,0, hInstance, NULL                             ; create child window for hyperlink

          mov hStatic, eax                                                      ; handle to window

          invoke CreateFont, -12, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0         ; 12 high 1 = underlined
          invoke SendMessage, hStatic, WM_SETFONT, eax, 1                       ; send message to window to use font
          invoke LoadCursor, 0, IDC_HAND                                        ; cursor to be displayed over hyperlink
          invoke SetClassLong, hStatic, GCL_HCURSOR,eax
          invoke SetWindowText,hStatic,addr sz_Url                              ; display text for hyperlink
   
      .ELSEIF uMsg==WM_CTLCOLORSTATIC

         invoke BeginPaint,hStatic, ADDR ps
          mov    hdcStatic,eax

          invoke SetBkMode,hdcStatic,TRANSPARENT                                      ; transparent background
          invoke SetTextColor,hdcStatic,00FF901Eh                                     ; dodgerblue from css sheet on site 0x00bbggrr
          mov hBrush1,eax                                                       ; save brush

          invoke SelectObject, hdc, hBrush1
         
      .ELSEIF uMsg==WM_PAINT

          invoke BeginPaint,hWnd, ADDR ps
          mov    hdc,eax

          .IF dw_Text_Flag ==0

             invoke TextOut, hdc, TEXT_LEFT, TEXT_TOP, ADDR sz_WarningText, SIZEOF sz_WarningText-1 
             mov dw_Text_Flag, 1

          .ELSE

             invoke TextOut, hdc, TEXT2_LEFT, TEXT_TOP, ADDR sz_ProgressText, SIZEOF sz_ProgressText-1

          .ENDIF
         
          invoke EndPaint,hWnd, ADDR ps

      .ELSEIF uMsg==WM_COMMAND

          mov eax, lParam

          .IF eax==hStatic                                                                         ; if from hypertext window

             invoke ShellExecute, 0, 0, chr$("http://www.shasti.ca"), 0, 0, SW_SHOWDEFAULT    ; goto web site

          .ENDIF

          movzx edx, word ptr wParam+2

          .IF edx==BN_CLICKED

             movzx eax, word ptr wParam

             .IF eax==BUTTON_ID                                               ; was the button pressed     

                 .IF AdminFlaq==1       

                     CALL Get_ELog_List                                       ; creates Event Log text file and dumps to buffer
                     CALL Count_ELogs                                         ; count the number of log files and calcs progress increment
                     CALL Create_Progress_Bar
                 
                     mov  eax,OFFSET Clear_ELogs
                 
                     invoke CreateThread,NULL,NULL,eax,\
                            NULL,NORMAL_PRIORITY_CLASS,\
                            ADDR dw_Clear_ELogs_ID
                               
                     invoke CloseHandle,eax

                     xor eax,eax                                              ; return 0

                 .ELSE

                     invoke MessageBox, NULL,addr sz_MsgBoxAdminText, addr sz_MsgErrorCaption, MB_OK
               
                     invoke PostMessage,hWnd,WM_SYSCOMMAND,SC_CLOSE,NULL                               

                     xor eax,eax                                                               

                 .ENDIF
           
             .ENDIF

          .ENDIF



;==================== need to close brush handle before exit ====================




      .ELSEIF uMsg==WM_FINISH
           
          invoke MessageBox, NULL,addr sz_MsgBoxDoneText, addr sz_MsgDoneCaption, MB_OK

          invoke PostMessage,hWnd,WM_SYSCOMMAND,SC_CLOSE,NULL                         

          xor eax,eax                                                                   

      .ELSEIF uMsg==WM_DESTROY

          invoke PostQuitMessage,NULL

   .ELSE

          invoke DefWindowProc,hWnd,uMsg,wParam,lParam      
          ret

      .ENDIF

      xor eax,eax                                                             ; clear message

      ret

   WndProc ENDP



jj2007

You are using the LOCAL hdc for different messages. That won't work. Use
.data?
hdc   dd ?

dedndave

i don't think you really need to use BeginPaint in WM_CTLCOLORSTATIC, either

you can use SetTextColor, SetBkColor
but - you must also return the background brush handle in EAX at the end of WM_CTLCOLORSTATIC

if you want underlines, that is a font issue
create a font with underline attribute set, then...
        INVOKE  SendMessage,hStatic,WM_SETFONT,hFont,TRUE

CommonTater

Probably the easiest way around this is to create a brush at global scope and store it's handle.

Then for any of the WM_CTLCOLOR????? messages, you only need to return the brush handle to change the background color.

Also note that brushes are handles, which are actually pointers to structs... if you create a new handle each time, it's going to leak bits of memory when the handle is forgotten.

Don57

Needed the DC for the child window with the hyperlink. As soon as I add SendMessage the link appears to change color, hard to tell though because it is flashing very rapidly.


      .ELSEIF uMsg==WM_CTLCOLORSTATIC

          invoke GetDC, hStatic
          mov hdcStatic, eax

          invoke SetBkMode,hdcStatic,TRANSPARENT                                 ; transparent background
          invoke SetTextColor,hdcStatic,00FF901Eh                                ; dodgerblue from css sheet on site 0x00bbggrr
          mov hBrush1,eax                                                        ; save brush

          ; invoke SelectObject, hdcStatic, hBrush1

          invoke SendMessage, hStatic,WM_SETFONT,hLinkFont,TRUE

          mov eax, hBrush1

dedndave

ok - that's not good, Don   :P

          invoke SetTextColor,hdcStatic,00FF901Eh                                ; dodgerblue from css sheet on site 0x00bbggrr
          mov hBrush1,eax                                                        ; save brush


SetTextColor does not return a brush handle !

CREF_BACKGROUND  EQU 888888h   ;light gray
CREF_FOREGROUND1 EQU 0FF0000h  ;blue
CREF_FOREGROUND2 EQU 0FFh      ;red
;
;
;
        .DATA?

hStatic   HWND   ?
hdcStatic HDC    ?
hBrush1   HBRUSH ?
;
;
        .CODE
;
;
    .if uMsg==WM_CTLCOLORSTATIC
        INVOKE  SetBkColor,hdcStatic,CREF_BACKGROUND
        INVOKE  SetTextColor,hdcStatic,CREF_FOREGROUND1
        mov     eax,hBrush1                                 ;return the background brush handle

    .elseif uMsg==WM_CREATE

;create static control here and store handle as hStatic

        INVOKE  GetDC,hStatic
        mov     hdcStatic,eax
        INVOKE  CreateSolidBrush,CREF_BACKGROUND
        mov     hBrush1,eax
        xor     eax,eax                                     ;return 0

    .elseif uMsg==WM_CLOSE
        INVOKE  ReleaseDC,hStatic,hdcStatic
        INVOKE  DestroyWindow,hWnd
        INVOKE  DeleteObject,hBrush1
        xor     eax,eax                                     ;return 0

    .else
        INVOKE  DefWindowProc,hWnd,uMsg,wParam,lParam       ;return DefWindowProc value

    .endif
    ret

dedndave

oops - i edited the above to release the static DC before destoying the window   :(

normally, i would name the brush handle variable something like "hbrStatic"
but - hBrush1 will work, of course

dedndave

ok
i played with it a little bit
i was making a mistake by creating and releasing a DC for the static control

for WM_CTLCOLORxxx messages, you should use the HDC specified in wParam

well - that simplifies our code a little
because we do not have to get/store/release the DC
we just grab wParam   :biggrin:

now - be warned - lol
changing the color of text on a button is a whole different ball of wax
it used to be very similar, before the newer versions of common controls

but, a static control is relatively easy...

Don57

The wParam got it. The color is stored as 0x00bbggrr.

Thank You. Do I ever miss the old days of writting right to the device.

dedndave

in this example, i also created an underline font....

first, i used SystemParametersInfo to fill a NONCLIENTMETRICS structure
this tells us many of the user-selectable settings, including the fonts he has selected for a few things

i grab the user-selected "message" font and modify it to be underlined (simple)
then, i use CreateFontIndirect to create a font for use in the static control
when done, i use DeleteObject to release the font handle

as for the color, you can use a global variable for the foreground color
initialize it to one CREF value
once the user has clicked on the link, set that var to a second color value


EDITED:
i put the underlined font creation in a little PROC so that NONCLIENTMETRICS could be LOCAL   :P
.... without putting the LOCAL in the WndProc

jj2007


dedndave

well - i was in a hurry - lol
i just grabbed my little MDI window, because the code is "clean"
overkill, though

and - i didn't size the static when the MDI child is sized, etc
it could use some work - i just wanted to get Don up and running   :P

hfheatherfox07

Quote from: dedndave on December 07, 2012, 07:18:42 AM
in this example, i also created an underline font....

first, i used SystemParametersInfo to fill a NONCLIENTMETRICS structure
this tells us many of the user-selectable settings, including the fonts he has selected for a few things

i grab the user-selected "message" font and modify it to be underlined (simple)
then, i use CreateFontIndirect to create a font for use in the static control
when done, i use DeleteObject to release the font handle

as for the color, you can use a global variable for the foreground color
initialize it to one CREF value
once the user has clicked on the link, set that var to a second color value


EDITED:
i put the underlined font creation in a little PROC so that NONCLIENTMETRICS could be LOCAL   :P
.... without putting the LOCAL in the WndProc

EDIT :
I can not seem to download any attachments here .....




@dedndave
I can not seem to download your examples ...it says they are 0bytes ???
Why ?
I tried from different computers and different ways to open them
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

dedndave

i had no trouble
perhaps you are bad mojo   :biggrin:

at any rate, you aren't missing much - lol

hfheatherfox07

#14
Looks Like An Issue....
the other Day my Avatar disappeared ?
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.