Notifications
Clear all

[Closed] Drag-to-select interface possible?

It’s coming along. Still very early, since there’s no control points, but this is the most stable it’s been so far.



macroScript laniCharacterStudioDotNet category:"Lani Scripts" buttonText: "Lani Character Studio DotNet"

(

	/*
	CREDIT WHERE IT'S DUE:
	Most of this was taken from/started out as Paul Neale's excellent tutorials on Dotnet
	 http://paulneale.com/tutorials/dotNet/form/index.htm 
	Also many thanks to lo, denisT, JokerMartini and LoneRobot on cgsociety.org


	*/

	--Create a form and display it in Max. 
	--Read about this process in the form & MaxForm tutorial.

	global laniCharStudio_DotnetVisible
	if laniCharStudio_DotnetVisible == undefined then laniCharStudio_DotnetVisible = false
	global laniCharacterStudioFormGlbl
	global laniCharStudioLastPos

	laniCharacterStudioForm=dotNetObject "MaxCustomControls.MaxForm"

	sysPointer=dotNetObject "system.intPtr" (windows.getMaxHWND())
	maxHandle=dotNetObject "maxCustomControls.win32HandleWrapper" sysPointer

	laniCharacterStudioForm.bounds=dotNetObject "system.drawing.rectangle" 10 90 410 512
	laniCharacterStudioForm.text="Lani Character Studio - DotNet Drawing Edition(tm)"

	borderStyle=(dotNetClass "System.Windows.Forms.FormBorderStyle").Sizable
	selectionColor = ((dotNetClass "system.drawing.color").fromArgb 80 102 153 255)
	charStudioBG = (dotNetclass "System.Drawing.Image").fromfile @"X:\3dsmax\2013\MaxScript\images\characterStudioBackground.png"

	laniCharacterStudioForm.formBorderStyle=borderStyle
	laniCharacterStudioForm.ShowInTaskbar = false
		
	pBox=dotNetObject "pictureBox" --"system.windows.forms.pictureBox"

	--Set the size and location of the pictureBox
	pBox.bounds=dotNetObject "System.drawing.rectangle" 0 0 410 512

	--Set the background color
	pBox.backColor=(dotNetClass "system.drawing.color").gray

	--Add the pictureBox to the form
	laniCharacterStudioForm.controls.add pBox
			
	--Rectangle and brush for painted box	
	boxRec=dotNetObject "system.drawing.rectangle" 10 10 100 100

	boxBrush=dotNetObject "system.drawing.solidBrush" selectionColor
	pBox.backgroundImage = charStudioBG

	--Add the paint function
	fn pBoxPaint sender arg=
	(
		--formatProps arg.graphics
		--Create graphics object
		g=arg.graphics
		
		--Paint a filled rectangle into the pictureBox
		g.fillRectangle boxBrush boxrec
		
	)
	--Add the paint event handler 
	dotNet.addEventHandler pBox "paint" pBoxPaint

	mouseIsDown=false
	movingWindow=false
	mO = #(0,0)
	--hold the starting position of the drag
	dragStartX = -1
	dragStartY = -1

	--Add event handlers for the form.
	fn formMouseDown sender arg=
	(
		--Check to see which mouse button is being pressed. 
		if arg.button==arg.button.left do (
			--LEFT button is down
			--formatProps arg;
			mouseIsDown=true
			dragStartX = arg.x
			dragStartY = arg.y
			
			
		)
			
		if arg.button==arg.button.middle do (
			print #middle
			movingWindow = true
			mO = #(arg.x,arg.y)
		)
		
		if arg.button==arg.button.right do (
			--RIGHT button is down
			print #right
		)
		
	)
	fn formMouseUp sender arg=
	(
		
		mouseIsDown=false
		movingWindow=false
		laniCharStudioLastPos = #(laniCharacterStudioForm.Left,laniCharacterStudioForm.Top)
		
	)
	fn formMouseMove sender arg=
	(
		
		if mouseIsDown do
		(	
			boxRec=NormalizeRectangle dragStartX dragStartY arg.x arg.y
			pbox.refresh()
		)
		if movingWindow do
		(
			laniCharacterStudioForm.Left = mouse.screenpos.x-mO[1]
			laniCharacterStudioForm.Top = mouse.screenpos.y-mO[2]
		)
		
	)

	--Add the event handlers. 
	dotNet.addEventHandler pBox "mouseDown" formMouseDown
	dotNet.addEventHandler pBox "mouseUp" formMouseUp
	dotNet.addEventHandler pBox "mouseMove" formMouseMove

	--Set the life time control
	dotNet.setLifeTimeControl pBox #dotNet

	--Force an update to the form to fire the paint event

		if (laniCharStudio_DotnetVisible == false) then (
			laniCharStudio_DotnetVisible = true
			laniCharacterStudioForm.show maxHandle
			laniCharacterStudioFormGlbl = laniCharacterStudioForm
			if (laniCharStudioLastPos != undefined) then (
				laniCharacterStudioForm.Left = laniCharStudioLastPos[1]
				laniCharacterStudioForm.Top = laniCharStudioLastPos[2]
			)

		) else (
			laniCharStudio_DotnetVisible = false
			laniCharacterStudioFormGlbl.hide()
		)
		
		
	laniCharacterStudioForm.refresh()
	
)

