<Edit_Poly>.GetOperation() counterpart in Editable Poly?


Is there any way to find if an operation that brings up a dialog (basically any of those you can bring up with <EditablePoly>.PopupDialog <enum>popupOperation) is currently active in EditablePoly? In Edit Poly modifier, there’s the GetOperation method which is just perfect but I couldn’t find anything similar for EditablePoly. Thanks in advance.


Editable_Poly doesn’t store current operation in public place (Edit_Poly stores it in a parameter block).
Editable_Poly stores it in a static variable with PopupDlgProc object.
There is no way to get access to it.

so… using UIAccessor you can check all popup dialogs and find which window belongs to “epoly.dlo”


for hwnd in uiaccessor.getpopupdialogs() do
	if filenamefrompath (uiaccessor.getwindowdllfilename hwnd) == "epoly.dlo" do
		text = uiaccessor.getwindowtext hwnd
		format "hwnd:% text:%
" hwnd text


But … there are stupid Caddy Controls. I have no idea what to do with them yet.


That’s ingenious and perfect for the task, never would have gotten the idea to use getwindowdllfilename for that! Thanks a lot.

Edit: ah, gotta hate the caddies :frowning: not completely solved then…


Even just getting the caddies control takes too much time…

caddyHwnd = 0
ownerHwnd = UIAccessor.GetFirstChildWindow (windows.getMaxHWND())
for w in windows.getChildrenHwnd 0P while caddyHwnd == 0 where w[3] == ownerHwnd and w[4] == "Qt5QWindowToolSaveBits" do caddyHwnd = w[1]

I could probably make it much faster if I searched for the owned window in say C# (I suppose there’s no maxscript trick to get owned windows, right?), but that’s getting pretty complicated for a task like this…


you still can use GetPopupDialogs and check window type. For Caddies it’s QWidget


the problem is that for max 2017+ it might be many other QWidgets, and how to find the epoly’s?


Yeah, plus there are also caddies for soft selection and it would be hard to differentiate them… Suddenly, checking if one of matching buttons in the editable poly rollouts is pressed doesn’t seem as crazy as it seemed when I started thinking about the ways to solve that…


i don’t get it… the buttons are not pressed after a dialog is opened. Do you want to monitor the pressing of buttons? How is about operations called with script for example?


what do you want to know? if any epoly operation is active or what operation is active?


Hmmm, you are right, script- or shortcut-triggered operations would be impossible to catch that way. I would like to know what operation is active.


Btw. this doesn’t apply in max 2018, the type is now Qt5QWindowToolSaveBits, GetPopupDialogs doesn’t collect it and different caddies elements are owned by a different Qt5QWindowIcon child of the main Qt5QWindowIcon.


The joys of max… this seems to work and will return the name of the current caddie control in max 2018 (the first line of it, since different parameter names are appended to it depending on the active input):

dotnet.LoadAssembly "UIAutomationClient.dll"

topLevelWindows = windows.getChildrenHwnd (windows.getDesktopHWND())
ownerHWND = (windows.getChildrenHWND (windows.getMaxHWND()))[6][1]
caddyHWND = for w in topLevelWindows where w[3] == ownerHWND and w[4] == "Qt5QWindowToolSaveBits" do exit with w[1]

UIAElem = (dotNetClass "System.Windows.Automation.AutomationElement").FromHandle caddyHWND
subElems = UIAElem.FindAll (dotNetClass "System.Windows.Automation.TreeScope").Children (dotNetClass "System.Windows.Automation.PropertyCondition").TrueCondition
name = (filterString subElems.Item[0].Current.Name "

But of course, since it’s going through all desktop children, it’s not that fast. Translating it to C# or anything else will remove the speed problem, the question that remains is: what’s the proper way to get the owner and what is it exactly anyway? I’m talking about this handle:

ownerHWND = (windows.getChildrenHWND (windows.getMaxHWND()))[6][1]

I don’t feel super confident about the indexed access and would prefer some sure way of getting it that won’t change in the next release or something…


i found finally how to get via SDK an Active Caddy if any active:

#include <igrip.h>
MSTR* GetActiveGripName()
	FPInterface* fpi = ::GetCOREInterface(IGRIPMANAGER_INTERFACE);
	if (fpi)
		IGripManager* igrip = (IGripManager*)fpi;
		if (IBaseGrip* base = igrip->GetActiveGrip())
			MSTR name;
			return new MSTR(name);
	return NULL;

it should be easy to do with MaxPlus as well.
Please show a solution if you will be able to get it.

PS. if Caddies are not used the windows search has to work instead


That’s awesome, exactly what I wanted! Here it is as a c# method:

IGlobal global = Autodesk.Max.GlobalInterface.Instance;

public static string getActiveGripName()
	IFPInterface fpi = global.GetCOREInterface(global.Interface_ID.Create(0x59cb513c, 0x7a0a5232));
	ICustomMarshaler marshaler = Autodesk.Max.Wrappers.CustomMarshalerIGripManager.GetInstance("");
	Autodesk.Max.Wrappers.IGripManager igrip = (Autodesk.Max.Wrappers.IGripManager)marshaler.MarshalNativeToManaged(fpi.NativePointer);

	if (igrip != null)
		IIBaseGrip baseGrip = igrip.ActiveGrip;

		if (baseGrip != null)
			string name = "";
			baseGrip.GetGripName(ref name);
			return name;
	return null;

Btw. I’m glad I’ve also checked UI Automation, might come in handy some time, quite a bit friendlier than pinvoke methods as well :slight_smile:

An old question

Just curious… Why do you need to know the active epoly operation?


To change properties (say bridge/connect/chamfer etc. segments) matching the currently active mode.


as i’ve understood it works for any max version ‘where Caddies are’ + , right?

at least the SDK solution…


Yes, tested in 2016, 2017 and 2018, it works in all of them.