Press Radio button with Maxscript in Command Panel

I want to press a radio button in the command panel. Someone asked how to press a checkbox in a 3dsmax menu (I have included the link). I am trying to press a radio button in the Command Panel: Proboolean --> (sub-object Operations) --> (Remove or Copy or Inst). These settings are not exposed in maxscript unfortunately. I tried your solution for the checkbox but it does not seem to work for radio button. Can someone help me?

Link to ScriptSpot Thread: Pressing a Checkbox with maxscript

miauu solution for Checkbox:

local RollOutHandle = (windows.getChildHWND 0 "access test" )[1]
local checkHandle =(windows.getChildHWND RollOutHandle "Check")[1]
local VK_RETURN = 0x000D
local WM_SETFOCUS = 0x007
local WM_CHAR = 0x0102
UIAccessor.sendMessage checkHandle WM_SETFOCUS 0 0
windows.sendMessage checkHandle WM_CHAR VK_RETURN 0
 

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
OccultArt's picture

Can someone help me?

I don't know how to get this working in 3dsmax 2017. Could someone please help. I build a lot of code that is now useless in 3dsmax 2017 because I can't select Remove/Copy/Inst in the Proboolean menu.

miauu's picture

.

This works:

(
	function SetRadiobuttonsState rbName state =
	(
		local properRb = false
		local BN_CLICKED = 0 -- clicky message ID
		local BM_SETCHECK = 241 -- checkbutton toggle message ID
		local WM_COMMAND = 273 -- windows command message
		max modify mode
		df = #max
		for child in (windows.getChildrenHWND dF)   do
		(
			for classN in (windows.getChildrenHWND child[1]) do
			(
				for btn in (windows.getChildrenHWND classN[1]) do
				(
					if btn[5] == "Extract Selected" do properRb = true
					if properRb == true and (btn[5] == rbName) do
					(
						local parent = UIAccessor.getParentWindow btn[1]
						local id = UIAccessor.getWindowResourceID btn[1]
						windows.sendMessage btn[1] BM_SETCHECK (if state then 1 else 0) 0
						windows.sendMessage parent WM_COMMAND ((bit.shift BN_CLICKED 16) + id) btn[1]
					)
				)
			)
		)
	)
 
-- the name of the radiobuttons: -- "Remove", "Copy", "Inst"
rbNamesArr = #("Remove", "Copy", "Inst")
-- first all radiobuttons have to be turned off
for rb in rbNamesArr do SetRadiobuttonsState rb false
-- turn on desired radiobutton
SetRadiobuttonsState "Copy" true
)

But it have one issue - the Remove Display Filter dialog will appear several times. Try to solve it.

OccultArt's picture

Thanks

Thanks! You are amazing :-)

When I tested it quickly I did not get a "Remove Display Filter dialog" popping up. But I still have to test more.

miauu's picture

.

Every time I have 20-30 dialogs to close, but the radiobuttons are changed.

OccultArt's picture

It does not work for 3dsmax 2018

It does not work for 3dsmax 2018 (since they introduced a new interface):
"Remove/Copy/Inst Radiobuttons in a Proboolean object in the modifier pannel. These settings are not exposed in maxscript.

The problem starts with this line (there no longer is a "ModifyTask"):

This was the old working code (working up to 3DSMax 2017)

fn priv_proboolean_Extract_pressRadioButton rbName state = (
local properRb = false
local BN_CLICKED = 0 	-- clicky message ID
local BM_SETCHECK = 241 -- checkbutton toggle message ID
local WM_COMMAND = 273 -- windows command message
local panelName = if((maxVersion())[1] >= 19000) then "QWidget" else "ModifyTask"	--QWidget instead of "ModifyTask"
max modify mode
for child in (windows.getChildrenHWND #max) where child[4] == "#32770" do(
	for classN in (windows.getChildrenHWND child[1]) where (classN[4] == panelName) do( --QWidget instead of "ModifyTask"
		for btn in (windows.getChildrenHWND classN[1]) do
		(
			if btn[5] == "Extract Selected" do properRb = true
			if properRb == true and (btn[5] == rbName) do
			(
				local parent = UIAccessor.getParentWindow btn[1]
				local id = UIAccessor.getWindowResourceID btn[1]
				windows.sendMessage btn[1] BM_SETCHECK (if state then 1 else 0) 0
				If state then windows.sendMessage parent WM_COMMAND ((bit.shift BN_CLICKED 16) + id) btn[1]
				if((maxVersion())[1] >= 1900) then return OK  ))))),

Called with function:

fn pressRadioButton rbName= (
	rbNamesArr = #("Remove", "Copy", "Inst")
	for rb in rbNamesArr do (																						--	the name of the radiobuttons: -- 	"Remove", "Copy", "Inst"
		proboolean_Extract_pressRadioButton rb false )						--	first all radiobuttons have to be turned off
	proboolean_Extract_pressRadioButton rbName true ),						--	turn on desired radiobutton

Called with:

pressRadioButton "Remove"
pressRadioButton "Copy" 
pressRadioButton "Inst"
OccultArt's picture

Does not work anymore in 3dsmax 2017

Please can anyone help? This used to work in 3dsmax 2016 to select the "Remove/Copy/Inst Radiobuttons in a Proboolean object in the modifier pannel. These settings are not exposed in maxscript.