This function is also needed, but I moved it to a separate file for clarity (since I will need more functions later)


fn NormalizeRectangle hX hY sX sY =
(
    local X = amin sX hX
	local Y = amin sY hY
	local w = abs (hX - sX)
	local h = abs (hY - sY)
	dotnetObject "system.drawing.rectangle" x y w h
)

Results in the following (so a looong way to go – but progress, so yay!)

Hmm, I must be missing something – but how would I go about creating X drawings of ellipses using just one iterative function? My current code is this:

update: is this a good way to do it?


macroScript laniCharacterStudioDotNet category:"Lani Scripts" buttonText: "Lani Character Studio DotNet"

(

	/*
	CREDIT WHERE IT'S DUE:
	Most of this was taken from/started out as Paul Neale's excellent tutorials on Dotnet
	 http://paulneale.com/tutorials/dotNet/form/index.htm 
	Also many thanks to lo, denisT, JokerMartini and LoneRobot on cgsociety.org


	*/

	--Create a form and display it in Max. 
	--Read about this process in the form & MaxForm tutorial.

	global laniCharStudio_DotnetVisible
	if laniCharStudio_DotnetVisible == undefined then laniCharStudio_DotnetVisible = false
	global laniCharacterStudioFormGlbl
	global laniCharStudioLastPos

	laniCharacterStudioForm=dotNetObject "MaxCustomControls.MaxForm"

	sysPointer=dotNetObject "system.intPtr" (windows.getMaxHWND())
	maxHandle=dotNetObject "maxCustomControls.win32HandleWrapper" sysPointer

	laniCharacterStudioForm.bounds=dotNetObject "system.drawing.rectangle" 10 90 425 540
	laniCharacterStudioForm.text="Lani Character Studio - DotNet Drawing Edition(tm)"

	borderStyle=(dotNetClass "System.Windows.Forms.FormBorderStyle").None
	selectionColor = ((dotNetClass "system.drawing.color").fromArgb 80 102 153 255)
	charStudioBG = (dotNetclass "System.Drawing.Image").fromfile @"X:\3dsmax\2013\MaxScript\images\characterStudioBackground.png"
	
	unselPointColor = ((dotNetClass "system.drawing.color").fromArgb 80 255 255 255)
	selPointColor = ((dotNetClass "system.drawing.color").fromArgb 80 0 255 0)
	
	ellipseRec = dotNetObject "system.drawing.rectangle" 0 0 20 20
	ellipseBrushUnSel = dotNetObject "system.drawing.solidBrush" unselPointColor
	ellipsePenUnSel = dotNetObject "system.drawing.pen" ellipseBrushUnSel 1
	
	
	
	laniCharacterStudioForm.formBorderStyle=borderStyle
	laniCharacterStudioForm.ShowInTaskbar = false
		
	pBox=dotNetObject "pictureBox" --"system.windows.forms.pictureBox"

	--Set the size and location of the pictureBox
	pBox.bounds=dotNetObject "System.drawing.rectangle" 0 0 425 540

	--Set the background color
	pBox.backColor=(dotNetClass "system.drawing.color").gray

	--Add the pictureBox to the form
	laniCharacterStudioForm.controls.add pBox
			
	--Rectangle and brush for painted box	
	boxRec=dotNetObject "system.drawing.rectangle" 10 10 0 0

	boxBrush=dotNetObject "system.drawing.solidBrush" selectionColor
	pBox.backgroundImage = charStudioBG

	--Add the paint function
	fn pBoxPaint sender arg=
	(
		--formatProps arg.graphics
		--Create graphics object
		g=arg.graphics
		
		--Paint a filled rectangle into the pictureBox
		g.fillRectangle boxBrush boxrec
		for i=1 to 5 do (
				try(
			g.DrawEllipse ellipsePenUnSel (dotNetObject "system.drawing.rectangle" (i*25) (i*25) 20 20)
				)catch(print(getCurrentException()))
			)
	)
	
	
	--Add the paint event handler 
	dotNet.addEventHandler pBox "paint" pBoxPaint

	mouseIsDown=false
	movingWindow=false
	mO = #(0,0)
	--hold the starting position of the drag
	dragStartX = -1
	dragStartY = -1

	--Add event handlers for the form.
	fn formMouseDown sender arg=
	(
		--Check to see which mouse button is being pressed. 
		if arg.button==arg.button.left do (
			--LEFT button is down
			--formatProps arg;
			mouseIsDown=true
			dragStartX = arg.x
			dragStartY = arg.y
			print("clicked at point: "+dragStartX as string+","+dragStartY as string)
			
		)
			
		if arg.button==arg.button.middle do (
			print #middle
			movingWindow = true
			mO = #(arg.x,arg.y)
		)
		
		if arg.button==arg.button.right do (
			--RIGHT button is down
			print #right
		)
		
	)
	fn formMouseUp sender arg=
	(
		
		mouseIsDown=false
		movingWindow=false
		laniCharStudioLastPos = #(laniCharacterStudioForm.Left,laniCharacterStudioForm.Top)
		boxRec.Width = 0
		boxRec.Height = 0
		pbox.refresh()
		
	)
	fn formMouseMove sender arg=
	(
		
		if mouseIsDown do
		(	
			boxRec=NormalizeRectangle dragStartX dragStartY arg.x arg.y
			pbox.refresh()
		)
		if movingWindow do
		(
			laniCharacterStudioForm.Left = mouse.screenpos.x-mO[1]
			laniCharacterStudioForm.Top = mouse.screenpos.y-mO[2]
		)
		
	)

	--Add the event handlers. 
	dotNet.addEventHandler pBox "mouseDown" formMouseDown
	dotNet.addEventHandler pBox "mouseUp" formMouseUp
	dotNet.addEventHandler pBox "mouseMove" formMouseMove

	--Set the life time control
	dotNet.setLifeTimeControl pBox #dotNet

	--Force an update to the form to fire the paint event

		if (laniCharStudio_DotnetVisible == false) then (
			laniCharStudio_DotnetVisible = true
			laniCharacterStudioForm.show(maxHandle)
			laniCharacterStudioFormGlbl = laniCharacterStudioForm
			if (laniCharStudioLastPos != undefined) then (
				laniCharacterStudioForm.Left = laniCharStudioLastPos[1]
				laniCharacterStudioForm.Top = laniCharStudioLastPos[2]
			)

		) else (
			laniCharStudio_DotnetVisible = false
			laniCharacterStudioFormGlbl.hide()
		)
		
		
	laniCharacterStudioForm.refresh()
	
)

