MXS: .NET button text color when disabled


#1

Is there some way to force the dotNet button to change the text color to gray when it’s enabled=false, as is done in 3ds max’s native button?
When I try to change the text of a button that becomes disabled, the text color doesn’t change and still remains black, as if the button is still active.
For the button I used the EnabledChanged event with the following code:

dotnetcontrol dnButton "System.Windows.Forms.Button"
---
on dnButton EnabledChanged e do (
if dnButton.enabled then (
setProperty dnButton "ForeColor" dotNetBlackColor
)
else(
setProperty dnButton "ForeColor" dotNetGrayColor
)
)

But that doesn’t work, just like the normal color assignment dnButton.ForeColor=dotNetGrayColor

Thanks for any help.


#2

Which max version? Both 2014 & 2020 work exactly the same for me
49IAnahw1Y

code
try (destroydialog X ) catch ()
rollout X "2014 max" (

	button tgl "toggle"
	dotnetcontrol dnButton "System.Windows.Forms.Button" text:"OPEN" height:30
	
	local state = true
	fn Toggle = 
	(
		state = not state
		dnButton.enabled = state
    --  dnButton.enabled = not dnButton.enabled   <== this one doesn't work for some reason 
	)
		
	on tgl pressed do Toggle()
	
	on x open do
	(
		dnButton.ForeColor = dnButton.ForeColor.red
	)
	

)
createDialog X pos:[100,100]

#3

No, you did not understand. Switching button.enabled to true or false works as it should. But changing color does not work if it is different from the one that was assigned to this button by default, e.g. black.
Try giving the disabled button a different text color, such as blue, and you’ll see that the text color becomes black instead of blue.
Try this code and you will understand what I mean:

try (destroydialog X ) catch ()
rollout X "2014 max" (

	button tgl "toggle"
	dotnetcontrol dnButton "System.Windows.Forms.Button" text:"OPEN" height:30
	
	local state = true
	fn Toggle = 
	(
		state = not state
		dnButton.enabled = state
        -- Сhange the text color if the enable state of the button is false
		if NOT dnButton.enabled do dnButton.ForeColor = dnButton.ForeColor.Blue
	)
		
	on tgl pressed do Toggle()
	
	on x open do
	(
		dnButton.ForeColor = dnButton.ForeColor.red
	)
)
createDialog X pos:[100,100]

As a result, I want the color of the text on the disabled button to be gray instead of black.


#4

I don’t remember if it is possible to override onPaint event in maxscript
Here’s what I’m about


#5

see this thread

https://social.msdn.microsoft.com/Forums/windows/en-US/c47d5315-0181-4303-9d19-02c310446051/change-fore-color-of-a-disabled-button?forum=winforms

you simply can’t

and is not that sergio did not understand, he is trying to see if you can implement a solution.

btw it’s highly unlike you can do it easily as you were hoping.


#6

Ok, I’ll read this.
I just thought there was some easier and direct way to do it.
Thank you.


#7

Thank you.
I read it, but I don’t quite understand how to implement it in maxscript.


#8

had to google it


#9

you can fake it this way

try (destroydialog X ) catch ()
rollout X "2014 max" (

	button tgl "toggle"
	dotnetcontrol dnButton "System.Windows.Forms.Button" text:"OPEN" height:30
	
	local state = true
	
	fn yourWorkingFn = (
		(if state == true then messagebox "this works only if the state is enabled" else print "disabled" )
		
		
		)
	
	
	fn Toggle = 
	(
		if state == true then (state = false 
								dnButton.ForeColor = dnButton.ForeColor.blue)
						else 
		
							(state = true
							dnButton.ForeColor = dnButton.ForeColor.red
								)

		print state
	)
	
	on tgl pressed do Toggle()
	
	on dnButton Click e do yourWorkingFn()
	
	on x open do
	(
		dnButton.ForeColor = dnButton.ForeColor.red
	)
	

)
createDialog X

or you can disable it at mousehover so it will become gray only when you try to click it and stays blue for the rest of the time


#10

Thank you Serejah and conradbenzin!

I added a Paint event to the button and now it works:

on dnButton Paint sender arg do (
	local buttonText="OPEN"
	if state then (
		textColor=(dotnetclass "System.Drawing.Color").Blue
	)
	else (
		textColor=(dotnetclass "System.Drawing.SystemColors").ControlDark
	)
	local dnTR = (dotnetclass "TextRenderer")
	local dnTF=(dotnetclass "System.Windows.Forms.TextFormatFlags")
	local dnFlags = dotnet.combineEnums dnTF.HorizontalCenter dnTF.VerticalCenter
	sender.Text=""
	dnTR.DrawText arg.Graphics buttonText sender.font arg.ClipRectangle textColor dnFlags
)

The only oddity is that when I specify butText=sender.Text, an empty string is repaint, so I had to specify butText="OPEN" directly in the variable.


#11

Paint is called quite often so it is a good idea to check if it leaks memory and move all reused classes and functions outside the onPaint handler


#12

Thanks Serejan, but it didn’t work. I moved all the reused classes and functions into a separate function that is called on the Paint event, but the text is still empty if I try to get it directly from the button before redrawing. Works only when I specify the text directly in the dnTR.DrawText function.
How can check for a memory leaks?


#13

If it leaks you’ll see it from the task manager. Here’s the thread that shows the issue

code
try (destroydialog X ) catch ()
rollout X "" height:70
(

	button toggle "toggle"
	dotNetControl b "system.windows.forms.button" text:"OPEN"

	local state = true
	
	on toggle pressed do
	(
		state = not state
		
		b.enabled = state		
	)		
	
	on x open do b.height = 30
	
	local dnTR    = (dotnetclass "TextRenderer")
	local dnTF    = (dotnetclass "System.Windows.Forms.TextFormatFlags")
	local dnFlags = dotnet.combineEnums dnTF.HorizontalCenter dnTF.VerticalCenter
	local buttonText = "OPEN"
	
	on b Paint sender arg do
	(			
		local textColor = if state then (dotnetclass "System.Drawing.Color").Blue else (dotnetclass "System.Drawing.SystemColors").ControlDark
		sender.Text = ""
		dnTR.DrawText arg.Graphics buttonText sender.font arg.ClipRectangle textColor dnFlags
	)
)

createDialog X pos:[100,100]

#14

Thank you very much Serejan!