Results 1 to 5 of 5

Thread: Gradient window background is not working properly

  1. #1
    Member
    Join Date
    Aug 2015
    Location
    Keralam, India
    Posts
    118
    Rep Power
    17

    Gradient window background is not working properly

    Hi all,
    I am trying to implement a gradient background color in tWindow class. Here is the the function for it.
    Function tWindow.SetGradientBackColor(Byval c1 As Long, Byval c2 As Long)
        Me.mGradientBkGnd = true
        Me.mIsBkChanged = True
        Me.mGradiClrOne = c1 '// This is Long
        Me.mGradiClrTwo = c2 '// This is also Long
        if me.mIsCreated Then Win_InvalidateRect(Me.mHandle, 0, true)
    End function
    
    And the user can call this function like this.
    win.SetGradientBackColor(0xFFCCCC, 0x6656FF)
    
    When the user calls this function, we will end up in WM_ERASEBKGND message. And in that message, I tried this function.
    Function tWindow.CreateGreadientBrush(Byval hDc As Dword) 
        Dim tc1 As tRgb(me.mGradiClrOne)  '// tRgb is my UDT. I will show the elements.
        Dim tc2 As tRgb(me.mGradiClrTwo) 
        Dim rct As RECT
        Win_getclientrect(me.mHandle, rct)
        Dim gBrush As Dword = 0
        Dim memHdc As Dword = Win_CreateCompatibleDC(hDc)
        Dim hBmp As Dword = Win_CreateCompatibleBitmap(hDc, rct.nRight, rct.nBottom)
        Dim loopEnd As Long = rct.nBottom
        Win_SelectObject(memHdc, hBmp)             
         
        For i as Long = 0 to loopEnd - 1
          Dim tRct As Rect
    
          Dim red as Long
          Dim green As Long
          Dim blue As Long       
                
          red = tc1.Red + (i * ((tc2.Red - tc1.Red)  / loopEnd))       
          green = tc1.Green + ( i * (( tc2.Green - tc1.Green) / loopEnd))       
          blue = tc1.Blue + ( i * ((tc2.Blue - tc1.Blue) / loopEnd))   
          
          gBrush = CreateSolidBrush(Rgb(red, green, blue))            
          
          tRct.nLeft = 0
          tRct.nTop = i
          tRct.nRight = rct.nRight - rct.nLeft
          tRct.nBottom = i + 1            
          
          Win_fillrect(memHdc, tRct, gBrush)
          Win_deleteobject(gBrush)          
        Next
        
        Dim Pattern As Dword = Win_CreatePatternBrush(hBmp)
        
        Win_deletedc(memHdc)
        Win_deleteobject(gBrush)
        Win_deleteobject(hBmp)
        
        Win_fillrect(hDc, rct, Pattern)
        Win_deleteobject(Pattern)
      End Function
    
    This is tRgb UDT.
    Type tRgb
      Red As Long
      Green As Long
      Blue As Long
    
      Function _Create(iVal As Long)    
        Me.Red = iVal >> 16     
        Me.Green = (Andb(iVal, 65280)) >> 8    
        Me.Blue = Andb(iVal, 255)    
      End function 
    
      Function PrintRgb()
        Printl(Me.Red, ", ", Me.Green, ", ", Me.Blue)
      End function
    End Type
    
    And the end result is attached here. Please check and guide me.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	Captured_000790.jpg 