Any pointers would be much appreciated

2 Replies
 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

That is the basic method. See my first code example in this thread.

I would avoid registering two different functions for the paint event. You can never be sure which one will be called first. Handle all your code in one function. If necessary, have this function call other sub-functions using the graphics object as a parameter.

(@mixx)
Joined: 11 months ago

Posts: 0

Good point, changed it accordingly.

Thanks, Rotem!

Yeah, very cool stuff LoneRobot.

 lo1

To be clear, this is an over-simplified example of what I mean:

struct ctrlPoint
(
	bounds,
	selected
)

dnFm = dotnetobject "form"
dnPnl = dotnetObject "panel"
rctCls = dotnetClass "System.Drawing.Rectangle"
ptCls = dotnetClass "System.Drawing.Point"
penCls = dotnetClass "System.Drawing.Pen"
brshCls = dotnetClass "System.Drawing.SolidBrush"
clrCls = dotnetClass "System.Drawing.Color"

dnPnl.dock = dnPnl.dock.Fill
ptPen = dotnetObject penCls (clrCls.black)
ptBrush = dotnetObject brshCls (clrCls.red)
selPtBrush = dotnetObject brshCls (clrCls.green)

ctrlPoints = #( \
	ctrlPoint (dotnetObject rctCls 100 100 20 20) off,
	ctrlPoint (dotnetObject rctCls 20 30 20 20) off,
	ctrlPoint (dotnetObject rctCls 150 180 20 20) off,
	ctrlPoint (dotnetObject rctCls 150 220 20 20) off,
	ctrlPoint (dotnetObject rctCls 300 10 20 20) off
)

fn paintFn s e =
(
	e.graphics.smoothingMode = e.graphics.smoothingMode.highQuality
	for p in ctrlPoints do
	(
		e.graphics.fillEllipse (if p.selected then selPtBrush else ptBrush) p.bounds
		e.graphics.drawEllipse ptPen p.bounds
	)
)

fn mouseUp s e =
(
	for p in ctrlPoints where p.bounds.contains e.location do
	(
		p.selected = not p.selected
		s.invalidate p.bounds
	)
)

dnFm.controls.add dnPnl
dotnet.addEventHandler dnPnl "MouseUp" mouseUp
dotnet.addEventHandler dnPnl "Paint" paintFn
dnFm.size = dotnetObject "System.Drawing.Size" 400 400
dnFm.show()
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

if you like this way of making UI probably you have to make friends with WPF… it will help you to design any control without deriving from the existent.

 lo1

maybe I’m just a … … control-freak

 lo1

Don’t get me wrong, I won’t recreate a checkbox or datagridview just for fun, that’s just unnecessary tedium. Only when there are obvious benefits.

I’ve been meaning to make friends with WPF for a long time, it’s somewhere on my list

I’m still working on this, but it’s not really in a postable state right now heh. Making progress, though – many thanks to everyone for the help so far!

What’s this WPF though?

 lo1

http://en.wikipedia.org/wiki/Windows_Presentation_Foundation

Think of it as an evolution of system.windows.forms.

Thanks, not sure if it’s something I’ll even try to incorporate right now, but there’s yet another thing to look into

edit: and why the HELL have I never used structs before – those things are great! :banghead:

Page 4 / 5