How to change the back color of a control at runtime ?

New to FreeBASIC? Post your questions here.
kcvinu
Posts: 212
Joined: Oct 07, 2015 16:44
Location: Keralam, India

Re: How to change the back color of a control at runtime ?

Postby kcvinu » Mar 15, 2021 9:56

Here is the three types of button i have created.
1 - flat color button
2 - gradient button
3 - normal button.
Image here - https://drive.google.com/file/d/1sJmWZHTD8XCeL0vTnlyc1CJV4dLI-g_r/view?usp=sharing
jj2007
Posts: 2133
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to change the back color of a control at runtime ?

Postby jj2007 » Mar 15, 2021 11:59

I know, it works fine. Your buttons look nice.

Even SetBkMode(hDC, TRANSPARENT) works, so a button with a coloured background is possible. What doesn't work for me are the SetBkColor(hDC, Rgb(...)) and SetTextColor(hDC, Rgb(...)) calls. Same for SetDCBrushColor(hDC, Rgb(0, 255, 0)). Bad luck...
kcvinu
Posts: 212
Joined: Oct 07, 2015 16:44
Location: Keralam, India

Re: How to change the back color of a control at runtime ?

Postby kcvinu » Mar 15, 2021 15:02

@jj2007,

Code: Select all

 SetBkMode(lp.hdc, TRANSPARENT)
    SetTextColor(lp.hdc, RGB(102, 255, 51) )

This is not working in my case. I want to change the button forecolor. But no way. What to do ? Any idea ?
Josep Roca
Posts: 529
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: How to change the back color of a control at runtime ?

Postby Josep Roca » Mar 15, 2021 18:00

Te button must be owner draw. Then you can process the WM_CTLCOLORBTN message.

The WM_CTLCOLORBTN message is sent to the parent window of a button before drawing the button. The parent window can change the button's text and background colors. However, only owner-drawn buttons respond to the parent window processing this message.

See: https://docs.microsoft.com/en-us/window ... tlcolorbtn

BTW you insist in using RGB when you must use BGR. I already explained it in an earlier post in this thread.

I ended witing my own button control.
Code: https://github.com/JoseRoca/WinFBX/blob ... Button.inc
Documentation: https://github.com/JoseRoca/WinFBX/blob ... 20Class.md

Paul Squire's WinFBE IDE uses this control in its visual designer.
PaulSquires
Posts: 899
Joined: Jul 14, 2005 23:41

Re: How to change the back color of a control at runtime ?

Postby PaulSquires » Mar 15, 2021 19:59

Josep Roca wrote:Te button must be owner draw. Then you can process the WM_CTLCOLORBTN message.
Paul Squire's WinFBE IDE uses this control in its visual designer.

Yes, and I did so because of my experience with my other visual designers and users always wanting to be able to change colors of the default standard Windows button. Using Jose's custom button control made it much easier to satisfy those user needs at the slight price of increasing the program size because the button source code gets compiled into the final program's exe whereas using the standard Window's control it is already baked into the operating system.
kcvinu
Posts: 212
Joined: Oct 07, 2015 16:44
Location: Keralam, India

Re: How to change the back color of a control at runtime ?

Postby kcvinu » Mar 17, 2021 10:27

@Josep Roca
I've found the answer myself. We can change the Back color and fore color with NM_CUSTOMDRAW. To change the back color, we can use the same approach which I said above comment.
To change the fore color, Just use three functions.
SetBkMode
SetTextColor
DrawText

And then return CDRF_NOTIFYPOSTPAINT.
If you returned any other values, the color won't change.
So there is no need to use BS_OWNERDRAW style.
Sorry for using RGB again. Since, I copied my Nim code to this forum. In Nim, RGB is just RGB.

Your Button class is amazing. I am using sub classing but you create a new window class for creating button. Is there any special advantages in using special class ?
jj2007
Posts: 2133
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to change the back color of a control at runtime ?

Postby jj2007 » Mar 17, 2021 10:56

kcvinu wrote:And then return CDRF_NOTIFYPOSTPAINT.
Sounds good! At which dwDrawStage do you return it? Can you post the code?
Josep Roca
Posts: 529
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: How to change the back color of a control at runtime ?

Postby Josep Roca » Mar 17, 2021 14:27

I have used CDRF_* values previously, mainly with ListViews, but wasn't aware that buttons did support CDRF_NOTIFYPOSTPAINT. Apparently it was introduced in Windows Vista and you must use a manifest.