Views:	10 
Size:	94.5 KB 
ID:	10255  
    Last edited by kcvinu; 17-04-2021 at 15:33.

  2. #2
    thinBasic MVPs ReneMiner's Avatar
    Join Date
    Oct 2012
    Location
    Germany
    Age
    51
    Posts
    1,418
    Blog Entries
    1
    Rep Power
    156
    Quote Originally Posted by kcvinu View Post
    Hi all,
    ...


    When the user calls this function, we will end up in WM_ERASEBKGND message. And in that message, I tried this function.
    Function tWindow.CreateGreadientBrush(Byval hDc As Dword)
    
    ....
    CreateGreadientBrush

    really a gread...y brush? is it a typo - same in your script? are you sure it is called? Are you using Call_IfExists? or call by function?GetPtr?
    I would spell it Gradient. thats the first a saw. the other thing i see, it is doing the gradient somehow but not as intended because you use the wrong type to store colors and positions,
    colors as rgb in range of bytes only. the desktops is multiple times that big in pixels
    . you need fractures of bytes to display it. trying to store 255 / 1000 in a long integer is like using a grenade to peel off a banana.

    try to use NO INTEGERS, exchange LONG and replace it with NUMBER

    there is that rect,
    width is right - left and
    heigth is bottom - top since bottom is the bigger number and we want to have an absolute / positive number not negative.
    lets assume an average screen 16:9 or 16:10 or just 4:3 width perhaps 1200 more ore less, height 750 , somewhere a taskbar...its not for being exact but to check in what ranges the numbers are.
    loopEnd were 768 maybe. and we can to make it look good go from very bright to very dark in 768 steps
    and also you go from orange to blue/ thats 9nce across the spectrum as these are opposing colors, orange i full red, half green, zero blue
    start with RGB 255,127,0 and go to purple blue 63, 0, 255
    the red will chANGE 192 IN Height STEPS from 255 to 63 that were to subtract 192/Height every iteration, an integer to use here will not word precise enough - thinBasic offers high precision numbers - completely free, you might use these., don't be shy. Really, at no extra cost you get as many Numbers as you need. As you want... grab a few, its always good to have some numbers in storage.

    mentioning it:
    also the storages must be a numbers where you keep colors ore the amount that schall change with every iteration
    so i suggest you look i did not completely fix everything up for yoou to use but i messed it up and captured and abused your
    VARIABLES, I GAVE THEM OTHER NAMES and forced them to do something completely different or even commented some of them...
    I did not use the provided fat brush nor the bucket to poor the color onto a thin line that has no space to deal with such amounts of paint
    ' the big brush and a bucket are not tools for me to draw a fine line
    ' i use like

    Declare Function FineLine Lib "gdi32.dll" Alias "Rectangle"( byval hDc As Dword, Byval L as Long, ByVal Y as Long, ByVal R as Long Byval H As Long
    
    
    
    
    Function tWindow.Gradient()
        Dim tc1 As tRgb(me.mGradiClrOne)  '// tRgb is my UDT. I will show the elements.
    												  ' these 2 udts  contain colors to start and end?
         Dim tc2 As tRgb(me.mGradiClrTwo) 'tc1 what is now and tc2 what shall be final?
         
        ' clean out a bit here...
        Dim rct As RECT
        Win_getclientrect(me.mHandle, rct)
        ':::::::Dim gBrush As Dword = 0 
        
        Dim Me_Hdc As Dword = Win_CreateCompatibleDC(hDc)
      ' i  will draw onto the windows surface...
      dim lHeight as Long at varptr(rct.nBottom) ' i capture this
      Dim lRight as Long at Varptr(rct.nRight) ' also my hostage now
      dim lLeft As Long at Varptr(rct.nLeft)  ' got all i need froom this...
    
    
    	' avoid missing pixels at left or right
       lLeft  -= 1
       lRight +=2                                       
     
      '   instead of creating additional variables i create shortcuts to the already existing
      
    '    Dim hBmp As Dword = Win_CreateCompatibleBitmap(hDc, rct.nRight, rct.nBottom)
    '    Dim loopEnd As Long = rct.nBottom
    '    Win_SelectObject(memHdc, hBmp)             
    '      
    '    For i as Long = 0 to loopEnd - 1
    '      Dim tRct As Rect
    '  Long can not be. The screen might be 750 pixels high. colors are only bytes from 0 to 255
    ' but integer can not show nor memorize the result of 255 / 750 
    ' for a gradient it should be smooth so we must use fractures of bytes.
    ' Numbers are great and very precise
    
    
    ' haha, i captured them, now they are mine:
          Dim red as Long = 1
          Dim green As Long = 2
          Dim blue As Long  = 3    
          number current(3) 
          current()= array assign  tc1.red, tc1.green, tc1.blue
          number change(3)
          ' what we want minus what we already have  is to achieve in the count of lHeight steps
          change(red) = (tc2.red - current(red) )/ lHeight   
          change(green) = (tc2.green - current(green) /lHeight
          change(blue) = tc2.blue - current(blue) / lHeight
          
    	while lHeight  
          ' no need to count for to next if we have the count already in lHeight 
           
                                '//// gBrush = CreateSolidBrush(Rgb(red, green, blue))   ////
                  
        ' i use a thinpencil  instead of Bob Ross' 2-inch-wide-brush  :)
        
    		sendmessage me.handle,  %META_SETTEXTCOLOR | %DS_SETFOREGROUND, 
    						0, RGB( current(red), current(green), current(blue) ) 
          ' this to change the current foreground color  on a dialog.
          ' somehow thinBsic did not grab one when the foreground-colors 
          ' were available for anyone and for free.  now dialogs  in thinbasic wait for the next
          ' outlet of paint to receive their forecolor adjustment..
           
          ' does not know %Meta_SetTextColor? = 0x0200
          '   |                   %DS_SetForeGround? = 0x0209
          '                       -----------------------------------
           '                 ...  use this as message:    0x0409
            '                                                  ========    
            
         if FineLine(  Me_hDC, lLeft, lHeight, lRight, lHeight ) then nop 
         
        ' now add what is needed per step to reach the destination Color
        
    		current(red) += change(red)
    		current(green) += change(green)
    		current(blue) += change(blue)    
    		
    		decr lHeight 
    		' 1 step less to go
    	wend 
    						
    						
    							
        end function
    
    if that will do?
    Last edited by ReneMiner; 17-04-2021 at 22:12.
    running thinBasic in HP Pavillon Desktop 590 a0xxx 8GB Ram AMD A6-9225 Radeon R4 5Compute Cores 2C+3G @2.6GHz

    OS: downgraded again to Windows 10 Enterprise x64 10.0.18363 Build 18363 (1909)
    (alternate OS: modified WinRE - boot from a fake ramdisk - currently in "reconstruction mode")

  3. #3
    Member
    Join Date
    Aug 2015
    Location
    Keralam, India
    Posts
    118
    Rep Power
    17
    @ReneMiner,

    First of all thank you for the reply. Well, CreateGreadientBrush was a typo. Usually, I do copy & paste for function names. I corrected it to "Gradient". I was about to change the code as per your suggestions but, suddenly a thought came into my mind. I have this same code working in Nim programming laguage. And the only only difference is, Nim is a strictly typed language and I can use cast function to convert data types. So, after a rethink, I decided to inspect the values of tRct RECT. In order to do that, I wrote a function like this.
    Function printRt(ByVal rt as twRect)
        'printl(StrFormat$("left : {1}, top : {2}, right : {3}, bottom : {4}", rt.nLeft, rt.nTop, rt.nRight, rt.nBottom)) '// You see this line commented ?
      End Function
    
    And I called this function, right after I fill the RECT values. When I run this program, it shocked me and gave this result. (Please see the attached image)

    It's so strange that i can't believe my eyes. Then for an experiment, I commented out the print statement in that function. Then also the code works good and gave the perfect result. How can I explain this behaviour.
    See, this the code looks like now.
    tRct.tLeft = 0
    tRct.tTop = i
    tRct.tRight = rct.nRight - rct.nLeft
    tRct.tBottom = i  + 1  
          
    printRt(tRct )   '// Dummy function goes here.      
          
    Win_fillrect(memHdc, tRct, gBrush)
    Win_deleteobject(gBrush)
    
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	Captured_000792.jpg 
Views:	8 
Size:	26.0 KB 
ID:	10256  
    Last edited by kcvinu; 17-04-2021 at 19:47.

  4. #4
    thinBasic MVPs ReneMiner's Avatar
    Join Date
    Oct 2012
    Location
    Germany
    Age
    51
    Posts
    1,418
    Blog Entries
    1
    Rep Power
    156
    begin controlid


    the printing on top messed it up?
    what would happen if you print it and use redraw/refresh?
    as in Callback
    callback function tWindow_OnSizing() As Long'-------------------------------------------------------------------
      static cW as Long
      static cH as Long
      dialog get client cbhndl to cw, cH
    
    
    'cw-=20    
    Dialog set Timer cbhndl , 0x1001
    , 200
    ' use of a timer to redraw the window content after resizing the
    'window to prevent the content from flickering and restores 
    ' fractured layout-appearance. just let 200ms pass by so its secured the 
    ' user has stopped his resizing action. 
        function = true  ' pass back" true" if the callback is handled so the os is 
    informed that a recepient was found for this message and it can stop searching 
    a another destination for it.
    '-------------------------------------------------------------------
                                                       End Function
    '###############################################O
                CallBack Function tWindow_OnTimer() As Long
    
    
    long W, H
    '-------------------------------------------------------------------
    if cbctl =0x1001 then    
        dialog get size cbhndl to w, h 
        dialog set size cbhndl, w + 1, h ' tiny movements horizontal
        dialog set size cbhndl, w, h + 1 ' & vertical to make the 
        dialog set size cbhndl, w, h     ' controls looking good again
        dialog Redraw cbhndl
        dialog kill timer cbhndl, 0x1001
    
       timer disables itself and wakes up again if anyone resizes the wincow,
    EndIf
    
    was that the name of your window? "tWindow?" it were bit confusing if you use an udt+aructure withot to dimension is as a variable.
    but maybe it has a meaning.


    prefix lowercase in front of uppercase have mostly a meaning in a CamelCase-Environment
    (t is mainly used to mark somthing as and udt, a /type name or types, c commonly used to mark the strucutres, prototypes of classes, u indicates a union, o marks objects,p mostly pointer, h handles handled by handless handlings handlers
    e events that just eccur / no one knows why......0
    -----------------------------------------------------------------------------------
    btw. thinbasic has built in a function,
    dialog set Gradient hDlg, directional_setting, startcolor, endcolor
    Last edited by ReneMiner; 17-04-2021 at 23:08.
    running thinBasic in HP Pavillon Desktop 590 a0xxx 8GB Ram AMD A6-9225 Radeon R4 5Compute Cores 2C+3G @2.6GHz

    OS: downgraded again to Windows 10 Enterprise x64 10.0.18363 Build 18363 (1909)
    (alternate OS: modified WinRE - boot from a fake ramdisk - currently in "reconstruction mode")

  5. #5
    Member
    Join Date
    Aug 2015
    Location
    Keralam, India
    Posts
    118
    Rep Power
    17
    @ReneMiner
    the printing on top messed it up?
    Yes, obviously. That's why I comment out that line.But still it is working fine. That's strange.

    was that the name of your window? "tWindow?
    tWindow is a type. Here is the typical usage.
    Dim win As tWindow
    With Win
      .SetText("Thin Window")
      .SetPosition(400, 50)
      '.SetSize(650, 300)
      .OnMouseDown = "WindowMouseDown"  '// Name of the event handler function.
    End With
    win.MakeWindow()  '// Here is the actual window creation happens. 
    win.Display()
    
    btw. thinbasic has built in a function,
    dialog set Gradient hDlg, directional_setting, startcolor, endcolor
    Let me check this function with my tWindow.

Similar Threads

  1. DIALOG SET GRADIENT / Wrong equate names
    By Petr Schreiber in forum Fixed or cleared errors in help material
    Replies: 0
    Last Post: 22-08-2009, 14:08
  2. Dialog gradient background
    By ErosOlmi in forum UI (User Interface)
    Replies: 10
    Last Post: 21-01-2008, 16:53

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •