Notifications
Clear all

[Closed] UIAccessor- skinops.loadEnvelope

Can’t quite figure out how to get this to work. I already have a script that pushes the ‘Match by Name’ and ‘OK’ buttons on the skinops.loadEnvelope dialog:


fn confirmLoadEnvelopes removeIncomingPrefix:false removeCurrentPrefix:false =
(
	--local BM_SETCHECK = 241
	local hwnd = dialogMonitorOps.getWindowHandle()
	if (uiAccessor.getWindowText hwnd == "Load Envelopes") then
	(
		--controls = windows.getChildrenHWND hwnd
		--print controls
		--UIAccessor.SendMessage 4657876P BM_SETCHECK 1 1 --(if removeIncomingPrefix then 1 else 0) 0 -- 0 0 == unchecked
		--UIAccessor.SendMessage 3740438P BM_SETCHECK 1 1 --(if removeIncomingPrefix then 1 else 0) 0 -- 0 0 == unchecked
		--if removeIncomingPrefix then UIAccessor.PressButton 1248992
		--if removeCurrentPrefix then UIAccessor.PressButton 1380070
		UIAccessor.PressButtonByName hwnd "Match by Name"
		forceCompleteRedraw()
		UIAccessor.PressButtonByName hwnd "OK"
	)
	true
),

fn confTT = (confirmLoadEnvelopes removeIncomingPrefix:true removeCurrentPrefix:true),
fn confTF = (confirmLoadEnvelopes removeIncomingPrefix:true removeCurrentPrefix:false),
fn confFT = (confirmLoadEnvelopes removeIncomingPrefix:false removeCurrentPrefix:true),
fn confFF = (confirmLoadEnvelopes removeIncomingPrefix:false removeCurrentPrefix:false),

fn loadEnvelope theSkin envFile removeIncomingPrefix:false removeCurrentPrefix:false =
(
	--determine which confirmLoadEnvelopes to use
	local confirmFn = case of
	(
		(removeIncomingPrefix and removeCurrentPrefix):confTT
		(removeIncomingPrefix and not removeCurrentPrefix):confTF
		(not removeIncomingPrefix and removeCurrentPrefix):confFT
		(not removeIncomingPrefix and not removeCurrentPrefix):confFF
	)
	
	DialogMonitorOps.Enabled = true	--DialogMonitorOps.Enabled = false
	DialogMonitorOps.RegisterNotification confirmFn id:#pressSkinOK
	skinOps.LoadEnvelope theSkin envFile
	DialogMonitorOps.unRegisterNotification id:#pressSkinOK
	DialogMonitorOps.Enabled = false
	ok
),

I want to add in the ability to check the “Remove Incoming Prefix” and “Remove Current Prefix” checkboxes. I tried to do this based on some of Zeboxx’s code, but cannot get it to work, can anyone give me some help (and an explanation)? Could use it ASAP. Thanks.

3 Replies

the big bit you’re missing is the checkbutton (un)checking function – good idea to store it somewhere


 -- toggle an UI checkbox's checked state via UI messages/notifications
 -- usage:
 --   hwnd -- HWND of the control
 --   state -- checked state.  1 = check, 0 = uncheck
 -- result:
 --   value: OK
 --   effect: should check/uncheck the checkbox and have its change effected
 fn setUICheckboxState hwnd state = (
 	local BN_CLICKED = 0 -- clicky message ID
 	local BM_SETCHECK = 241 -- checkbutton toggle message ID
 	local WM_COMMAND = 273 -- windows command message
 
 	local parent = UIAccessor.getParentWindow hwnd
 	local id = UIAccessor.getWindowResourceID hwnd
 	windows.sendMessage hwnd BM_SETCHECK state 0
 	windows.sendMessage parent WM_COMMAND ((bit.shift BN_CLICKED 16) + id) hwnd
 	OK
 )
 

After that, it’s a fairly simple matter to get the checkboxes…

After you have identified the correct dialog (hwnd == “title you need”), add this code for testing…


 local children = windows.getchildrenhwnd hwnd
 print children
 

In your case, that should give some results such as these:


 #(10948078P, 13438340P, 13438340P, "Button", "OK")
 #(9637278P, 13438340P, 13438340P, "Button", "Cancel")
 ...
 #(9506296P, 13438340P, 13438340P, "Button", "Remove Incoming Prefix")
 #(8916402P, 13438340P, 13438340P, "Button", "Remove Current Prefix")
 #(9833856P, 13438340P, 13438340P, "Button", "Load Vertex Data")
 

These are the children (UI controls, in this case) details of the dialog in an array.
The first element in each child is the hwnd of the control, the 2nd and 3rd you may ignore here, the 4th is the type – can also ignore it – and the 5th is the title.

So now you can replace the previous testing code with something like:


 local children = windows.getchildrenhwnd hwnd
 for child in children do (
 	if (child[5] == "Remove Incoming Prefix") then (
 		setUICheckboxState child[1] 1
 	)
 	else if (child[5] == "Remove Current Prefix") then (
 		setUICheckboxState child[1] 1
 	)
 )
 

