Notifications
Clear all

[Closed] dotNet Form on top of Max only?

 PEN

Hows this for odd, this doesn’t work as it is now being created in local scope.

(
	try(form.close())catch()
	fn formPaint sender arg=
	(
		rec=dotNetObject "system.drawing.rectangle" 2 2 200 200
		bgColor=(dotNetClass "system.drawing.color").red
		brush=dotnetobject "System.Drawing.SolidBrush" bgColor
		arg.graphics.FillRectangle brush rec
	)

	-- form=dotNetObject "form"
	form=dotNetObject "MaxCustomControls.MaxForm"
	form.showmodeless()
	-- form.show()
	form.AllowTransparency=true
	-- form.opacity=10
	form.BackColor=(dotNetClass "system.drawing.color").fromArgb 0 255 0 
	form.TransparencyKey=(dotNetClass "system.drawing.color").fromArgb 0 255 0 
	-- form.ShowInTaskBar =false
	form.FormBorderStyle=form.FormBorderStyle.none
	-- form.TopMost=true

	dotnet.addEventHandler form "paint" formPaint
	dotnet.setLifeTimeControl form #dotNet

	LHM_methods.formatProps form
)
 PEN

I also can’t get it to display correctly when using file in. So there is just about no way so far to get this to work out, I can’t even run it with the Max script run command and have it show up transparent.

Can any one confirm this?

well… if we can’t do anything without c#’s help just ask c# for this help


global WindowWrapper 
(
 fn getWindowWrapper = 
 (
  source = ""
  source += "using System;
"
  source += "using System.Windows.Forms;
"
  source += "public class WindowWrapper : IWin32Window
"
  source += "{
"
  source += "	public WindowWrapper(IntPtr handle) { _hwnd = handle; }
"
  source += "	public WindowWrapper(Int32 handle) { _hwnd = (IntPtr)handle; }
"
  source += "	public IntPtr Handle { get { return _hwnd; } }
"
  source += "	private IntPtr _hwnd;
"
  source += "}
"
  -- Compile on fly
  csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
  compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
  compilerParams.ReferencedAssemblies.Add("System.dll");
  compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll");
  compilerParams.GenerateInMemory = on
  compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
  
  compilerResults.CompiledAssembly
 )
 try(form.close())catch()
  
 if WindowWrapper == undefined do
 (
  getWindowWrapper()
  WindowWrapper = dotnetobject "WindowWrapper" (windows.getMAXHWND()) 
 )
 fn formPaint sender arg=
 (
  rec = dotNetObject "system.drawing.rectangle" 2 2 200 200
  bgColor = (dotNetClass "system.drawing.color").red
  brush = dotnetobject "System.Drawing.SolidBrush" bgColor
  arg.graphics.FillRectangle brush rec
 )
-- form = dotNetObject "MaxCustomControls.MaxForm"
 form = dotNetObject "Form"
 dotnet.addEventHandler form "paint" formPaint
 form.AllowTransparency = true
 form.opacity = 10
 form.TransparencyKey = (dotNetClass "system.drawing.color").fromArgb 0 255 0 
 form.FormBorderStyle = form.FormBorderStyle.none
 form.ShowInTaskBar = false
 form.BackColor = (dotNetClass "system.drawing.color").fromArgb 0 255 0 
 --form.showmodeless()
 --form.show()
 form.show(WindowWrapper) -- Shows the form with the specified owner (MAX) to the user
)
--dotnet.setLifeTimeControl form #dotNet

I think you could also do the same like so:

local MainForm = DotNetObject "MaxCustomControls.MaxForm"
local p = DotNetObject "System.IntPtr" ( Windows.GetMAXHWND() )
local maxHwnd = DotNetObject "MaxCustomControls.Win32HandleWrapper" p
MainForm.Show ( maxHwnd )

Light

3 Replies
(@denist)
Joined: 11 months ago

Posts: 0

great! i don’t have time to check all new methods of all new max dlls

but it works for dotnetobject “Form” only


(
  form = dotNetObject "Form"
  p = DotNetObject "System.IntPtr" ( Windows.GetMAXHWND() )
  maxHwnd = DotNetObject "MaxCustomControls.Win32HandleWrapper" p -- I like it!
  form.Show ( maxHwnd )
)

(@light)
Joined: 11 months ago

Posts: 0

