Notifications
Clear all

[Closed] setting focus to viewport with maxscript

reviving this thread in hopes that someone might have a solution these days…
http://forums.cgsociety.org/showthread.php?t=627551

to summarize: i’m trying to restore hotkey/keyboard shortcuts after a script is run. simply setting a viewport “active” doesn’t do this, and none of the built-in maxscript refresh commands that i can find will do it either.

i was thinking of trying to use sendMessage as in the dotNet example from the original thread (code reposted below) to try and send a “click” to the viewport (perhaps a middle click), but i’m not sure how to click a specific coordinate in a specific window.

if anyone can translate the dotnet code below to maxscript, that would probably do it… otherwise i was thinking of trying to use windows.getChildrenHWND to determine the “active viewport” and then send the click there–just not sure how to do that either.

thanks for any help…

 public class MakeAClick{
  
  [DllImport("user32.dll")]
  static extern bool SetCursorPos(int X, int Y);  
  
  
   [DllImport("user32.dll", SetLastError=true)]
  	public static extern void mouse_event(UInt32 dwFlags, UInt32 dx, UInt32 dy, UInt32 cButtons, UInt32 dwExtraInfo)
  
  
  
  [Flags]
    public enum MouseEventFlags
    {
  	LEFTDOWN   = 0x00000002,
  	LEFTUP	 = 0x00000004,
  	MIDDLEDOWN = 0x00000020,
  	MIDDLEUP   = 0x00000040,
  	MOVE	   = 0x00000001,
  	ABSOLUTE   = 0x00008000,
  	RIGHTDOWN  = 0x00000008,
  	RIGHTUP	= 0x00000010
    } 
  
  }
  
  SetCursorPos(10, 50);
  MakeAClick.mouse_event((uint)MouseEventFlags.RIGHT  DOWN,0,0,0,0); 
  MakeAClick.mouse_event((uint)MouseEventFlags.RIGHT  UP,0,0,0,0);
   MakeAClick.mouse_event((uint)MouseEventFlags.LEFTD  OWN,0,0,0,0); 
  MakeAClick.mouse_event((uint)MouseEventFlags.LEFTU  P,0,0,0,0);
11 Replies

it doesn’t need any hack… all that you need is to set focus to any max window. your dialog is ok. and if you want to be absolutely sure set enableaccelerators = on
so the code should look like:

 ...
  on <edittext> entered text do
   (
   	<whateveryouwant>
   	setfocus <parentrollout>
   	enableaccelerators = on
   )

that’s it. if it doesn’t work please show your code.

thanks for your reply, denis… i was able to get this working, but not consistently. i haven’t been able to narrow it down to anything–it seems to work completely randomly and fail completely randomly… i even thought it might be related to where the cursor was but even that doesn’t give a consistent result.

i’m not familiar with the ‘enableaccelerators’ toggle… does this need to be toggled off at somepoint to refresh?

my code is somewhat complicated, but here’s the gist: i have a main dialog (“gui”) that contains a dotnet treeview control. right-clicking on treeview item launches a rcmenu with a menuitem “miLoad”, and here is the handler for that:


		on miLoad picked do (

			createDialog subDialog modal:true


			setFocus gui
			enableaccelerators = on
		)

(“subDialog”) is another rollout definition with its own buttons and list view.

miLoad actually does quite a bit of other stuff (including setting an active viewport), but the “SetFocus” and “enableaccelerators” lines are last to act. indeed the focus is correctly set to the main dialog as the code instructs, but 3ds max hotkeys are sometimes functional, sometimes not (unless i actually click in a viewport somewhere).

i can probably post the entire code if it’s really necessary but it has a few references to external libraries and i fear it may create more questions than answers.

after some more trial and error, the success of this doesn’t appear to have anything to do with the setfocus\accelerators code, but rather where the cursor is and whether or not the subdialog is closed with a single-click or a double-click.

in my case, for keys to be restored i must use a double-click to close the modal dialog (selecting a treeview item) and there must be a viewport underneath the modal dialog.

from this behavior it appears that the double-click operation is actually registering as a viewport click somehow.

if the cursor is over the main parent dialog when the modal dialog is closed (or if i only use a single-click) hot keys do not transfer to max viewport commands. to be clear, this behavior is the same whether or not i use the setfocus\accelerator commands denis posted.

slow down… no one have known that you use a dotnet control… but i can bet that you don’t need any maxy-csharpy-dotty hack any way…
please show a piece of your code that causes freezing of keyboard entry.
there is no any magic, and can’t be.
when ANY max window gets a focus all hotkeys have to work.

i have to say that i was wrong… the problem is not trivial. as i have time i will look at this more careful.

ok … i’ve solved it.
in this sample i simulate middle mouse click in view. i don’t send activation message because i don’t want accidentally change the active window.


  global _user32 =
  (
  	source = ""
  	source += "using System;
"
  	source += "using System.Runtime.InteropServices;
"
  	source += "class User32
"
  	source += "{
"
  	source += "	[DllImport(\"user32.dll\")]
"
  	source += "	public static extern int PostMessage(Int32 hWnd, int wMsg, int wParam, int lParam);
"
  	source += "}
"
  
  	csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
  	compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
  					
  	compilerParams.GenerateInMemory = on
  	compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
  	compilerResults.CompiledAssembly.CreateInstance "User32"
  )
  
  fn MButtonViewClick =
  (
  	WM_MBUTTONDOWN 	= 0x0207
  	WM_MBUTTONUP 	= 0x0208
  	
  	hwnd = for w in (windows.getChildrenHWND #max) where w[4] == "ViewPanel" do exit with w[1]
  	hwnd = (windows.getChildrenHWND hwnd)[1][1]
  
  	_user32.postmessage hwnd WM_MBUTTONDOWN 0 0
  	_user32.postmessage hwnd WM_MBUTTONUP 0 0
  )
  
  try(destroyDialog editTextRol) catch()
  rollout editTextRol "After Edit Text..." width:200
  (
  	edittext tx width:196 pos:[0,4]
  	on tx entered text do
  	(
  		tx.text = ""
  		MButtonViewClick()
  	)
  )
  createdialog editTextRol 
  

honestly i was very surprised that this solution is so complicated. if anyone knows any better way, please share with us.

this works great! i was afraid no one else would be able to reproduce this problem, let alone fix it… thanks very much for your help!

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

in your previous post you said that you use treeview control… in your case the solution might be simpler.
could you make a little snippet that shows your problem?

Yea, as the original poster i felt i should chime in.

Since it was years ago, I believe this was the case and solution…

I was also having the problem with making max lose focus of an edit text in a rollout. We did the simulation right click stuff because in the help, and i cant find it for the moment, maybe i’m remembering wrong, or maybe bobo can chime in. But i believe somewhere it says max stores your “right clicks” in the viewport, which would result in quad randomly showing up. so i had to “right click” on a dialog, to make it lose focus of the edit text. Again this was years ago, but i believe that was the case, and the solution.

For mine, we had to use a custom dll, but it looks like denis, you came with a much more elegant solution.

Nicely done : )

ah, here it is

[left][b][b]NOTE:[/b][/b]

[/left]
[left]Right mouse button state is not always correct. If you right-click to bring up a right-click menu and then click in the viewport to dismiss the menu, the right mouse button is still reported as down.
[/left]

Page 1 / 2