Notifications
Clear all

[Closed] Triggering an event handler programatically

Hello. I did a quick search to see if this was covered, but I didn’t find much, so here goes (apologies in advance if I overlooked it)…

I’ve got a piece of UI on a script that I need to manipulate programatically. There is one “master” dropdownlist that, when its selection changes, it updates the selections on 15 other dropdownlists. Think of it as a preset selector for the other 15. It has an “on selected” event handler that I use to change the enabled states and selections of the other 15 ddls. It works all nice, but now I need to manipulate it from a function in the same script.

I’m using UIAccessor and windows messages to get to my “master” dropdown and set a selection on it. It all works pretty well, except that, when setting the selection via windows messages, the event handler is not triggered, and the other ddls don’t get updated (which are the ones I actually care about, since the master one just sets their correct states). Therefore, my options are not set correctly to continue with other things the script needs to do.

So, my question is… is there a notification I’m missing to update the other items on the UI? Or is there a way to “force-call” the event handler so it updates the other dropdowns? Any help is appreciated… cheers!

14 Replies
 lo1

I’m confused. Do you control the DDL you are trying to change programmatically or is it owned by code you don’t control?

I’m not sure what you’d mean by “me controlling it”, but for all intents and purposes, I’d say I do. It’s my code in my tool. Is this what you mean?

1 Reply
 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

Yes. I asked because it sounded by your actions that you’re trying to change controls from other tools.

There is no need to use windows messages and UIAccessor if you have a reference to the control.

The reason you’re having a problem specifically in this page, is because the MAXScript developers named DropDownLists .selected property the same as the selected event, thereby making it impossible to trigger the event programmatically.

The solution for this like you already mentioned is to wrap all the functionality in a separate function and call it.

I’m starting to think that the easiest way outta this one (since I haven’t found a way to trigger the event handler) will be to wrap all my code in the event handler in an external function, and call it both from the event handler, and from my script trying to trigger it. I’ll have to check my code won’t melt when I do this… but looks like that’s my best option right now.

It seems I’ve missed sending a CBN_SELCHANGE notification to the dropDownList. I’m looking into that now…

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

is it your controls and your code? or you want to handle anyone’s else controls?

All mine. I can post a snippet of what I’ve got so far tomorrow… Thanks for the help!

Sergio, what they are asking is if the drop down are settings you are trying to modify are all in a scripted tool or if you are trying to access say a drop down in a plugin you that you don’t control. The reason they ask is there are functions in maxscript and dotnet to call event handlers that should trigger the change. However, if you have a scripted tool with various drop downs in a UI/tool you control, but the end result is the modification of something out of your control then the options may be different.

-Eric

I’m confused… if it’s all yours… (and therefore maxscript I’m assuming)

Rollout RL_test ""
(
    dropdownlist ddl_a "a" items:#("1","2","3","4")
    dropdownlist ddl_b "b" items:#("1","2","3","4")
    button btn_test "test"

    fn UpdateDDL =
    (
        ddl_b.selection = ddl_a.selection
    )

    on ddl_a selected sel do
    (
        UpdateDDL()
    )

    on btn_test pressed do
    (
        ddl_a.selection = 1
        UpdateDDL()
    )
)
CreateDialog RL_Test
2 Replies
(@toonman2)
Joined: 11 months ago

Posts: 0

You just gave me an idea… let me try it out…

(@toonman2)
Joined: 11 months ago

Posts: 0

I’ll be damned. I’ve been banging my head against the wall for nothing! This works! Much more simple than using UIAccessor (I assumed that setting the selection directly in the rollout wouldn’t get me to far, but then, throughout the day I incorporated other things into the scrip that helped, but I was too far into my skewed designs). Terrible sin!
Thanks Dave! Damn… damn damn damn.

FWIW… I’m still curious about how to use CBN_SELCHANGE correctly… :shrug:
Thanks again!

They are all part of a scripted tool I have. Let me try to explain in a little more detail what I’m doing, because maybe I’m trying to solve it in no the most efficient way.

This is a pretty big tool I’m developing for a client. Given all the stuff it does, the UI is divided in tabs devoted to different tasks. However, sometimes, tools on one tab have to do stuff with things in another tab. Because of this, I’ve encapsulated the entire thing in a struct, and I can do some pretty cool connections inside to call stuff in one tab from elsewhere, and I also use some members in the struct as placeholders to hold global data that different tools in different tabs can access. That’s the general design behind it.

