How to call a structure-based control procedure

Hello,

I am wondering if it is possible to execute a procedure that is intended to be called by a button, when this procedure is written using
WMButtonAction
.
I mean, the problem is that the parameter is a structure. Using the old style, it would be many parameters instead, for instance,
ctrlName
,
eventCode
... Here, I think only one parameter is allowed, and when I try to call the
ButtonProc_RedefineCoords_M procedure
like that :

ButtonProc_RedefineCoords_M(Button_Coords_Acetic_M_Pos)


Igor tells me that a local variable name is expected...

To sum up, I'd like to execute this procedure, normally executed when the button is clicked, but without clicking it.

Would you have any idea ?

Thank you in advance


Function Display_BtnRedefineCoords(instance_locale)

	STRUCT class_VFA &instance_locale
	SVAR Polarity = root:Polarity
		
	variable y
	string str_Button_RedefineCoords
	string strStruct4UserData
	
	SetActiveSubWindow $"MAIN_CAPTIVOCS_Panel#CAPTIVOCS_Panel_"+Polarity
		
	str_Button_RedefineCoords = "Button_Coords_" + instance_locale.str_Analyte
	y = instance_locale.numero

	StructPut /S instance_locale, strStruct4UserData //we save the structure instance in a string
	
	Button $str_Button_RedefineCoords+"_M_" + Polarity, pos={600,460+20*y},size=17,18},proc=ButtonProc_RedefineCoords_M,title="M", userdata=strStruct4UserData

End


//-  -  -  -  -  -  -  -  -  - Function to execute when the button is clicked -  -  -  -  -  -  -  -  -  -  -  

Function ButtonProc_RedefineCoords_M(ba) : ButtonControl
	STRUCT WMButtonAction &ba

	STRUCT class_VFA myVFA
		
	switch( ba.eventCode )
		case 2: // mouse up
			StructGet/S myVFA, ba.userdata 	// written out to control
			RedefineCoords(myVFA,1)				// click code here
		break
	endswitch

	return 0
End
Not for sure exactly, but do you mean something like this?



Function DoButtonClick()

     STRUCT WVButtonAction ba
     ba.eventCode = 2
     ba.userData = // set the userData here as needed
     ButtonProc_RedefineCoords_M(ba)
     return 0

end

Function ButtonProc_RedefineCoords_M(ba) : ButtonControl
	STRUCT WMButtonAction &ba
 
	STRUCT class_VFA myVFA
 
	switch( ba.eventCode )
		case 2: // mouse up
			StructGet/S myVFA, ba.userdata 	// written out to control
			RedefineCoords(myVFA,1)				// click code here
		break
	endswitch
 
	return 0
End


--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
It is often tempting to try to call action procedures from code, but that is a sign that you need to re-factor your code. A better design is to extract the code that actually does the work into a function designed to do that work, then call the extracted function from both the action procedure and from your other code.

If the action procedure is part of someone else's package, and you want to use their functionality in your code, you may be better off copying the "engine" code from their action procedure and re-packaging it in your own function. Naturally, you will respect any copyright :)

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Hello jjweimer and Johnweeks,

Thank you for your reply.

@Johnweeks : what you suggest makes sense, but I'm afraid that's tricky. Indeed, a button that calls the procedure of interest contains a
userdata
. Moreover, there are many button instancies, each containing a specific
userdata
(consisting of a structure passed as a string)
If I want to do so, I'd have to write a function that has
STRUCT WMButtonAction &ba
as a parameter.

@jjweimer : I'm going to try it in parallel to the above solution.

Thank you !

Best Regards
Hello,

:-D EDIT : After a good mug of coffee high in caffeine, I've realized that it was not necessary to retrieve the structures from their associated buttons. The confusion came from the fact a structure cannot be global, but using
StructPut
, it is possible to save it in a global string (that's actually what I did to store it in the button's userdata).
Thus, those global strings are used as parameters to call the procedure of interest.

Hope it will be useful for anyone.

Thanks

(It's still not working.) EDIT: Actually, it's OK..

@jjweimer : I've slightly modified your code, to that :

Function DoClick(Button_Coords_Acetic_M_Pos)
	STRUCT WMButtonAction &Button_Coords_Acetic_M_Pos

	Button_Coords_Acetic_M_Pos.eventCode = 2
	ButtonProc_RedefineCoords_M(Button_Coords_Acetic_M_Pos)
	return 0
end

But... I got this message during compilation :
"ERROR : Local variable expected"

Indeed, in the manual it's written that :
"When a Structure is passed to a user function, it can only be passed by reference, so in the declaration within the function you must use &localStructName to define the function input parameter."

That's why I've added the '&'.
Otherwise, if I wrote this, as you firstly suggested :

Function DoClick_QuantifyAll()//Button_Coords_Acetic_M_Pos)
	
STRUCT WMButtonAction Button_Coords_Acetic_M_Pos

Button_Coords_Acetic_M_Pos.eventCode = 2
//Button_Coords_Acetic_M_Pos.userdata = ... //shouldn't be necessary
	
ButtonProc_RedefineCoords_M(Button_Coords_Acetic_M_Pos)
return 0

end


it would be impossible to know to which button (=parameter of the procedure of interest) we refer.
Moreover, a button already contains the userdata, so it shouldn't be necessary to redefine it.

@johnweeks : I've split the button procedure :

//*************************(Part 1)*******************************

Function RedefineCoords_M(ba)

STRUCT WMButtonAction &ba

STRUCT class_VFA myVFA
		
	switch( ba.eventCode )
		case 2: 
			StructGet/S myVFA, ba.userdata 	// written out to control
			RedefineCoords(myVFA,1)		// click code here				
		break
	endswitch

	return 0
End
		
//*************************(Part 2)*******************************
Function ButtonProc_RedefineCoords_M(ba) : ButtonControl
STRUCT WMButtonAction &ba

	RedefineCoords_M(ba)
End


The problem is that the data that has to be updated is contained in the button's
userdata
.
Indeed, a structure cannot be global. That's why I've stored it in a button made to update it.
So, if I directly execute
 RedefineCoords_M(ba)
(for instance, a button can be named "Button_Coords_Acetic_M_Pos", so I execute
RedefineCoords_M(Button_Coords_Acetic_M_Pos)
)

Then I get this error : "Local variable expected"

To sum up

Is it correct to reference the button (defined as a structure) using its name ?
If it is possible to do so, how should I proceed ?

I hope my explanations are not too confusing...


Thank you



Best Regards
Yes, buttons have names, and you can get the buttons userdata using the function GetUserData(). So you don't have to have the STRUCT WMButtonAction in order to get the button's user data. I would recommend, in fact, not using the unnamed userdata. I would do something like


	Button $str_Button_RedefineCoords+"_M_" + Polarity, pos={600,460+20*y},size=17,18},proc=ButtonProc_RedefineCoords_M,title="M", userdata(Struct4)=strStruct4UserData

Then you can get the userdata like this:


	String structString = GetUserData("MAIN_CAPTIVOCS_Panel#CAPTIVOCS_Panel_"+Polarity, str_Button_RedefineCoords+"_M_" + Polarity, "Struct4")

Naturally, these lines have references to your local string variables; you need a way to retrieve those later if you are to do anything with all this stuff.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com