How to change the back color of a control at runtime ?
Re: How to change the back color of a control at runtime ?
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/1sJmWZH ... sp=sharing
1 - flat color button
2 - gradient button
3 - normal button.
Image here - https://drive.google.com/file/d/1sJmWZH ... sp=sharing
Re: How to change the back color of a control at runtime ?
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...
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...
Re: How to change the back color of a control at runtime ?
@jj2007,
This is not working in my case. I want to change the button forecolor. But no way. What to do ? Any idea ?
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 ?
-
- Posts: 603
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: How to change the back color of a control at runtime ?
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.
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.
-
- Posts: 1009
- Joined: Jul 14, 2005 23:41
Re: How to change the back color of a control at runtime ?
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.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.
Re: How to change the back color of a control at runtime ?
@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 ?
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 ?
Re: How to change the back color of a control at runtime ?
Sounds good! At which dwDrawStage do you return it? Can you post the code?kcvinu wrote:And then return CDRF_NOTIFYPOSTPAINT.
-
- Posts: 603
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: How to change the back color of a control at runtime ?
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.
> 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.
Re: How to change the back color of a control at runtime ?
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?

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?

Re: How to change the back color of a control at runtime ?
@ jj2007
The button with an icon is superb. However, this is my Nim code to change the button text color.
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
Re: How to change the back color of a control at runtime ?
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...
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...
-
- Posts: 603
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: How to change the back color of a control at runtime ?
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... :)
> 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... :)
Re: How to change the back color of a control at runtime ?
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
Re: How to change the back color of a control at runtime ?
Lovely, dodicat! I couldn't resist ;-)

