Announcement

Collapse
No announcement yet.

Problems with WM_CTLCOLORSTATIC

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problems with WM_CTLCOLORSTATIC

    Hello folks,

    What is wrong with this code? I guess something's going wrong while processing the %WM_CTLCOLORSTATIC message.
    This is what happens: when clicking the OK-button, the new text is mixed up with the original line (etc.).
    Instead of an hollow brush, I've tried to use a solid brush, but then the label's background is black. And yes,
    I know how to give the brush a different color, but which one? %LTGRAY is not the default dialog background on all
    platforms (for instance: on NT4 it appears to be lighter). And finally: GetBkColor hLbl returns white; why not the
    proper gray variant?

    Code:
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    
    CALLBACK FUNCTION DlgCallBck()
      STATIC hLbl AS LONG
      LOCAL  hFnt AS LONG, lf AS LOGFONT, hBrsh AS LONG, lb AS LOGBRUSH
      
      SELECT CASE CBMSG
        CASE %WM_INITDIALOG
          CONTROL HANDLE CBHNDL, 101 TO hLbl
          CONTROL SEND CBHNDL, 101, %WM_GETFONT, 0, 0 TO hFnt
          GetObject hFnt, SIZEOF(lf), BYVAL VARPTR(lf)
          lf.lfWeight = %FW_BOLD
          hFnt = CreateFontIndirect(lf)
          CONTROL SEND CBHNDL, 101, %WM_SETFONT, hFnt, 1
          CONTROL SEND CBHNDL, %IDOK, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE
          CONTROL SET FOCUS CBHNDL, %IDOK
          FUNCTION = 1
    
        CASE %WM_CTLCOLORSTATIC
          SetBkMode CBWPARAM, %TRANSPARENT
          SELECT CASE CBLPARAM
            CASE hLbl
              SetTextColor CBWPARAM, %RED
              
              ' ALTERNATIVE WAY:
              ' lb.lbStyle = %BS_SOLID
              ' lb.lbColor = %LTGRAY ' this does not work for NT4
              ' hBrsh = CreateBrushIndirect(lb)
              ' END ALTERNATIVE WAY
              hBrsh = GetStockObject(%NULL_BRUSH)
              FUNCTION = hBrsh
          END SELECT
          
        CASE %WM_COMMAND
          IF CBCTL = %IDOK THEN
            CONTROL GET TEXT CBHNDL, 101 TO content$
            IF INSTR(content$, "initial") THEN
              CONTROL SET TEXT CBHNDL, 101, "Modified"
            ELSE
              CONTROL SET TEXT CBHNDL, 101, "This is the initial line"
            END IF
          END IF
    
        CASE %WM_DESTROY
          DeleteObject hFnt
          DeleteObject hBrsh
      END SELECT
    END FUNCTION
            
    FUNCTION PBMain() AS LONG
      LOCAL hDlg AS LONG
      
      DIALOG NEW 0, " Test label colors", , , 200, 100, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
      CONTROL ADD LABEL, hDlg, 101, " This is the initial line", 10, 10, 180, 10
      CONTROL ADD BUTTON, hDlg, %IDOK, "OK", 140, 76, 50, 14
      DIALOG SHOW MODAL hDlg CALL DlgCallBck
    END FUNCTION
    ------------------
    mailto:[email protected][email protected]</A>
    www.basicguru.com/zijlema/

    Egbert Zijlema, journalist and programmer (zijlema at basicguru dot eu)
    http://zijlema.basicguru.eu
    *** Opinions expressed here are not necessarily untrue ***

  • #2
    If you use transparent mode AND you wish to change the text in the label, you'll either need to destroy and recreate the control (use PostMessage with a custom message number to trigger this action), or emulate a owner-draw by using the %SS_GRAYFRAME style and handling %WM_PAINT and drawing the control 'image' yourself. In the latter case, when yo need to change the text, just Invalidate the control with InvalidateRect() and then immediately call UpdateWindow().

    Personally, I prefer to use the latter technique, but I like doing things the hard way sometimes.



    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      Egbert:
      Code:
      #COMPILE EXE
      #INCLUDE "WIN32API.INC"
      
      
      CALLBACK FUNCTION DlgCallBck()
        STATIC hLbl AS LONG
        LOCAL  hFnt AS LONG, lf AS LOGFONT, hBrsh AS LONG, lb AS LOGBRUSH
      
      
        SELECT CASE CBMSG
          CASE %WM_INITDIALOG
            CONTROL HANDLE CBHNDL, 101 TO hLbl
            CONTROL SEND CBHNDL, 101, %WM_GETFONT, 0, 0 TO hFnt
            GetObject hFnt, SIZEOF(lf), BYVAL VARPTR(lf)
            lf.lfWeight = %FW_BOLD
            hFnt = CreateFontIndirect(lf)
            CONTROL SEND CBHNDL, 101, %WM_SETFONT, hFnt, 1
            CONTROL SEND CBHNDL, %IDOK, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE
            CONTROL SET FOCUS CBHNDL, %IDOK
            FUNCTION = 1
          CASE %WM_CTLCOLORSTATIC
            SetBkMode CBWPARAM, %TRANSPARENT
            SELECT CASE CBLPARAM
              CASE hLbl
                SetTextColor CBWPARAM, %RED
      
                ' ALTERNATIVE WAY:
                ' lb.lbStyle = %BS_SOLID
                ' lb.lbColor = %LTGRAY ' this does not work for NT4
                ' hBrsh = CreateBrushIndirect(lb)
                ' END ALTERNATIVE WAY
                hBrsh = GetStockObject(%NULL_BRUSH)
                FUNCTION = hBrsh
            END SELECT
      
          CASE %WM_COMMAND
            LOCAL RC AS RECT ' <---- Add
      
      
            IF CBCTL = %IDOK THEN
              CONTROL GET TEXT CBHNDL, 101 TO content$
      
      
              ' Clear label content
              CONTROL SET TEXT CBHNDL, 101, ""
              ' Invalidate just the label's region of the dialog (no flicker)
              CONTROL GET LOC CBHNDL, 101 TO X&, Y&
              DIALOG UNITS CBHNDL, X&, Y& TO PIXELS X&, Y&
              CONTROL GET SIZE CBHNDL, 101 TO XX&, YY&
              DIALOG UNITS CBHNDL, XX&, YY& TO PIXELS XX&, YY&
              SetRect RC, X&, Y&, X& + XX&, Y& + YY&
              InvalidateRect CBHNDL, RC, %TRUE
      
      
              IF INSTR(content$, "initial") THEN
                CONTROL SET TEXT CBHNDL, 101, "Modified"
              ELSE
                CONTROL SET TEXT CBHNDL, 101, "This is the initial line"
              END IF
            END IF
          CASE %WM_DESTROY
            DeleteObject hFnt
            DeleteObject hBrsh
        END SELECT
      END FUNCTION
      
      
      FUNCTION PBMAIN() AS LONG
        LOCAL hDlg AS LONG
      
      
        DIALOG NEW 0, " Test label colors", , , 200, 100, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
        CONTROL ADD LABEL, hDlg, 101, "This is the initial line", 10, 10, 180, 10
        CONTROL ADD BUTTON, hDlg, %IDOK, "OK", 140, 76, 50, 14
        DIALOG SHOW MODAL hDlg CALL DlgCallBck
      END FUNCTION
      Timm

      [This message has been edited by Timm Motl (edited July 31, 2001).]
      mailto:[email protected]
      Tsunami Record Manager

      Comment


      • #4
        Timm,
        Thanks for the fast response. It works great!

        Lance,
        Is Timm's solution approx. the same you had in mind?
        To be honest, I did'nt understand your explanation.

        ------------------
        mailto:[email protected][email protected]</A>
        www.basicguru.com/zijlema/

        [This message has been edited by Egbert Zijlema (edited August 01, 2001).]

        Egbert Zijlema, journalist and programmer (zijlema at basicguru dot eu)
        http://zijlema.basicguru.eu
        *** Opinions expressed here are not necessarily untrue ***

        Comment


        • #5
          Lance --
          If background of dialog is bitmap (with palette) and it's necessary to change a label very often (a counter), how do you redraw ?



          ------------------
          E-MAIL: [email protected]

          Comment


          • #6
            Ahha! In pursuit of "visual candy", Semen!?

            The solution is not really much different to an owner-draw control or a WM_PAINT handler - draw the whole content of the label on demand (or just the clipping region): Initially create a memory DC, BitBlt() just the portion of the bitmap that forms the background of the label (and hold onto this as a memory bitmap). Then during %WM_PAINT, select the memory BMP into a memory DC; draw the text; and finally BitBlt() onto the dialog DC.

            Not simple (since the circumstances are extreme), but it works... (I prefer to use %SS_GRAYFRAME so that I can handle the drawing myself).

            Under NT/2000, it may be possible to use a brush that includes the whole label background, then handle %WM_CTLCOLORSTATIC normally. However, I've never tried this personally... off hand, I'm not sure how large a brush can be under NT/2000 - but I seem to recall that 8x8 is the limit for Win9x.

            ------------------
            Lance
            PowerBASIC Support
            mailto:[email protected][email protected]</A>
            Lance
            mailto:[email protected]

            Comment


            • #7
              Originally posted by Lance Edmonds:
              If you use transparent mode AND you wish to change the text in the label, you'll either need to destroy and recreate the control (use PostMessage with a custom message number to trigger this action)(......)
              Lance,
              What should the custom message number be in this case? I've looked at all the %WM_xxxxx messages in Win32API.inc, but I don't un derstand the meaning of every equate.
              BTW: I'm asking this because it is my feeling that this way is more to the point than Timm's solution (it works perfectly, though).


              ------------------
              mailto:[email protected][email protected]</A>
              www.basicguru.com/zijlema/



              [This message has been edited by Egbert Zijlema (edited August 01, 2001).]

              Egbert Zijlema, journalist and programmer (zijlema at basicguru dot eu)
              http://zijlema.basicguru.eu
              *** Opinions expressed here are not necessarily untrue ***

              Comment

              Working...
              X