And you’re all set.
Note that I could’ve used an OR above, but logic-wise it’s better to keep them separate as they are, essentially, who separate operations.
Edit: similarly, the checkbox (un)checking function could use true/false – would probably be nicer, but I prefer keeping it 1/0 myself so that it’s absolutely clear I’m mucking with windows UI messages code.

After that, just press the OK button and you should be all done.

If you want an explanation of what setUICheckboxState does, have a search in these forums… it’s pretty technical

fn setUICheckboxState hwnd state =
(
/****************************************************************************
	<DOC> toggle an UI checkbox's checked state via UI messages/notifications
	Arguments:
		<int> hwnd:			HWND of the control
		<int> state: 		checked state.  1 = check, 0 = uncheck
		<skin modifier> curObj:		The selected skin modifier (must be in modify panel)
	Return:
		<ok>  should check/uncheck the checkbox and have its change effected
*************************************************************************/
	local BN_CLICKED = 0 -- clicky message ID
	local BM_SETCHECK = 241 -- checkbutton toggle message ID
	local WM_COMMAND = 273 -- windows command message

	local parent = UIAccessor.getParentWindow hwnd
	local id = UIAccessor.getWindowResourceID hwnd
	windows.sendMessage hwnd BM_SETCHECK state 0
	windows.sendMessage parent WM_COMMAND ((bit.shift BN_CLICKED 16) + id) hwnd
	OK
),


fn confirmLoadEnvelopes removeIncomingPrefix:0 removeCurrentPrefix:0 =
(
/*************************************************************************
	<DOC> Manipulate the Load Envelopes dialog via the UI Accessor.
	Arguments:
		<int> removeIncomingPrefix:		Corresponds to the "Remove Incoming Prefix" checkbox.  0 is false, 1 is true
		<int> removeCurrentPrefix:		Corresponds to the "Remove Current Prefix" checkbox.  0 is false, 1 is true
	Return:
		<bool> true (needed for DialogMonitorOps)
*************************************************************************/
	--local BM_SETCHECK = 241
	local hwnd = dialogMonitorOps.getWindowHandle()
	if (uiAccessor.getWindowText hwnd == "Load Envelopes") then
	(
		local children = windows.getChildrenHWND hwnd
		for child in children do
		(
			if (child[5] == "Remove Incoming Prefix") then
			(
				setUICheckboxState child[1] 1
			)
			else if (child[5] == "Remove Current Prefix") then
			(
				setUICheckboxState child[1] 1
			)
		)
		
		UIAccessor.PressButtonByName hwnd "Match by Name"
		forceCompleteRedraw()
		UIAccessor.PressButtonByName hwnd "OK"
		--UIAccessor.PressDefaultButton()
	)
	true
),

fn confTT = (confirmLoadEnvelopes removeIncomingPrefix:1 removeCurrentPrefix:1),
fn confTF = (confirmLoadEnvelopes removeIncomingPrefix:1 removeCurrentPrefix:0),
fn confFT = (confirmLoadEnvelopes removeIncomingPrefix:0 removeCurrentPrefix:1),
fn confFF = (confirmLoadEnvelopes removeIncomingPrefix:0 removeCurrentPrefix:0),

fn loadEnvelope theSkin envFile removeIncomingPrefix:false removeCurrentPrefix:false =
(
/*************************************************************************
	<DOC> Load an .env file.  There is no function for silently loading an .env, so this
	is a UI Accessor workaround.
	Arguments:
		<skin modifier> theSkin:		The selected skin modifier (must be in modify panel)
		<string>	envFile:					Filename of the .env file.
	Return:
		<ok>
****************************************************************************/
	--determine which confirmLoadEnvelopes to use
	local confirmFn = case of
	(
		(removeIncomingPrefix and removeCurrentPrefix):confTT
		(removeIncomingPrefix and not removeCurrentPrefix):confTF
		(not removeIncomingPrefix and removeCurrentPrefix):confFT
		(not removeIncomingPrefix and not removeCurrentPrefix):confFF
	)
	
	DialogMonitorOps.Enabled = true	--DialogMonitorOps.Enabled = false
	DialogMonitorOps.RegisterNotification confirmFn id:#pressSkinOK
	skinOps.LoadEnvelope theSkin envFile
	DialogMonitorOps.unRegisterNotification id:#pressSkinOK
	DialogMonitorOps.Enabled = false
	ok
),

Awesome! That’s the code for anyone who needs it. So you’d put that in a struct, and call:

<struct>.loadEnvelope <skin modifier> <envelope filename> removeIncomingPrefix:true removeCurrentPrefix:true

For anyone that wants it, there you go. Nothing like refreshing every 5 minutes saying ‘where is zeboxx, where is zeboxx’ and then getting a great answer and your code works.

Great~!:buttrock:
Meet the same problem too.
It is so ugly that in runtime you have to clicke any button.

After see the solution.
I think i can’t find the answer by myself in my life…