> Your Button class is amazing. I am using sub classing but you create a new window class for creating button. Is there any special advantages in using special class ?

It gives you control about everything. It was an exercise to build controls from scratch that I did in XP times. Subclassing can be used to modify the behaviour of existing controls (I did subclass the Edit control to create a masked edit control), but not to create a new control. As it was an exercise, I did choose the button control because it was the easier one.
jj2007
Posts: 2133
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to change the back color of a control at runtime ?

Postby jj2007 » Mar 17, 2021 23:27

I hesitate to go for a full ownerdraw button because some styles, like the BS_COMMANDLINK button in the middle, would need complex treatment. The left button, for example, uses DrawText, and it was tricky to center it properly, despite the use of DT_CALCRECT.

It would also imply a check for the styles applied by the coder. For the time being, I can change the background colour. @kcvinu: How did you change the foreground colour? By drawing the text yourself?
Image
kcvinu
Posts: 212
Joined: Oct 07, 2015 16:44
Location: Keralam, India

Re: How to change the back color of a control at runtime ?

Postby kcvinu » Mar 18, 2021 2:05

@ jj2007
The button with an icon is superb. However, this is my Nim code to change the button text color.

Code: Select all

proc setTxtColor(lp : LPNMCUSTOMDRAW, txt : string) : UINT =
   
    let txtFlag : UINT = DT_SINGLELINE or DT_VCENTER or DT_CENTER or DT_HIDEPREFIX
    SetBkMode(lp.hdc, TRANSPARENT)
    SetTextColor(lp.hdc, tColor.toColorRef())
    var tLen  = txt.len.toi32
    DrawText(lp.hdc, txt, tLen, lp.rc, txtFlag)
    result = CDRF_NOTIFYPOSTPAINT
jj2007
Posts: 2133
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to change the back color of a control at runtime ?

Postby jj2007 » Mar 18, 2021 9:24

Thanks, kcvinu. So it is what I suspected: a complete ownerdraw. I had tested that version already, and discarded it because, as written earlier, it becomes complex with certain buttons. I will have a look at Joseph's version...

P.S.: If I add a BS_COMMANDLINK style to the pXpButton3 button in Josep Roca's example, it doesn't change at all.

Compliments to Josep, you put an incredible amount of work into Afx! CXpButton.inc alone is 1600+ lines, and there are so many inc files...
Josep Roca
Posts: 529
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: How to change the back color of a control at runtime ?

Postby Josep Roca » Mar 18, 2021 18:37

Thanks for the compliments.

> P.S.: If I add a BS_COMMANDLINK style to the pXpButton3 button in Josep Roca's example, it doesn't change at all.

This control was not intended as a replacement of the Windows button control. I first wrote it with PowerBasic many years ago, in XP times (hence the "Xp" in its name), as a way of using icons with styled buttons (currently, Windows supports it using an image list and a manifest). Then I translated it to FreeBasic as a training exercise to learn how to make custom controls using a class... and some time ago, Paul suggested to make some chnages to allow for coloured buttons, that seem to be in high demand lately... :)
dodicat
Posts: 6930
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How to change the back color of a control at runtime ?

Postby dodicat » Mar 18, 2021 22:48

For fun, an alternative;

Code: Select all


#include "windows.bi"
#include "file.bi"
Declare Sub tree(x1 As Single,y1 As Single,size As Single,angle As Single,depth As Single,colb As Uinteger<32>=0,colL As Uinteger<32>=0,im As Any Ptr=0)
Declare Sub finish()
Dim Shared As Single spread=25,scale=.76     
Dim Shared As Any Ptr i(1 To 4)
Dim Shared szBitmap(Lbound(i) To Ubound(i)) As String
Dim Shared As Point p(1 To 4)
Dim As MSG msg
Dim Shared As HWND hWnd, edit(Lbound(i) To Ubound(i))
Dim Shared hbitmap(1 To 4) As handle
hWnd = CreateWindowEx( 0, "#32770", "Bitmap Button Test",WS_OVERLAPPEDWINDOW Or WS_VISIBLE , 100, 0, 620, 320, 0, 0, 0, 0 )