My particular problem comes here.
I have this tool in a given tab that takes care of assembling a scene. Boiled down for simplicity, it basically hides and unhides different sets of objects based on filters. The filters are controller by 15 dropDownList widgets, and there is one “master” dropDownList widget that acts as a “preset selector” that affects the other 15 ddls. Selecting something in this preset ddls, changes the items selected by the other 15 filter ddls. After that there’s a button that launches a routine that decides what to display or not based on what the 15 filter ddls have selected, and once the scene is done, the user can export the visible objects. That’s the basic idea (it’s a bit more complex, there are .ini files involved, preset files, etc, but no need to go into that).

The thing is now, I need to develop a batch exporter for this tool. The batch exporter works by reading a text file from disk, which just contains a list of presets to export. This batch exporter is in a different tab from the dialog. My initial idea (which is what I’m trying to do) was to read the first preset to export, find it in the preset list of the “master” ddl on the Assembly tab, and force the UI to select it. I thought that forcing the ddl to select it would trigger the function that updates the 15 filter ddls to the correct values stated by the selected preset. I know that just saying ddl_masterPreset.seleted = <preset value> would do nothing, because it would not trigger the event handler that updates the 15 filter ddls. So I thought that using UIAccessor, I would be able to force the UI actions I need, and this would actually trigger the event handler to update the 15 filter ddls. The rest of the export process should be a breeze after that.
However, I found this is a bit more complicated that I thought. I have been able to get the master preset dll selector to select the correct preset through windows.sendMessage, but when I query the active selection in the ddl through MAXScript, I still get a value of 1 (the first item), which means that the UI changed, but the tool does not know about the change. This means to me I’m lacking a notification I need to send so the tool updates internally, and this is where I’m stuck. I know I need to send another windows message using CBN_SELCHANGE, but I’m not sure how to use it. This is the code I have right now…

-- Get Max HWND
MaxHWND = windows.getMAXHWND()
-- Find the Scene Manager dialog
BRPdialogHWND = undefined
for i in (UIAccessor.getPopupDialogs()) do
( 
	if (UIAccessor.getWindowText i) == "Scene Manager" then BRPdialogHWND = i
)
if BRPdialogHWND != undefined then
(
	-- Find the UI controls I need
	presetsDropDownHWND = undefined
	for i in (UIaccessor.getChildWindows BRPdialogHWND) do
	(
		if (UIAccessor.getWindowText i) == "Presets List" then presetsDropDownHWND = (UIAccessor.getNextWindow i)
	)
	
	if presetsDropDownHWND != undefined then
	(
		-- Select in dropDown
		CB_SETCURSEL = 0x014E
		CB_GETCOUNT = 0x0146
		numItems = windows.sendMessage presetsDropDownHWND CB_GETCOUNT 0 0
		-- Start Batch processing... iterate over all passes in queue
		for i in 1 to self.queuePresetName.count do
		(
			-- Get preset ouput paths
			exportFileName = self.queueFileName[i] ; exportFilePath = self.queuePath[i]
			-- Find preset in preset list (ddl)
			for i in 0 to numItems-1 do
			(
				-- Find the correct preset name in the DDL list
				windows.sendMessage presetsDropDownHWND CB_SETCURSEL i 0
				ddlText = UIAccessor.getWindowText presetsDropDownHWND
				if ddlText == exportFileName then exit
			)
			-- Call filters on Assembly rollout based on preset selection (ddl). This is the function that hides/unhides objects. The function is called with the preset selected in the DDL as an argument
			self.TMUI.sceneAssembly.updateFilters (self.TMUI.sceneAssembly.ddl_presetsList.selection)
			-- Get filtered vehicle and export
			vehicleObjs = self.Pixi_TMUI.sceneAssembly.updateViewportsL mode:#BATCH
			if self.queuePath[i][self.queuePath[i].count] != "\\" then self.queuePath[i] += "\\"
			saveNodes vehicleObjs (self.queuePath+self.queueFileName) quiet:true
		)
	)
)

So, I know I’m just missing a windows.message using CBN_SELCHANGE before I call the function to update the viewports. I don’t know exactly how to call it, and the examples I’ve found through google have not worked in my case. So… any help around how to call CBN_SELCHANGE correctly are appreciated .

My other alternative if I can’t get this to work is to manually go and fetch the preset file, look at the values inside, update the 15 filters to the values used by the file, and update the viewports. It’s a lot more work than what I’m trying to do now, but I’m running out of time and have to get this done.

Thanks for any help!

 lo1

Using windows messages and UIAccessor for doing this is like blowing up a door when you have the key.

See Dave’s code, it is exactly what you need to do and it literally can not have any adverse effects.

1 Reply
(@toonman2)
Joined: 11 months ago

Posts: 0

Now that I see what I’m doing, I have to completely agree. Thanks!! :banghead: