Announcement

Collapse
No announcement yet.

sdk transparent labels on gradient bkgrnd

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

  • BOB MECHLER
    replied
    Back to the gradient tab control questions.
    I just about have everything the way I want it with the help and advice from Chris Boss and Dominic. A colleague pointed out that the tabs themselves don't redraw correctly once selected and I can see the point. They are ownerdrawn style and are painted in WM_DRAWITEM initially.

    Dialog Redraw hdlg will redraw them correctly after a tab click but I really don't want the flicker.

    The dialog background has a gradient, the tabs have a gradient and the tab control background also has a gradient via the subclassing that uses the Chris Boss suggestion of processing the wm_erasebk.. event and paint the tab body background with a gradient.

    After a tab click the clicked tab raises a little bit. The next click doesn't return the first tab to it's original state. My question is, do I trigger a redraw of the dialog background, the tab background or the tab items.

    Bob Mechler

    If that isn't enough info, I'm just about finished with a compilable example. I hope to use this as a general template for future consistency in my look and feel for new programs.

    Leave a comment:


  • BRENT GARDNER
    replied
    Thanks Dominic,

    Your right it is not obvious. If you are going to create code, can the bitmap be bigger than the textbox? My program uses the bitmap as a frame and background for editing text. I used a graphic control with dimensions 53,61,205,229 dialog units, and the textbox is inside: 58,74,270,205. The bitmap is rendered (0,0)-(285,229).

    Leave a comment:


  • Dominic Mitchell
    replied
    I will modify your sample code as soon as I find the time.
    You are already using a bitmap, it is just not obvious.

    Leave a comment:


  • BRENT GARDNER
    replied
    Dominic,

    Your example code seems to work fine, but when I integrated into
    my program, I get windows error: "The procedure entry point
    SymSetSymWithAddr64 could not be located on the dynamic link
    Library DBGHELP.dll"

    Only thing I can see different is that I don't use
    CASE %WM_CTLCOLORDLG or CASE %WM_SIZE

    Later, after double checking, found my error. Left out the code:
    " CALL CreateBg(CBHNDL,0,0,0)"
    in CASE %WM_INITALIZE
    Now works beautifully!!! Flicker Free!!!
    This is a very fine piece of coding.
    One other question. How can I RENDER a bitmap instead of just
    painting a gradient color on bitmap? Your code mentions that it
    is possible, but can't figure out how to load a bitmap from file?
    Do I need a patternbrush?

    Thanks for your taking the time to do such great work.
    Last edited by BRENT GARDNER; 20 Feb 2008, 10:40 AM.

    Leave a comment:


  • Dominic Mitchell
    replied
    The following code modifies your sample to avoid flickering.
    This code renders the background and text of the edit control to a memory device context
    and then BitBlt's the image to the screen.
    See WM_CTLCOLORDLG, WM_CTLCOLOREDIT, WM_SIZE(if dialog and controls are resizeable),
    PaintBg, CreateBg, PaintEdit, and Edit_SubclassProc.

    Note: do not add the WS_EX_TRANSPARENT style to the edit controls.
    If the control is resizeable, the WS_EX_TRANSPARENT style will cause flickering.
    In fact, this style serves no purpose when this technique is used.
    Note: the edit control must be subclassed or superclassed.

    Code:
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    
    TYPE DIALOGBACKGROUND
      hBmpOld   AS DWORD
      hDC       AS DWORD
    END TYPE
    
    %IDT_TEXT       = 1000
    
    GLOBAL hDlg AS DWORD
    GLOBAL ghKbrdHook, KEYP, KEY13 AS LONG
    GLOBAL lpfnKbrdHook AS LONG
    
    '========================KEYBOARDHOOK FUNCTION===================================================
    FUNCTION KeyboardHook(BYVAL iCode AS INTEGER, BYVAL wParam AS LONG, _
             BYVAL lParam AS LONG) AS DWORD
    
      FUNCTION = CallNextHookEx(ghKbrdHook, iCode, wParam, lParam)
    
      IF iCode = %HC_ACTION THEN
        IF ISFALSE(lParam AND &H80000000) THEN ' KeyUp
          STATIC nHook AS LONG
          INCR nHook
          KEYP = wParam
          IF KEY13 = 1 THEN
             KEYP = 32  ' <SPACE BAR>, SUB PRINTRECORD, 7-18-2007, so dialog does not leave shadow
          END IF
        END IF
      END IF
    
    END FUNCTION
    
    FUNCTION MakeFont(BYVAL SYSFont AS STRING, BYVAL PointSize AS LONG) AS LONG
    
      LOCAL hDC      AS LONG
      LOCAL CyPixels AS LONG
      hDC = GetDC(%HWND_DESKTOP)
      CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
      ReleaseDC %HWND_DESKTOP, hDC
      PointSize =-MulDiv(PointSize, CyPixels, 72)
      FUNCTION = CreateFont(PointSize, 0, 0, 0, %FW_NORMAL, 0, 0, 0, _
                %ANSI_CHARSET, %OUT_TT_PRECIS, %CLIP_DEFAULT_PRECIS, _
                  %DEFAULT_QUALITY, %FF_DONTCARE, BYCOPY SYSFont)
    
    END FUNCTION
    
    FUNCTION WINMAIN (BYVAL hCurInstance  AS LONG, _
                      BYVAL hPrevInstance AS LONG, _
                      BYVAL lpszCmdLine   AS ASCIIZ PTR, _
                      BYVAL nCmdShow      AS LONG) EXPORT AS LONG
      ' File to open when program starts up
      CALL MAINDIALOG
    END FUNCTION 'FUNCTION WINMAIN
    
    CALLBACK FUNCTION CancelCallBack
      DIALOG END CBHNDL, 0
    END FUNCTION
    
    SUB MAINDIALOG
      STATIC hBrush50 AS DWORD
      LOCAL    Result AS LONG
      LOCAL    hWndControl AS DWORD
      GLOBAL   x1, y1, x2, y2, hToolTip AS LONG
      x1 = 77: y1 = 22: x2 = 407: y2 = 347 ' = units 407 wide for windows 98, 10-22-2007
      ' Create our top level primary GUI
      DIALOG NEW %HWND_DESKTOP, "", 0, 0, x2, y2, _
       %DS_CENTER OR %DS_SETFONT OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX _
       OR %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN, %WS_EX_CONTROLPARENT, TO hDlg
    
      IF ERR OR hDlg = 0 THEN EXIT SUB  ' Error occurred
    
      CONTROL ADD TEXTBOX,  hDlg, %IDT_TEXT,      "",              58,   74 ,270, 205, _
      %ES_NOHIDESEL OR %ES_AUTOVSCROLL OR %ES_LEFT OR %ES_MULTILINE OR %WS_BORDER _
       OR %WS_TABSTOP 
      ' Subclass text box
      hWndControl = GetDlgItem(hDlg,%IDT_TEXT)
      SetProp hWndControl, "OLDWNDPROC", SetWindowLong(hWndControl, %GWL_WNDPROC, CODEPTR(Edit_SubclassProc))
    
      CONTROL ADD BUTTON,  hDlg, %IDCANCEL,    "&Quit",  370,  305,  31,  14 CALL CancelCallBack
      ', %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW OR %BS_PUSHLIKE, 0
    
      DIALOG SHOW MODAL hDlg, CALL MAINDIALOGCallBack TO Result
    
      IF Result = 0 THEN
        EXIT SUB
      END IF
      DIALOG END hDlg
    
      hDlg = 0
    END SUB
    
    CALLBACK FUNCTION MAINDIALOGCallBack
    
      SELECT CASE AS LONG CBMSG
        CASE %WM_INITDIALOG
          '--------------------------------------------------------------------
          ghKbrdHook = SetWindowsHookEx(%WH_KEYBOARD, CODEPTR(KeyboardHook), _
          0, GetCurrentThreadId)
          '====================================================================
          LOCAL Lb         AS LOGBRUSH
          LOCAL lf         AS LOGFONT
          LOCAL trc        AS RECT  
          LOCAL ptDlgBg    AS DIALOGBACKGROUND PTR
          LOCAL hDC        AS DWORD
          LOCAL hDCBg      AS DWORD
          LOCAL hEdit      AS DWORD
          LOCAL cxEdit     AS LONG
          LOCAL cyEdit     AS LONG
          STATIC hFont11   AS LONG
          STATIC hBrush10  AS LONG
    
          CALL CreateBg(CBHNDL,0,0,0)
    
          hFont11 = MakeFont("MS Sans Serif", 8)
          GetObject hFont11, SIZEOF(lf), BYVAL VARPTR(lf)
          lf.lfWeight = %FW_BOLD
          Lb.lbStyle  = %NULL_BRUSH
          hBrush10  = CreateSolidBrush(GetSysColor(%COLOR_3DFACE))
    
          SendMessage GetDlgItem(hDlg, %IDCANCEL), %WM_SETFONT, hFont11, 0
          SendMessage GetDlgItem(hDlg, %IDT_TEXT), %WM_SETFONT, hFont11, 0
    
        CASE %WM_CTLCOLORDLG
          CALL PaintBg(CBHNDL,CBWPARAM,0,0,0)
          FUNCTION = GetStockObject(%NULL_BRUSH)
    
        CASE %WM_CTLCOLOREDIT
    
          SELECT CASE GetDlgCtrlID(CBLPARAM) ' paints textbox background, but flickers
            CASE %IDT_TEXT
              SetTextColor CBWPARAM, RGB(64,0,0)
              SetBkMode CBWPARAM,%TRANSPARENT
              FUNCTION = GetStockObject(%NULL_BRUSH)
          END SELECT
    
        CASE %WM_SIZE
          CALL CreateBg(CBHNDL,0,0,0)
          
          InvalidateRect CBHNDL, BYVAL %NULL, %TRUE
          UpdateWindow CBHNDL
          
          IF CBWPARAM <> %SIZE_MINIMIZED THEN
            hEdit = GetDlgItem(CBHNDL, %IDT_TEXT)
            GetWindowRect hEdit, trc
            MapWindowPoints %NULL, CBHNDL, BYVAL VARPTR(trc), 2
            SetWindowPos hEdit, %NULL, 0, 0, LO(WORD, CBLPARAM) - trc.nLeft - 20, _
                         HI(WORD, CBLPARAM) - trc.nTop - 80, %SWP_NOZORDER OR %SWP_NOMOVE
          END IF
    
        CASE %WM_DESTROY
          ptDlgBg = RemoveProp(CBHNDL, "DIALOG_BACKGROUND")
          IF ptDlgBg THEN
            DeleteObject SelectObject(@ptDlgBg.hDC, @ptDlgBg.hBmpOld)
            DeleteDC @ptDlgBg.hDC
            HeapFree GetProcessHeap(), 0, ptDlgBg
          END IF
          ' The dialog is being destroyed, so release the bitmap handle
          UnhookWindowsHookEx ghKbrdHook
          DeleteObject hBrush10
          'For windows 98 problem to fix 1 keypress exit 3-27-2006 AND SKINS 4-24-2006
          DIALOG END CBHNDL, 5000
    
        ' Initialization handler - KEEPS HELPFILE ON TOP AND DISABLES hDlg, 2-19-2008
        CASE %WM_NCACTIVATE
          STATIC hWndSaveFocus AS DWORD
          IF ISFALSE CBWPARAM THEN
            ' Save control focus
            hWndSaveFocus = GetFocus()
            ELSEIF hWndSaveFocus THEN
              ' Restore control focus
              SetFocus(hWndSaveFocus)
              hWndSaveFocus = 0
          END IF
    
        CASE %WM_COMMAND
    
          SELECT CASE AS LONG CBCTL
            IF CBCTL = %IDT_TEXT THEN
             KEY13 = 1
            END IF
            FUNCTION = 1
    
            ' To close program with 1 keypress for windows 98, must be a case, not if cbctl
            CASE %IDCANCEL ' <ESC> KEY
               IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                  DIALOG POST CBHNDL, %WM_USER + 500, 0, 0
               END IF
               FUNCTION = 1
          END SELECT
    
      END SELECT
    
    END FUNCTION ' FUNCTION DIARYCALLBACK FUNCTION
    
    FUNCTION SetColor (BYVAL tCOLOR AS BYTE) AS WORD
        ' the windows api GradientFill routine wants r/g/b colors to be
        ' 16 bit words with the 8 bit color values left shifted 8 bits.
        ' this takes care of that.
        LOCAL clr AS WORD
        clr = tCOLOR
        SHIFT LEFT clr, 8
        FUNCTION = clr
    END FUNCTION
    
    SUB PaintBg(BYVAL hDlg AS LONG, BYVAL hDC AS DWORD, BYVAL r AS LONG, BYVAL g AS LONG, BYVAL b AS LONG)
    
      LOCAL rc        AS RECT   
      LOCAL ptDlgBg   AS DIALOGBACKGROUND PTR
      LOCAL hDCBg     AS DWORD
    
      ptDlgBg = GetProp(hDlg, "DIALOG_BACKGROUND")
      hDCBg = @ptDlgBg.hDC
      GetClientRect hDlg, rc
      BitBlt hDC, 0, 0, rc.nRight, rc.nBottom, hDCBg, 0, 0, %SRCCOPY
    
    END SUB
    
    '-------------------------------------------------------------------------------
    '
    ' CreateBg
    ' This procedure creates a bitmap, gradient fills it, and stores
    ' the entire thing in a memory device context.
    ' The same technique can be used for bitmaps loaded from a file or a resource.
    '
    '-------------------------------------------------------------------------------
    
    SUB CreateBg(BYVAL hDlg AS LONG, BYVAL r AS LONG, BYVAL g AS LONG, BYVAL b AS LONG)
         ' this is to paint the background of the dialog
         ' it's all straight out of the MSDN help file.  We can change the values
         ' if we like.
         LOCAL rc       AS Rect 
         LOCAL ptDlgBg  AS DIALOGBACKGROUND PTR
         LOCAL hDC      AS DWORD
         LOCAL hDCBg    AS DWORD
         LOCAL hBmpOld  AS DWORD
    
         LOCAL Xin&
         LOCAL Yin&,Temp&,cRed&,cGreen&,cBlue&
         DIM vert(1) AS TRIVERTEX
         DIM gRect AS GRADIENT_RECT
    
           ' Tile the background
         GetClientRect hDlg, rc
    
         ptDlgBg = GetProp(hDlg, "DIALOG_BACKGROUND")
         IF ptDlgBg THEN
           hDCBg = @ptDlgBg.hDC
           DeleteObject SelectObject(hDCBg, @ptDlgBg.hBmpOld)    
           DeleteDC hDCBg
         ELSE
           ptDlgBg = HeapAlloc(GetProcessHeap(), %HEAP_ZERO_MEMORY, SIZEOF(@ptDlgBg))
           SetProp hDlg, "DIALOG_BACKGROUND", ptDlgBg
         END IF
         hDC = GetDC(hDlg)
         hDCBg = CreateCompatibleDC(hDC)
         @ptDlgBg.hDC = hDCBg
         @ptDlgBg.hBmpOld = SelectObject(hDCBg, CreateCompatibleBitmap(hDC, rc.nRight, rc.nBottom))
    
         Xin = rc.nRight - rc.nLeft
         Yin = rc.nBottom - rc.nTop
         Xin = rc.nRight - rc.nLeft
         Yin = rc.nBottom - rc.nTop
    
         'Temp& = RGB(205,214,255)
         Temp& = RGB(226,187,143) ' TAN 'RGB(255,128,255) ' changes to magenta
         IF Temp& <> 0 THEN
           cRed&   = Temp& MOD 256
           cGreen& = (Temp& \ 256) MOD 256
           cBlue&  = ((Temp& \ 256) \ 256) MOD 256
         ELSE
           cRed&   = 192
           cGreen& = 224
           cBlue&  = 192
         END IF
         vert(0).x      = 0 '29 '58 '116 'textbox up lft col in pixels  '0
         vert(0).y      = 0 '37 '74 '148 'textbox up lft row in pixels  '0
         vert(0).Red    = SetColor(cRed& - 90)
         vert(0).Green  = SetColor(cGreen& - 90)
         vert(0).Blue   = SetColor(cBlue& - 90)
         vert(0).Alpha  = &H0000
         vert(1).x      = xin
         vert(1).y      = yin
         vert(1).Red    = SetColor(cRed&)
         vert(1).Green  = SetColor(cGreen&)
         vert(1).Blue   = SetColor(cBlue&)
         vert(1).Alpha  = &H0000
         gRect.UpperLeft  = 0
         gRect.LowerRight = 1
         GradientFill hDCBg, vert(0), 2, gRect, 1, %GRADIENT_FILL_RECT_V
    
         ReleaseDC hDlg, hDC
    
    END SUB
    
    '-------------------------------------------------------------------------------
    '
    ' PaintEdit
    ' This procedure renders the background and text of an edit control to a
    ' memory dc to avoid flicker.
    '
    '-------------------------------------------------------------------------------
    
    FUNCTION PaintEdit _
      ( _
      BYVAL lpOldWndProc  AS DWORD, _
      BYVAL hWnd          AS DWORD, _
      BYVAL uMsg          AS DWORD, _
      BYVAL wParam        AS DWORD, _
      BYVAL lParam        AS LONG _
      ) AS LONG
    
      LOCAL trc       AS RECT 
      LOCAL ptDlgBg   AS DIALOGBACKGROUND PTR
      LOCAL hDCBg     AS DWORD
      LOCAL hDC       AS DWORD
      LOCAL hDCMem    AS DWORD
      LOCAL hBmpOld   AS DWORD
      LOCAL cxEdit    AS DWORD
      LOCAL cyEdit    AS DWORD
      LOCAL x         AS LONG
      LOCAL y         AS LONG
      LOCAL lRetVal   AS LONG
    
      ' Let the edit control do its thing.
      ' A flag is set to avoid double paints in case a WM_PAINT message is generated
      SetProp hWnd, "SKIP_PAINT_FLAG", 1
      lRetVal = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
      RemoveProp hWnd, "SKIP_PAINT_FLAG"
    
      GetClientRect hWnd, trc
      cxEdit = trc.nRight
      cyEdit = trc.nBottom
      MapWindowPoints hWnd, hDlg, BYVAL VARPTR(trc), 2
      x = trc.nLeft
      y = trc.nTop
    
      ' Get the background image of the dialog
      ' (it is stored in a memory dc)
      ptDlgBg = GetProp(hDlg, "DIALOG_BACKGROUND")
      hDCBg = @ptDlgBg.hDC
    
      ' Render the background of the client area of the dialog that is occupied by the
      ' edit control to the memory dc used for drawing the contents of the edit control
      hDC = GetDC(hWnd)
      hDCMem = CreateCompatibleDC(hDC)
      hBmpOld = SelectObject(hDCMem, CreateCompatibleBitmap(hDC, cxEdit, cyEdit))
      BitBlt hDCMem, 0, 0, cxEdit, cyEdit, hDCBg, x, y, %SRCCOPY
      ' Tell the edit control to draw its text to the memory dc
      SendMessage hWnd, %WM_PRINTCLIENT, hDCMem, %PRF_CLIENT
      ' Copy the finished product to the screen
      HideCaret hWnd
      BitBlt hDC, 0, 0, cxEdit, cyEdit, hDCMem, 0, 0, %SRCCOPY
      ShowCaret hWnd
      DeleteObject SelectObject(hDCMem, hBmpOld)
      DeleteDC hDCMem
      ReleaseDC hWnd, hDC
    
      FUNCTION = lRetVal
    
    END FUNCTION
    
    '-------------------------------------------------------------------------------
    
    FUNCTION Edit_SubclassProc _
      ( _
      BYVAL hWnd    AS DWORD, _ ' control handle
      BYVAL uMsg    AS DWORD, _ ' type of message
      BYVAL wParam  AS DWORD, _ ' first message parameter
      BYVAL lParam  AS LONG _   ' second message parameter
      ) EXPORT AS LONG
    
      LOCAL tps             AS PAINTSTRUCT
      LOCAL lpOldWndProc    AS DWORD    ' address of original window procedure
    
      lpOldWndProc = GetProp(hWnd, "OLDWNDPROC")
    
      SELECT CASE uMsg
        CASE %WM_KEYDOWN
          FUNCTION = PaintEdit(lpOldWndProc, hWnd, uMsg, wParam, lParam)
          EXIT FUNCTION
    
        CASE %WM_CHAR
          FUNCTION = PaintEdit(lpOldWndProc, hWnd, uMsg, wParam, lParam)
          EXIT FUNCTION
    
        CASE %WM_LBUTTONDOWN
          FUNCTION = PaintEdit(lpOldWndProc, hWnd, uMsg, wParam, lParam)
          EXIT FUNCTION
    
        CASE %WM_MOUSEMOVE
          IF GetCapture() = hWnd THEN
            FUNCTION = PaintEdit(lpOldWndProc, hWnd, uMsg, wParam, lParam)
            EXIT FUNCTION
          END IF
    
        CASE %WM_PAINT
          BeginPaint hWnd, tps
          EndPaint hWnd, tps
          IF GetProp(hWnd, "SKIP_PAINT_FLAG") = 0 THEN
            CALL PaintEdit(lpOldWndProc, hWnd, uMsg, wParam, lParam)
          END IF
          EXIT FUNCTION
    
        CASE %WM_DESTROY
          RemoveProp hWnd, "SKIP_PAINT_FLAG"
          ' Remove control subclassing
          SetWindowLong hWnd, %GWL_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")
      END SELECT
    
      FUNCTION = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
    
    END FUNCTION
    Last edited by Dominic Mitchell; 20 Feb 2008, 01:37 AM. Reason: Invalidate entire client area of dialog on WM_SIZE

    Leave a comment:


  • Dominic Mitchell
    replied
    Ignore the last question, the solution I came up with works for both single and mutiline text boxes.

    Leave a comment:


  • Dominic Mitchell
    replied
    Are all the text boxes multiline, or is it acceptable to make any that are single line mutiline?

    Leave a comment:


  • BRENT GARDNER
    replied
    Dominic,

    Here compilable sample:

    Code:
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    
    %IDT_TEXT       = 1000
    
    GLOBAL hDlg AS DWORD
    GLOBAL ghKbrdHook, KEYP, KEY13 AS LONG
    GLOBAL lpfnKbrdHook AS LONG
    '========================KEYBOARDHOOK FUNCTION===================================================
       FUNCTION KeyboardHook(BYVAL iCode AS INTEGER, BYVAL wParam AS LONG, _
        BYVAL lParam AS LONG) AS DWORD
        FUNCTION = CallNextHookEx(ghKbrdHook, iCode, wParam, lParam)
         IF iCode = %HC_ACTION THEN
           IF ISFALSE(lParam AND &H80000000) THEN ' KeyUp
            STATIC nHook AS LONG
            INCR nHook
            KEYP = wParam
            IF KEY13 = 1 THEN
               KEYP = 32  ' <SPACE BAR>, SUB PRINTRECORD, 7-18-2007, so dialog does not leave shadow
            END IF
           END IF
         END IF
       END FUNCTION
        
       FUNCTION MakeFont(BYVAL SYSFont AS STRING, BYVAL PointSize AS LONG) AS LONG
         LOCAL hDC      AS LONG
         LOCAL CyPixels AS LONG
         hDC = GetDC(%HWND_DESKTOP)
         CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
         ReleaseDC %HWND_DESKTOP, hDC
         PointSize =-MulDiv(PointSize, CyPixels, 72)
         FUNCTION = CreateFont(PointSize, 0, 0, 0, %FW_NORMAL, 0, 0, 0, _
         %ANSI_CHARSET, %OUT_TT_PRECIS, %CLIP_DEFAULT_PRECIS, _
            %DEFAULT_QUALITY, %FF_DONTCARE, BYCOPY SYSFont)
       END FUNCTION
    
       FUNCTION WINMAIN (BYVAL hCurInstance  AS LONG, _
                          BYVAL hPrevInstance AS LONG, _
                          BYVAL lpszCmdLine   AS ASCIIZ PTR, _
                          BYVAL nCmdShow      AS LONG) EXPORT AS LONG
         ' File to open when program starts up
         CALL MAINDIALOG
       END FUNCTION 'FUNCTION WINMAIN
    
       CALLBACK FUNCTION CancelCallBack
          DIALOG END CBHNDL, 0
       END FUNCTION
    
       SUB MAINDIALOG
         STATIC hBrush50 AS DWORD
         LOCAL    Result AS LONG
         GLOBAL   x1, y1, x2, y2, hToolTip AS LONG
          x1 = 77: y1 = 22: x2 = 407: y2 = 347 ' = units 407 wide for windows 98, 10-22-2007
         ' Create our top level primary GUI
         DIALOG NEW %HWND_DESKTOP, "", 0, 0, x2, y2, _
           %DS_CENTER OR %DS_SETFONT OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX _
           OR %WS_OVERLAPPEDWINDOW, %WS_EX_CONTROLPARENT, TO hDlg
    
         IF ERR OR hDlg = 0 THEN EXIT SUB  ' Error occurred
         
         CONTROL ADD TEXTBOX,  hDlg, %IDT_TEXT,      "",              58,   74 ,270, 205, _
          %ES_NOHIDESEL OR %ES_AUTOVSCROLL OR %ES_MULTILINE OR %ES_LEFT _
           OR %WS_TABSTOP, %WS_EX_TRANSPARENT
           
         CONTROL ADD BUTTON,  hDlg, %IDCANCEL,    "&Quit",  370,  305,  31,  14 CALL CancelCallBack
         ', %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW OR %BS_PUSHLIKE, 0
    
         DIALOG SHOW MODAL hDlg, CALL MAINDIALOGCallBack TO Result
    
         IF Result = 0 THEN
          EXIT SUB
         END IF
         DIALOG END hDlg
         hDlg = 0
       END SUB
    
       CALLBACK FUNCTION MAINDIALOGCallBack
        SELECT CASE AS LONG CBMSG
        CASE %WM_INITDIALOG
         '--------------------------------------------------------------------
         ghKbrdHook = SetWindowsHookEx(%WH_KEYBOARD, CODEPTR(KeyboardHook), _
         0, GetCurrentThreadId)
         '====================================================================
         LOCAL Lb         AS LOGBRUSH
         LOCAL lf         AS LOGFONT
         STATIC hFont11    AS LONG
         STATIC hBrush10  AS LONG
         
           hFont11 = MakeFont("MS Sans Serif", 8)
           GetObject hFont11, SIZEOF(lf), BYVAL VARPTR(lf)
           lf.lfWeight = %FW_BOLD
           Lb.lbStyle  = %NULL_BRUSH
           hBrush10  = CreateSolidBrush(GetSysColor(%COLOR_3DFACE))
           
           SendMessage GetDlgItem(hDlg, %IDCANCEL), %WM_SETFONT, hFont11, 0
           SendMessage GetDlgItem(hDlg, %IDT_TEXT), %WM_SETFONT, hFont11, 0
           
        CASE %WM_CTLCOLOREDIT
          SELECT CASE GetDlgCtrlID(CBLPARAM) ' paints textbox background, but flickers
            CASE 1000
             SelectObject CBWPARAM, hFont11
             SetTextColor CBWPARAM, RGB(64,0,0)
             SetBkMode CBWPARAM,%TRANSPARENT
             CALL PaintBg(CBHNDL,CBWPARAM,0,0,0)
            FUNCTION = hFont11
          END SELECT
    
         CASE %WM_DESTROY
            ' The dialog is being destroyed, so release the bitmap handle
             UnhookWindowsHookEx ghKbrdHook
             DeleteObject hBrush10
          'For windows 98 problem to fix 1 keypress exit 3-27-2006 AND SKINS 4-24-2006
          DIALOG END CBHNDL, 5000
          
          ' Initialization handler - KEEPS HELPFILE ON TOP AND DISABLES hDlg, 2-19-2008
        CASE %WM_NCACTIVATE
          STATIC hWndSaveFocus AS DWORD
          IF ISFALSE CBWPARAM THEN
          ' Save control focus
          hWndSaveFocus = GetFocus()
          ELSEIF hWndSaveFocus THEN
          ' Restore control focus
          SetFocus(hWndSaveFocus)
          hWndSaveFocus = 0
          END IF
          
        CASE %WM_COMMAND
           SELECT CASE AS LONG CBCTL
            IF CBCTL = %IDT_TEXT THEN
             KEY13 = 1
             
             SELECT CASE HIWRD(CBWPARAM)
                CASE %EN_UPDATE,%EN_CHANGE,%EN_VSCROLL
                   CALL reduceflick ' USE THIS IN PLACE OF "control redraw cbhndl, %idt_text
             END SELECT
             'EXIT FUNCTION   ' Causes redraw
            END IF
            FUNCTION = 1
            ' To close program with 1 keypress for windows 98, must be a case, not if cbctl
            CASE %IDCANCEL ' <ESC> KEY
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
              DIALOG POST CBHNDL, %WM_USER + 500, 0, 0
             END IF
             FUNCTION = 1
             
           END SELECT
        END SELECT
    
       END FUNCTION ' FUNCTION DIARYCALLBACK FUNCTION
    
    FUNCTION SetColor (BYVAL tCOLOR AS BYTE) AS WORD
        ' the windows api GradientFill routine wants r/g/b colors to be
        ' 16 bit words with the 8 bit color values left shifted 8 bits.
        ' this takes care of that.
        LOCAL clr AS WORD
        clr = tCOLOR
        SHIFT LEFT clr, 8
        FUNCTION = clr
    END FUNCTION
    
    SUB PaintBg(BYVAL hDialog AS LONG, BYVAL hDC AS DWORD, BYVAL r AS LONG, BYVAL g AS LONG, BYVAL b AS LONG)
         ' this is to paint the background of the dialog
         ' it's all straight out of the MSDN help file.  We can change the values
         ' if we like.
         LOCAL rc AS Rect
         LOCAL Xin&
         LOCAL Yin&,Temp&,cRed&,cGreen&,cBlue&
         DIM vert(1) AS TRIVERTEX
         DIM gRect AS GRADIENT_RECT
    
           ' Tile the background
         GetWindowRect GetDlgItem(hDlg, %IDT_TEXT), rc
    
         Xin = rc.nRight - rc.nLeft
         Yin = rc.nBottom - rc.nTop
         Xin = rc.nRight - rc.nLeft
         Yin = rc.nBottom - rc.nTop
    
         'Temp& = RGB(205,214,255)
         Temp& = RGB(226,187,143) ' TAN 'RGB(255,128,255) ' changes to magenta
         IF Temp& <> 0 THEN
           cRed&   = Temp& MOD 256
           cGreen& = (Temp& \ 256) MOD 256
           cBlue&  = ((Temp& \ 256) \ 256) MOD 256
         ELSE
           cRed&   = 192
           cGreen& = 224
           cBlue&  = 192
         END IF
         vert(0).x      = 0 '29 '58 '116 'textbox up lft col in pixels  '0
         vert(0).y      = 0 '37 '74 '148 'textbox up lft row in pixels  '0
         vert(0).Red    = SetColor(cRed& - 90)
         vert(0).Green  = SetColor(cGreen& - 90)
         vert(0).Blue   = SetColor(cBlue& - 90)
         vert(0).Alpha  = &H0000
         vert(1).x      = xin
         vert(1).y      = yin
         vert(1).Red    = SetColor(cRed&)
         vert(1).Green  = SetColor(cGreen&)
         vert(1).Blue   = SetColor(cBlue&)
         vert(1).Alpha  = &H0000
         gRect.UpperLeft  = 0
         gRect.LowerRight = 1
         GradientFill hDc, vert(0), 2, gRect, 1, %GRADIENT_FILL_RECT_V
    
    END SUB
                   
        SUB ReduceFlick  ' per Chris Boss
           LOCAL rtc AS RECT
           ' Works either way?
           GetWindowRect GetDlgItem(hDlg, %IDT_TEXT), rtc
           ScreenToClient hDlg, BYVAL VARPTR(rtc.nLeft)  ' converts first pair
           InvalidateRect hDlg, rtc, 1
           ScreenToClient hDlg, BYVAL VARPTR(rtc.nRight) ' converts second pair
           InvalidateRect hDlg, rtc, 1
        END SUB
    when I drag mouse in textbox, it gradually disapears?

    Leave a comment:


  • BRENT GARDNER
    replied
    Hi Dominic,

    Just wanted to post lastest testing info. See if I can do what you said,
    but will be later tonight.

    If I CALL PaintBg(CBHNDL, CBWPARAM,0,0,0) from %WM_CTLCOLOREDIT, it paints gradient rect behind textbox alright and dialog is not transparent, but any editing flickers as bad as ever?
    Code:
      
       CASE %WM_CTLCOLOREDIT
          SELECT CASE GetDlgCtrlID(CBLPARAM) 
            CASE 104
             SelectObject CBWPARAM, hFont11
             SetTextColor CBWPARAM, RGB(64,0,0)
             SetBkMode CBWPARAM,%TRANSPARENT
             CALL PaintBg(CBHNDL,CBWPARAM,0,0,0)
            FUNCTION = hFont11
          END SELECT
          EXIT FUNCTION
    In Sub PaintBg, I use:
    GetWindowRect GetDlgItem(hDlg, %IDT_TEXT), rc

    Leave a comment:


  • Dominic Mitchell
    replied
    Post a compileable sample with the bare essentials.
    What happens when you drag the mouse in the text box?

    Leave a comment:


  • BRENT GARDNER
    replied
    Using Dominic's code and getting the dimensions of my textbox, it will
    paint gradient background for textbox and I can edit text with no flicker!
    Problem is that the rest of the dialog is transparent and shows desktop?
    I guess I need some help on how to just paint a region the size of textbox and not entire dialog?

    Leave a comment:


  • BOB MECHLER
    replied
    Don't know myself but I've seen code where it works for a static label to draw a gradient on it's background. I felt the non-flickering transparent effect on the static label with a gradient dialog background was good enough for now. Interested to see the answer myself.

    Bob Mechler

    Leave a comment:


  • BRENT GARDNER
    replied
    Very interesting. Is there a way to convert the paint structure so that it
    will paint background of textbox instead of dialog? I get too much flicker
    when editing text in textbox over a bitmap, which is rendered on a
    graphic control. Thought, maybe just paint a gradient background for
    textbox control and do away with graphic control. Should not be any
    flicker?

    Leave a comment:


  • BOB MECHLER
    replied
    Forgot to mention that this approach allowed the CONTROL ADD LABEL statements to work fine. I didn't need to go to SDK.

    Bob Mechler

    Leave a comment:


  • BOB MECHLER
    replied
    I moved the relevant changes you proposed to my production code and it works absolutely great. I can now happily erase and/or replace all the controls on my gradient background dialog as much as I want and no flicker.

    Thanks Dominic!! As a bonus I used Chris's suggestion of loading a bitmap into the dialog and that also works well too. Great,great,great!

    Thanks,

    Bob Mechler

    Leave a comment:


  • Dominic Mitchell
    replied
    Try the modified version of your code shown below.
    The old version had a serious memory leak because a new font was created with each invocation of dlgMain.
    Also, your old code did not have the modification to WM_ERASEBKGND suggested by Chris.
    Unfortunately, even with that modification you will still get streaks when a window is dragged across your dialog.

    This modified version paints the background during WM_CTLCOLORDLG, adds an hDC parameter to the PaintBg procedure, and drops BeginPaint/EndPaint.
    Also, the font is created and destroyed during WM_INITDIALOG and WM_DESTROY respectively.

    Code:
    #DIM ALL
    #REGISTER ALL
    #INCLUDE "win32api.inc"
    
    GLOBAL ghMain AS DWORD,hFontCap AS LONG
        %LBL_LABEL = 1001
        %LBL_AFTER = 1002
        %LBL_DDT   = 1003
        %NEW_LBL1  = 1004
        %NEW_LBL2  = 1005
        %NEW_LBL3  = 1006
        %NEW_LBL4  = 1007
        %BUT_DDT   = 2001
    
    FUNCTION MakeFont(BYVAL CFont AS STRING, BYVAL PointSize AS LONG) AS LONG
    
      LOCAL hDC      AS LONG
      LOCAL CyPixels AS LONG
    
      hDC = GetDC(%HWND_DESKTOP)
      CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
      ReleaseDC %HWND_DESKTOP, hDC
    
      PointSize = (PointSize * CyPixels) \ 72
      FUNCTION = CreateFont(0 - PointSize, 0, 0, 0, %FW_NORMAL, 0, 0, 0, _
                %ANSI_CHARSET, %OUT_TT_PRECIS, %CLIP_DEFAULT_PRECIS, _
                %DEFAULT_QUALITY, %FF_DONTCARE, BYCOPY CFONT)
    END FUNCTION 
    
    CALLBACK FUNCTION dlgMain
      LOCAL szNewStaticText AS STRING 
      DIM hWndControl AS DWORD
      SELECT CASE CBMSG 
        CASE %WM_INITDIALOG
          hFontCap = MakeFont("Ms Sans Serif",10) 
    
        CASE %WM_DESTROY
          DeleteObject hFontCap
          
        CASE %WM_CTLCOLORSTATIC
          SELECT CASE GetDlgCtrlID(CBLPARAM) 
            CASE %LBL_LABEL TO %NEW_LBL4      'in case other labels need different handling
              SelectObject CBWPARAM, hFontCap
              SetBkMode CBWPARAM,%TRANSPARENT
             FUNCTION = GetStockObject(%NULL_BRUSH)
          END SELECT 
    
        CASE %WM_CTLCOLORDLG
          CALL PaintBg(CBHNDL,CBWPARAM,0,0,0)      
          FUNCTION = GetStockObject(%NULL_BRUSH)
    
        CASE %WM_COMMAND
          SELECT CASE CBCTL
            CASE %BUT_DDT
              szNewStaticText = "New Label 1"
              hWndControl = CreateWindowEx(%WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING , _
                                     "Static", _  ' window class name
                                     BYCOPY szNewStaticText, _    ' window caption
                                     %SS_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                     10, 64, 150, 18, _
                                     ghMain, %NEW_LBL1, GetModuleHandle(BYVAL 0&), BYVAL %NULL)
              szNewStaticText = "New Label 2"
              hWndControl = CreateWindowEx(%WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING , _
                                     "Static", _  ' window class name
                                     BYCOPY szNewStaticText, _    ' window caption
                                     %SS_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                     10, 84, 150, 18, _
                                     ghMain, %NEW_LBL2, GetModuleHandle(BYVAL 0&), BYVAL %NULL)
              szNewStaticText = "New Label 3"
              hWndControl = CreateWindowEx(%WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING , _
                                     "Static", _  ' window class name
                                     BYCOPY szNewStaticText, _    ' window caption
                                     %SS_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                     10, 104, 150, 18, _
                                     ghMain, %NEW_LBL3, GetModuleHandle(BYVAL 0&), BYVAL %NULL)
              szNewStaticText = "New Label 4"
              hWndControl = CreateWindowEx(%WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING , _
                                     "Static", _  ' window class name
                                     BYCOPY szNewStaticText, _    ' window caption
                                     %SS_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                     10, 124, 150, 18, _
                                     ghMain, %NEW_LBL4, GetModuleHandle(BYVAL 0&), BYVAL %NULL)
              
          END SELECT  
      END SELECT    
    END FUNCTION
    
    FUNCTION PBMAIN
        DIM hWndControl AS DWORD,szControlText AS STRING,cnt AS LONG
    
        DIALOG NEW 0, "Transparent sdk style label ",,,200,170,%WS_SYSMENU TO ghMain
    
        szControlText = "Before Show ghMain"
        hWndControl = CreateWindowEx(%WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING , _
                                     "Static", _  ' window class name
                                     BYCOPY szControlText, _    ' window caption
                                     %SS_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                     10, 10, 150, 18, _
                                     ghMain, %LBL_LABEL, GetModuleHandle(BYVAL 0&), BYVAL %NULL)
        DIALOG SHOW MODELESS ghMain CALL dlgMain
        
        szControlText = "After Show ghMain"
        hWndControl = CreateWindowEx(%WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING , _
                                     "Static", _  ' window class name
                                     BYCOPY szControlText, _    ' window caption
                                     %SS_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                     10, 30, 150, 18, _
                                     ghMain, %LBL_AFTER, GetModuleHandle(BYVAL 0&), BYVAL %NULL)
    
        CONTROL ADD LABEL, ghMain,%LBL_DDT,"After Show ghMain DDT",100,30,130,18,%SS_LEFT OR %WS_CHILD OR %WS_VISIBLE _
                                                                   OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN, _
                                                                   %WS_EX_TRANSPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING
    
        CONTROL ADD BUTTON, ghMain,%BUT_DDT,"Add more labels",120,130,60,14                                                                                                                                 
        DO
          DIALOG DOEVENTS TO cnt      
        LOOP UNTIL cnt = 0
    END FUNCTION
    
    FUNCTION SetColor (BYVAL tCOLOR AS BYTE) AS WORD
        ' the windows api GradientFill routine wants r/g/b colors to be
        ' 16 bit words with the 8 bit color values left shifted 8 bits.
        ' this takes care of that.
        LOCAL clr AS WORD
        clr = tCOLOR
        SHIFT LEFT clr, 8
        FUNCTION = clr
    END FUNCTION 
    
    SUB PaintBg(BYVAL hDialog AS LONG, BYVAL hDC AS DWORD, BYVAL r AS LONG, BYVAL g AS LONG, BYVAL b AS LONG)
         ' this is to paint the background of the dialog
         ' it's all straight out of the MSDN help file.  We can change the values
         ' if we like.
         LOCAL rc AS Rect
    
         LOCAL Xin&
         LOCAL Yin&,Temp&,cRed&,cGreen&,cBlue&
         DIM vert(1) AS TRIVERTEX
         DIM gRect AS GRADIENT_RECT
    
           ' Tile the background
         GetClientRect hdialog, rc
         Xin = rc.nRight - rc.nLeft
         Yin = rc.nBottom - rc.nTop
         Xin = rc.nRight - rc.nLeft
         Yin = rc.nBottom - rc.nTop
         Temp& = RGB(205,214,255)
         IF Temp& <> 0 THEN
           cRed&   = Temp& MOD 256
           cGreen& = (Temp& \ 256) MOD 256
           cBlue&  = ((Temp& \ 256) \ 256) MOD 256
         ELSE
           cRed&   = 192
           cGreen& = 224
           cBlue&  = 192
         END IF
         vert(0).x      = 0
         vert(0).y      = 0
         vert(0).Red    = SetColor(cRed& - 90)
         vert(0).Green  = SetColor(cGreen& - 90)
         vert(0).Blue   = SetColor(cBlue& - 90)
         vert(0).Alpha  = &H0000
         vert(1).x      = xin
         vert(1).y      = yin
         vert(1).Red    = SetColor(cRed&)
         vert(1).Green  = SetColor(cGreen&)
         vert(1).Blue   = SetColor(cBlue&)
         vert(1).Alpha  = &H0000
         gRect.UpperLeft  = 0
         gRect.LowerRight = 1
         GradientFill hDc, vert(0), 2, gRect, 1, %GRADIENT_FILL_RECT_V
    
    END SUB

    Leave a comment:


  • BOB MECHLER
    replied
    I tried that Peter but with as many labels as I draw at one time, going from screen to screen removing and then adding up 40 labels the redraw causes an unacceptable flicker. I'm playing with loading a bitmap and it seems to work just fine. What I want to do is create a gradient bitmap and load it as you would from a resource file to allow the user to choose their own starting color. I'm in the process of trying to find some code that will create the gradient bitmap and then how to transfer it to the dialog.

    Bob Mechler

    Leave a comment:


  • Peter Jinks
    replied
    Hi Bob,

    You mentioned in one of your posts the "-1, -2 method", but that it doesn't work for DDT controls placed after the SHOW MODELESS. I'm guessing that the method you are referring to is CONTROL SET COLOR ? If so, then that does appear to work after the SHOW statement, but you need to force a redraw. i.e. if you add these two lines:
    Code:
    CONTROL SET COLOR ghMain, %LBL_DDT, -1, -2
    CONTROL REDRAW ghMain, %LBL_DDT
    After the CONTROL ADD LABEL, then it appears to work fine.

    Not sure if that helps any, and I get the sneaking feeling I'm missing something, but this appears to work...

    Regards,

    Pete.

    Leave a comment:


  • BOB MECHLER
    replied
    I think using a brush in this situation won't work. I put a little sleep 300 in between putting 23 new labels on the screen and this is how it proceeded. It started by putting rectangles with no text of the dialog's original color (before the gradient), After it created these empty rectangles, it placed the text and the transparent effect only when it hit a messagbox or a textbox.

    I'm going now in the direction of transparent bits as Chris suggested. I need the ability to put the text on the screen with a transparent background without the intermediate steps. This particular program has 259 fields that come into view with information based on buttons I provide. The problem of course is not there if I abandon the gradient effect and make the labels have the same background color as the dialog.

    I thought I had the problem licked with the SDK labels but in practice they acted very much like the DDT labels if I drew enough of them at one time.

    BOB MECHLER

    Leave a comment:


  • BOB MECHLER
    replied
    The following works if placed right after the CONTROL ADD LABEL statement if this statement is being executed after the Dialog Show Modeless.

    Code:
        CONTROL SHOW STATE ghMain,%LBL_DDT,%SW_HIDE                                                               
        CONTROL SHOW STATE ghMain,%LBL_DDT,%SW_SHOW
    Last edited by BOB MECHLER; 16 Feb 2008, 06:37 PM. Reason: More info

    Leave a comment:

Working...
X