Sub makebitmap(x As Single,z As Long=0)
    Dim As Long w,h
    w=150
    h=150
    Screenres w,h,32,,-1 'create a temp [hidden] screen
    Width w\8,h\16
    For n As Long=Lbound(i) To Ubound(i)
        If z=0 Then
            i(n)=Imagecreate(w,h,Rgb(55+x,255,255-50*n))
            tree(70,100,70,90+(Rnd*25-Rnd*25),12,Rgb(200,100,0),Rgb(0,100,0),i(n))
            Draw String i(n),(10,10),"Hello",0
            Bsave ("small"+Str(n)+".bmp",i(n))
            szbitmap(n)="small"+Str(n)+".bmp"
            Imagedestroy i(n):i(n)=0
        Else
            i(z)=Imagecreate(w,h,Rgb(Rnd*x,Rnd*x,Rnd*x))
            tree(70,100,70,90+(Rnd*25-Rnd*25),12,Rgb(200,100,0),Rgb(0,100,0),i(z))
            Draw String i(z),(10,10),"Hello",0
            Bsave ("small"+Str(z)+".bmp",i(z))
            szbitmap(z)="small"+Str(z)+".bmp"
            Imagedestroy i(z):i(z)=0
        End If
    Next n
    Screen 0  'return to console
    Dim As Integer k,y=0,start
    For n As Long=Lbound(i) To Ubound(i)
        k+=1
        If (k) Mod 5=0 Then y+=h:k=1
        p(n)=Type((k-1)*150+w/2,y+h/2)
        If edit(n)=0 Then edit(n) = CreateWindowEx( 0, "BUTTON", "" , WS_VISIBLE Or WS_CHILD Or ANSI_CHARSET Or BS_PUSHBUTTON Or BS_BITMAP, (k-1)*150 , y+50 , w , h , hWnd, 0, 0, 0 )
    Next n
   
    For n As Long=Lbound(i) To Ubound(i)
        deleteobject(hbitmap(n))
        hBitmap(n) = LoadImage(0, szBitmap(n), IMAGE_BITMAP, w, h,  LR_LOADFROMFILE )
        If hbitmap(n) Then SendMessage(edit(n), BM_SETIMAGE, IMAGE_BITMAP, Cast(LPARAM, hbitmap(n)))
    Next n
End Sub

makebitmap(Rnd*50)

#macro switch(i,r)
Case edit(i)
    Select Case msg.message 
    Case WM_LBUTTONDOWN
        makebitmap(r,i)
    End Select
    #endmacro
   
    While GetMessage( @msg, 0, 0, 0 )
       
        TranslateMessage( @msg )
        DispatchMessage( @msg )
       
        Select Case msg.hwnd
        Case hWnd
            Select Case msg.message
            Case 273 : PostQuitMessage(0)
            End Select
            switch(1,255)
            switch(2,255)
            switch(3,255)
            switch(4,255)
        End Select
       
       
    Wend
   
    Sub Tree(x1 As Single,y1 As Single,size As Single,angle As Single,depth As Single,colb As Uinteger<32>=0,colL As Uinteger<32>=0,im As Any Ptr=0)
        #define incircle(cx,cy,radius,x,y) (cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
        Var x2=x1-.25*size*Cos(angle*.01745329)
        Var y2=y1-.25*size*Sin(angle*.01745329)
        Static As Integer<32> count,fx,fy,sz,z
        If count=0 Then  fx=x1:fy=y1:sz=size:z=2^(depth+1)-1
        Line im,(x1,y1)-(x2,y2),colb
        If count=0 Then  fx=x2:fy=y2:sz=size
        count=count+1
        If count>z Then count=0
        If incircle(fx,fy,(.45*sz),x2,y2)=0 Then Circle im,(x2,y2),.01*sz,colL
        If depth>0 Then
            Tree(x2, y2, size * Scale, angle - Spread, depth - 1,colB,colL,im)
            Tree(x2, y2, size * Scale, angle + Spread, depth - 1,colB,colL,im)
        End If
    End Sub
   
   
    Sub finish Destructor
        For n As Long=Lbound(i) To Ubound(i)
            deleteobject(hbitmap(n))
            If i(n) Then Imagedestroy(i(n)):i(n)=0
            Kill "small"+Str(n)+".bmp"
            Print "destroying ";n
            print iif(fileexists("small"+Str(n)+".bmp"),"Delete bitmaps manually","OK")
            if fileexists("small"+Str(n)+".bmp") then sleep 1000
        Next
     
        End Sub
 
jj2007
Posts: 2133
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to change the back color of a control at runtime ?

Postby jj2007 » Mar 18, 2021 23:42

Lovely, dodicat! I couldn't resist ;-)
Image

Return to “Beginners”

Who is online

Users browsing this forum: No registered users and 4 guests