The problem starts with this line (there no longer is a "ModifyTask"):

for classN in (windows.getChildrenHWND child[1]) where (classN[4] == "ModifyTask") do(

This was the old working code (working up to 3DSMax 2016)

fn proboolean_Extract_pressRadioButton rbName state = (
	local properRb = false
	local BN_CLICKED = 0 			-- clicky message ID
	local BM_SETCHECK = 241 		-- checkbutton toggle message ID
	local WM_COMMAND = 273 			-- windows command message
	max modify mode
	df = #max
	for child in (windows.getChildrenHWND dF) where child[4] == "#32770" do(
		for classN in (windows.getChildrenHWND child[1]) where (classN[4] == "ModifyTask") do(
			for btn in (windows.getChildrenHWND classN[1]) do
			(
				if btn[5] == "Extract Selected" do properRb = true
				if properRb == true and (btn[5] == rbName) do
				(
					local parent = UIAccessor.getParentWindow btn[1]
					local id = UIAccessor.getWindowResourceID btn[1]
					windows.sendMessage btn[1] BM_SETCHECK (if state then 1 else 0) 0
					If state then windows.sendMessage parent WM_COMMAND ((bit.shift BN_CLICKED 16) + id) btn[1] ))))),	--ADDED IF STATE THEN 2015

Called with function:

fn pressRadioButton rbName= (
	rbNamesArr = #("Remove", "Copy", "Inst")
	for rb in rbNamesArr do (																						--	the name of the radiobuttons: -- 	"Remove", "Copy", "Inst"
		proboolean_Extract_pressRadioButton rb false )						--	first all radiobuttons have to be turned off
	proboolean_Extract_pressRadioButton rbName true ),						--	turn on desired radiobutton

Called with:

pressRadioButton "Remove"
pressRadioButton "Copy" 
pressRadioButton "Inst"
OccultArt's picture

Does not work anymore in 3dsmax 2017

Double Post

OccultArt's picture

Does not work anymore in 3dsmax 2017

Double Post

Maarten's picture

This method works for me

I just got this working on my example (changing a radiobutton in the '3ds import' dialog).
But it should work for other UI elements also :)

fn fn_change_3ds_rdo Exporttype =( --Main function
objname = "C:\Users\Maarten\Desktop\TEST\\box001.3ds" -- This is just a file directory to make the importer window work
 
dialogMonitorOPS.UnRegisterNotification id:#test -- remove any old instance
dialogMonitorOps.enabled = true -- enable the monitor
 
fn test = (
	hwnd = DialogMonitorOPS.GetWindowHandle() -- check the dialog that popped up
	 hwnd_title = UIAccessor.GetWindowText hwnd
 
 
		if (hwnd_title == "3DS Import") then ( -- INSERT WINDOW TITLE HERE
		controls= windows.getChildrenHWND hwnd -- get all controls for this dialog
 
		UIAccessor.Sendmessage  controls[3][1] 241 0 0 --Uncheck first radiobutton
		UIAccessor.Sendmessage  controls[4][1] 241 1 0 --Check second radiobutton
 
		)	
 
	true
)
dialogMonitorOPS.RegisterNotification test id:#test -- register the monitor
importfile objname using:importerplugin.classes[Exporttype] useNewFile:false --CREATE WINDOW HERE	
dialogMonitorOPS.UnRegisterNotification id:#test -- remove the monitor
dialogMonitorOps.enabled = false -- disable the monitor
)
 
fn_change_3ds_rdo 1 --Calling the function

If you want to filter out the correct controls from the controls array using wildcards (in this example I am using the wildcard "*Selected*only*" to find the 'selected only' option in the 3ds import dialog) use this piece of code:

	controls= windows.getChildrenHWND hwnd -- get all controls for this dialog
 
 
		for i in 1 to controls.count do (
			if matchpattern controls[i][5] pattern: "*Selected*only*" then(
				UIAccessor.SendMessage controls[i][1] BM_SETCHECK 1 0
				) 
			)

I hope this also works for you guys.
Also check out this page, I got a lot of useful info there:
http://forums.cgsociety.org/showthread.php?f=98&t=639812&page=1&pp=15&hi...

-Maarten

AttachmentSize
3ds_radiobutton_changer.ms 1.12 KB
Maarten's picture

Also this

And if you want to get the correct ID's for the controls in a certain dialog use this piece of code:

	controls= windows.getChildrenHWND hwnd -- get all controls for this dialog
 
		for i in 1 to controls.count do (
			format "i: % \n Control Array: % \n" i controls[i]
				) 

it will return something like this:

i: 1 
 Control Array: #(4459714P, 5704492P, 5704492P, "Edit", "Object01", 0P, 5704492P, 790098P) 
i: 2 
--etc. until it has printed out this info for all controls in the dialog

The 'i' value is the item number of each control in the dialog, the array behind each 'i' value contains info on that control. The first item in this 'control array' is the Window Handle which is used for identification. So when I am sending a message to a certain control I am using this handle example:

print controls[4][1]
--will return the Window Handle (first array item) of the 4th control in the dialog

I do recommend using wildcards in combination with Matchpattern as the control ID's do change between differnt max versions.

-Maarten

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.