I like your determination (:

Mine works on MaxForm too in Max 2010.

Thanks,
Light

 PEN
(@pen)
Joined: 11 months ago

Posts: 0

Well this is just fantastic. I tried getting DotNetObject “System.IntPtr” ( Windows.GetMAXHWND() ) to work early in my test but just got errors. I guess I was just doing it wrong but at least I was on the right track. Is MaxCustomControls in the SDK help as it is not in the Max script help at all. I should be able to get this tool complete, not something that I can release to the public as it is very specific to this project but I will release some screen grabs so you can see where I have been going with it all.

Thanks for every ones help.

 PEN

Thanks guys, I will have a poke at this later today.

Hi

any sugestions for 3DsMax 9 ?

form = dotNetObject “Form”
diag = dotnetclass “System.Diagnostics.Process”
app_array = diag.GetProcessesByName “3Dsmax”
app_array[1].MainWindowHandle
app_array[1].MainWindowTitle
app_array[1].Handle

hwnd = DotNetObject “IntPtr” app_array[1].MainWindowHandle

–how to convert it in to System.Windows.Forms.IWin32Window

maxHwnd = DotNetObject “System.Windows.Forms.IWin32Window” ???

form.Show ( maxHwnd )

3 Replies
(@denist)
Joined: 11 months ago

Posts: 0

“MaxCustomControls.Win32HandleWrapper” dotnet object was added to max 2010 …
you can use my c# solution for 2009 (see above)

(@light)
Joined: 11 months ago

Posts: 0

Actually it’s added in Max 2008.

Cheers,
Light

(@denist)
Joined: 11 months ago

Posts: 0

it was not added for me :(… eh…

p = DotNetObject “System.IntPtr” ( Windows.GetMAXHWND() )
c = dotNetclass “System.Windows.Forms.Control”

maxHwnd = ctrl.FromHandle c

listener: undefined

why ?

Hi Denis this function is cool! How can I mis it again

fn getWindowWrapper =
(
source = “”
source += “using System;

source += “using System.Windows.Forms;

source += “public class WindowWrapper : IWin32Window

source += “{

source += ” public WindowWrapper(IntPtr handle) { _hwnd = handle; }

source += ” public WindowWrapper(Int32 handle) { _hwnd = (IntPtr)handle; }

source += ” public IntPtr Handle { get { return _hwnd; } }

source += ” private IntPtr _hwnd;

source += “}

– Compile on fly
csharpProvider = dotnetobject “Microsoft.CSharp.CSharpCodeProvider”
compilerParams = dotnetobject “System.CodeDom.Compiler.CompilerParameters”
compilerParams.ReferencedAssemblies.Add(“System.dll”);
compilerParams.ReferencedAssemblies.Add(“System.Windows.Forms.dll”);
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)

compilerResults.CompiledAssembly
)

Thanks Man


Global mc2ViewportRecorderDialog
Global WindowWrapper
if mc2ViewportRecorderDialog != undefined do destroyDialog mc2ViewportRecorderDialog
rollout mc2ViewportRecorderDialog "rec" width:304 height:24
(
	local dMove = false, DmPos, frame_min = [100,100], frame_max = [2048,2048]
	local netDMove = false, netDmPos, netform
	button btn_rec "R" pos:[0,0] width:24 height:24 --images:(mc2Call.getIcon 172) tooltip:"Start Reco"
	button btn_stop "S" pos:[24,0] width:24 height:24 --images:(mc2Call.getIcon 171) tooltip:"Stop Record"
	button btn_play "P" pos:[48,0] width:24 height:24
	label lbl1 "FPS:" pos:[76,4] width:24 height:12
	spinner spn_fps "" pos:[104,4] width:52 height:16 range:[1,45,4] type:#integer scale:1
	label lbl2 "W:" pos:[160,4] width:16 height:12
	spinner spn_w "" pos:[176,4] width:52 height:16 range:[frame_min.x,frame_max.x,280] type:#integer scale:1
	label lbl3 "H:" pos:[236,4] width:16 height:12
	spinner spn_h "" pos:[248,4] width:52 height:16 range:[frame_min.y,frame_max.y,180] type:#integer scale:1
	fn getWindowWrapper = --made by DenisT :-)
	(
		print "compile WindowWrapper"
 
		source = ""
		source += "using System;
"
		source += "using System.Windows.Forms;
"
		source += "public class WindowWrapper : IWin32Window
"
		source += "{
"
		source += "	public WindowWrapper(IntPtr handle) { _hwnd = handle; }
"
		source += "	public WindowWrapper(Int32 handle) { _hwnd = (IntPtr)handle; }
"
		source += "	public IntPtr Handle { get { return _hwnd; } }
"
		source += "	private IntPtr _hwnd;
"
		source += "}
"
		-- Compile on fly
		csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
		compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
		compilerParams.ReferencedAssemblies.Add("System.dll");
		compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll");
		compilerParams.GenerateInMemory = on
		compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
 
		compilerResults.CompiledAssembly
	)
	fn resizing ctrl arg =
	(
		--mc2system.show ctrl
		--ctrl.MouseButtons
		--ctrl.MousePosition
		mc2ViewportRecorderDialog.spn_w.value = ctrl.Width
		mc2ViewportRecorderDialog.spn_h.value = ctrl.Height
		--netform.Location =dotNetObject "System.Drawing.Point" 200 300
	)
	fn updateFrameSize axis val =
	(
		case axis of
		(
			#x:(netform.Width = val)
			#y:(netform.Height = val)
		)
	)
	fn updateFramePos dia_pos: =
	(
		if dia_pos == unsupplied do dia_pos = getDialogPos mc2ViewportRecorderDialog
		netform.Location = dotNetObject "System.Drawing.Point" (dia_pos.x) (dia_pos.y+mc2ViewportRecorderDialog.height+6)
	)
	fn dragFrame ctrl arg = 
	(
		if netDMove do
		(
			local netDPos = [ctrl.MousePosition.x, ctrl.MousePosition.y] - netDmPos
			netform.Location = dotNetObject "System.Drawing.Point" netDPos.x netDPos.y
		)
	)
	fn enableDrag = 
	(
		format "dia pos :%	 dia m pos:%	screen m pos:%
" [netform.Location.x, netform.Location.y] [netform.MousePosition.x, netform.MousePosition.y] mouse.screenpos
		netDmPos = [netform.MousePosition.x, netform.MousePosition.y] - [netform.Location.x, netform.Location.y] 
		netDMove = true 
		--.Cursor : <System.Windows.Forms.Cursor>
	)
	fn disableDrag = (netDMove = false)
	fn createFrame =
	(
		if WindowWrapper == undefined do
		(
			getWindowWrapper()
			WindowWrapper = dotnetobject "WindowWrapper" (windows.getMAXHWND()) 
			print WindowWrapper
		)
		try( netform.close(); netform.dispose() )catch()
 
		local color_class = (dotnetclass "System.Drawing.Color")
		 netform = dotnetobject "System.Windows.Forms.Form"
		 netform.width = 200
		 netform.height = 200
		netform.MinimumSize = dotNetObject "System.Drawing.Size" frame_min.x frame_min.y
		netform.MaximumSize = dotNetObject "System.Drawing.Size" frame_max.x frame_max.y
		--netform.TopMost = true --always top on all
		 netform.ShowInTaskbar = false --hide from windows task bar
		netform.ControlBox = false --hide main bar
		netform.backColor = color_class.fromArgb 0 255 0 --form Back Color
		 --netform.TransparencyKey = color_class.fromArgb 0 255 0 --form Back Color
		netform.opacity = 0.5
 
		--.Controls : <System.Windows.Forms.Control+ControlCollection>, read-only
 
		--mc2system.show netform
		dotNet.addEventHandler netform "SizeChanged" resizing
		dotNet.addEventHandler netform "MouseMove" dragFrame
		dotNet.addEventHandler netform "MouseDown" enableDrag 
		dotNet.addEventHandler netform "MouseUp" disableDrag
 
		netform.Show ( WindowWrapper )
 
		updateFramePos()
	)
	on mc2ViewportRecorderDialog rbuttonup pos do (destroyDialog mc2ViewportRecorderDialog)
	-->MoveMode
	on mc2ViewportRecorderDialog lbuttondown pos do (dMove = true; DmPos = pos; if not keyboard.shiftPressed do pushprompt "Pres Shift To Move...")
	on mc2ViewportRecorderDialog lbuttonup pos do (dMove = false; pushprompt "")
	on mc2ViewportRecorderDialog mouseMove pos do
	(
		if dMove and keyboard.shiftPressed do 
		(
			setDialogPos mc2ViewportRecorderDialog (mouse.screenpos - DmPos)
		)
	)
	on mc2ViewportRecorderDialog open do
	(
		createFrame()
	)
	on mc2ViewportRecorderDialog close do try( netform.close(); netform.dispose() )catch()
	on mc2ViewportRecorderDialog moved pos do (updateFramePos dia_pos:pos)
	on spn_w changed val do (updateFrameSize #x val)
	on spn_h changed val do (updateFrameSize #y val) 
	on btn_rec pressed do
	(
		netform.backColor = color_class.fromArgb 0 255 0 --form Back Color
		 netform.TransparencyKey = netform.backColor
	)
	on btn_stop pressed do
	(
		--netform.backColor= color_class.fromArgb 0 255 0 --form Back Color
		 netform.TransparencyKey = undefined
	)
)
 
createDialog mc2ViewportRecorderDialog pos:[200,200] style:#(#style_border)
 

 PEN

Nice work guys. I still have yet to poke at it with my stick but I hope to get back to this part of the project tomorrow.

Hope i got the right end of the stick here Paul. there could be a few things going on here form what i can work out.

If you use a windows.forms.form object, you can use the transparency key to set the client window to transparent. You have this working already with your code. The transparent color is matted out on the backgorund of the form, leaving you to paint the 
contents. However, because you are using the paint event to draw things onto the form, and even when supplying a see-through brush color it doesnt appear to give the painted controls a seethrough quality. This is because the form seems to blend the resultant color with the color supplied as the form's transparency key. Even though the form itself is see-through, if for example you use red as a form transparency key and put a yellow square at 50% alpha in the paint event, all you will end up with is an orange square on a transparent form, as it creates a color blend between the two. The bummer is a form won't support using the transparent color as a background color.

Setting a form's opacity to anything above 1 will not work, despite visual studio asking for a percentage, your values specified need to be between 0 and 1. 

However, this didnt seem to work when used with a maxform. Maxform automatically gets the background color of the maxUI and paints this on the form. In VB you can prevent the form background painting itself by overideing the protected sub onBackgroundPaint. However I dont know if this is it here. Again you can set the maxform opacity to values between 0 and 1 but not the abilty to make the painted contents a different opacity level. 

one option might be to mask the area of the form you need to hide, then use the opacity to blend the form's drawn controls with the background viewport seen through it. You can do this by creating a region object (either from a rectangle or a graphics path if you need more compicated shapes - check my GDI+ framework for examples) You could in theory have a sub that calculates the path and then uses the same coordinates in the paint handler i guess. The thing about using a region means you do however need to build some form of movement into the control by click-dragging the client area, so far I havent been able to do this in max, only in VS by inherting a form object and adding the code into the class. humph.
(
    	try(form.close())catch()
    		
    		
    	fn formPaint sender arg=
    	(
    	--	arg.graphics.clear((dotNetClass "system.drawing.color")fromargb 255 255 255)
    		rec=dotNetObject "system.drawing.rectangle" 2 2 200 200
    		bgColor=(dotNetClass "system.drawing.color").fromargb 255 255 0 0 
    		brush=dotnetobject "System.Drawing.SolidBrush" bgColor
    		arg.graphics.FillRectangle brush rec
    	)
    	
    	fn clickhandler sender arg =
    	(
    		sender.close()
    	)
    	
    	--form=dotNetObject "form"
    	form=dotNetObject "MaxCustomControls.MaxForm"	
    	-- form.show()
    	
    		
       -- form.AllowTransparency=true
    	form.opacity=0.5
       -- form.BackColor=(dotNetClass "system.drawing.color").green
       -- form.TransparencyKey=(dotNetClass "system.drawing.color").green
    	-- form.ShowInTaskBar =false
    	form.FormBorderStyle=form.FormBorderStyle.none
    	-- form.TopMost=true
    	
    	dotnet.addEventHandler form "paint" formPaint
    	dotnet.addEventHandler form "click" clickhandler
    	dotnet.setLifeTimeControl form #dotNet
    	
    	cliprect=dotNetObject "system.drawing.rectangle" 2 2 200 200
    	formregion  =dotnetobject "system.drawing.Region" clipRect
    	form.Region = formregion
    	
    	form.showmodeless()
    )
    
Page 2 / 3