Notifications
Clear all

[Closed] Open Code Project: Self Made Image Viewer

I want to start new type of thread.
It’s any project where everyone can show and share any ideas, methods, tricks, etc. to help other people to navigate in the MXS,.NET,etc. world.

 Long holidays are coming and I want to post a snippet that shows how to make Image Viewer yourself using as much as possible .NET and only .NET methods.
 It's an open source and everyone free to play with it and use it (Just don't forget to give me a credit :)). 
 I didn't put any comments in the code (I want to give you a time to dig yourself). I didn't clean or optimize the code. 
 
 Please ask your questions, leave any ideas and wishes; any optimization solutions are welcome...
 
 In new year I will try to explain all code step-by-step...
 
 (MAX 2010 or [b]change default image Directory[/b])

  global DGV_Icons
  fn getGIFFiles = if DGV_Icons == undefined or true do
  (
  --	local path = (getDir #ui) + "Icons\\"
  --	local files = getFiles (path + "*.ico")
  
  	local path = (getDir #ui) + "Ribbon\\Tooltips\\Images\\"
  	local files = getFiles (path + "*.gif")
  
  --	local path = (getDir #ui) + "Ribbon\\Icons\\Modeling\\"
  --	local files = getFiles (path + "*.bmp")
  	DGV_Icons = for f in files collect 
  	(
  		bmp = dotNetObject "System.Drawing.Bitmap" f
  		bmp.tag = f
  		bmp
  	)
  )
  getGIFFiles()
  
  global DataGridViewExtensionAssembly
  fn CreateDataGridViewExtensionAssembly forceRecompile:on =
  (
  	if forceRecompile or not iskindof ::DataGridViewExtensionAssembly dotnetobject or (::DataGridViewExtensionAssembly.GetType()).name != "Assembly" do
  	(
  
  source = ""
  source += "using System;
"
  source += "using System.Reflection;
"
  source += "using System.Runtime.InteropServices;
"
  source += "using System.Drawing;
"
  source += "using System.Windows.Forms;
"
  source += "namespace DataGridViewExtension
"
  source += "{
"
  source += "	public class Style
"
  source += "	{
"
  source += "		public void SetStyle(Control control, ControlStyles styles, bool newValue)
"
  source += "		{
"
  source += "			object[] args = { styles, newValue };
"
  source += "			typeof(Control).InvokeMember(\"SetStyle\",
"
  source += "					BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
"
  source += "					null, control, args);
"
  source += "		}
"
  source += "		public bool SetSelectable(Control control, bool newValue)
"
  source += "		{
"
  source += "			SetStyle(control, ControlStyles.Selectable, newValue);
"
  source += "			return newValue;
"
  source += "		}
"
  source += "		public void SetDoubleBuffer(Control control)
"
  source += "		{
"
  source += "			SetStyle(control, ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
"
  source += "		}
"
  source += "	}
"
  source += "	public class ImageTextCellColumn : DataGridViewImageColumn
"
  source += "	{
"
  source += "		private Boolean showLabel;
"
  source += "		private String label;
"
  source += "		private ContentAlignment labelAlign;
"
  source += "		private Color labelBackColor;
"
  source += "		private Color labelForeColor;
"
  source += "		public ImageTextCellColumn()
"
  source += "		{
"
  source += "			this.ShowLabel = true;
"
  source += "			this.LabelForeColor = Color.White;
"
  source += "			this.LabelBackColor = Color.FromArgb(100, Color.Black);
"
  source += "			this.CellTemplate = new ImageTextCell();
"
  source += "		}
"
  source += "		public override object Clone()
"
  source += "		{
"
  source += "			ImageTextCellColumn c = base.Clone() as ImageTextCellColumn;
"
  source += "			c.ShowLabel = this.showLabel;
"
  source += "			c.Label = this.label;
"
  source += "			c.LabelAlign = this.labelAlign;
"
  source += "			c.LabelForeColor = this.labelForeColor;
"
  source += "			c.LabelBackColor = this.labelBackColor;
"
  source += "			return c;
"
  source += "		}
"
  source += "		private ImageTextCell ImageTextCellTemplate
"
  source += "		{
"
  source += "			get { return this.CellTemplate as ImageTextCell; }
"
  source += "		}
"
  source += "		public Boolean ShowLabel
"
  source += "		{
"
  source += "			get { return this.showLabel; }
"
  source += "			set { this.showLabel = value; }
"
  source += "		}
"
  source += "		public String Label
"
  source += "		{
"
  source += "			get { return this.label; }
"
  source += "			set { this.label = value; }
"
  source += "		}
"
  source += "		public ContentAlignment LabelAlign
"
  source += "		{
"
  source += "			get { return this.labelAlign; }
"
  source += "			set { this.labelAlign = value; }
"
  source += "		}
"
  source += "		public Color LabelForeColor
"
  source += "		{
"
  source += "			get { return this.labelForeColor; }
"
  source += "			set { this.labelForeColor = value; }
"
  source += "		}
"
  source += "		public Color LabelBackColor
"
  source += "		{
"
  source += "			get { return this.labelBackColor; }
"
  source += "			set { this.labelBackColor = value; }
"
  source += "		}
"
  source += "	}
"
  source += "	public class ImageTextCell : DataGridViewImageCell
"
  source += "	{
"
  source += "		private Boolean showLabel;
"
  source += "		private String label;
"
  source += "		private Color labelBackColor;
"
  source += "		private Color labelForeColor;
"
  source += "		public ImageTextCell()
"
  source += "		{
"
  source += "			this.ShowLabel = true;
"
  source += "		}
"
  source += "		public override object Clone()
"
  source += "		{
"
  source += "			ImageTextCell c = base.Clone() as ImageTextCell;
"
  source += "			c.ShowLabel = this.showLabel;
"
  source += "			c.Label = this.label;
"
  source += "			c.LabelForeColor = this.labelForeColor;
"
  source += "			c.LabelBackColor = this.labelBackColor;
"
  source += "			return c;
"
  source += "		}
"
  source += "		public Boolean ShowLabel
"
  source += "		{
"
  source += "			get
"
  source += "			{
"
  source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return showLabel; }
"
  source += "				else return (this.showLabel & this.ImageTextCellColumn.ShowLabel);
"
  source += "			}
"
  source += "			set { if (this.showLabel != value) { this.showLabel = value; } }
"
  source += "		}
"
  source += "		public String Label
"
  source += "		{
"
  source += "			get
"
  source += "			{
"
  source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return label; }
"
  source += "				else if (this.label != null)
"
  source += "				{
"
  source += "					return this.label;
"
  source += "				}
"
  source += "				else
"
  source += "				{
"
  source += "					return this.ImageTextCellColumn.Label;
"
  source += "				}
"
  source += "			}
"
  source += "			set { if (this.label != value) { this.label = value; } }
"
  source += "		}
"
  source += "		public Color LabelForeColor
"
  source += "		{
"
  source += "			get
"
  source += "			{
"
  source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return labelForeColor; }
"
  source += "				else if (this.labelForeColor != Color.Empty)
"
  source += "				{
"
  source += "					return this.labelForeColor;
"
  source += "				}
"
  source += "				else
"
  source += "				{
"
  source += "					return this.ImageTextCellColumn.LabelForeColor;
"
  source += "				}
"
  source += "			}
"
  source += "			set { if (this.labelForeColor != value) { this.labelForeColor = value; } }
"
  source += "		}
"
  source += "		public Color LabelBackColor
"
  source += "		{
"
  source += "			get
"
  source += "			{
"
  source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return labelBackColor; }
"
  source += "				else if (this.labelBackColor != Color.Empty)
"
  source += "				{
"
  source += "					return this.labelBackColor;
"
  source += "				}
"
  source += "				else
"
  source += "				{
"
  source += "					return this.ImageTextCellColumn.LabelBackColor;
"
  source += "				}
"
  source += "			}
"
  source += "			set { if (this.labelBackColor != value) { this.labelBackColor = value; } }
"
  source += "		}
"
  source += "		protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
"
  source += "			DataGridViewElementStates cellState, object value, object formattedValue, string errorText,
"
  source += "			DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
"
  source += "		{
"
  source += "			// Paint the base content
"
  source += "			base.Paint(graphics, clipBounds, cellBounds, rowIndex,
"
  source += "				cellState, value, formattedValue, errorText,
"
  source += "				cellStyle, advancedBorderStyle, paintParts);
"
  source += "			if (this.ShowLabel && this.Label != null)
"
  source += "			{
"
  source += "				// Draw the image clipped to the cell.
"
  source += "				System.Drawing.Drawing2D.GraphicsContainer container = graphics.BeginContainer();
"
  source += "				SizeF ss = TextRenderer.MeasureText(this.Label, cellStyle.Font);
"
  source += "				ss = SizeF.Add(ss, new SizeF(0, 2));
"
  source += "				Single px = cellBounds.X;
"
  source += "				Single tx, py;
"
  source += "				switch (this.ImageTextCellColumn.LabelAlign)
"
  source += "				{
"
  source += "					case ContentAlignment.BottomCenter:
"
  source += "						{
"
  source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
  source += "							py = (cellBounds.Height - ss.Height) + cellBounds.Y;
"
  source += "							break;
"
  source += "						}
"
  source += "					case ContentAlignment.MiddleCenter:
"
  source += "						{
"
  source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
  source += "							py = (cellBounds.Height - ss.Height) / 2 + cellBounds.Y;
"
  source += "							break;
"
  source += "						}
"
  source += "					case ContentAlignment.TopCenter:
"
  source += "						{
"
  source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
  source += "							py = cellBounds.Y;
"
  source += "							break;
"
  source += "						}
"
  source += "					case ContentAlignment.TopLeft:
"
  source += "						{
"
  source += "							tx = px;
"
  source += "							py = cellBounds.Y;
"
  source += "							break;
"
  source += "						}
"
  source += "					case ContentAlignment.BottomRight:
"
  source += "						{
"
  source += "							tx = (cellBounds.Width - ss.Width) + px;
"
  source += "							py = (cellBounds.Height - ss.Height) + cellBounds.Y;
"
  source += "							break;
"
  source += "						}
"
  source += "					default:
"
  source += "						{
"
  source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
  source += "							py = (cellBounds.Height - ss.Height) + cellBounds.Y;
"
  source += "							break;
"
  source += "						}
"
  source += "				}
"
  source += "				Rectangle rect = new Rectangle((int)px, (int)py, (int)cellBounds.Width, (int)ss.Height);
"
  source += "				graphics.SetClip(rect);
"
  source += "				graphics.FillRectangle(new SolidBrush(this.LabelBackColor), rect);
"
  source += "				graphics.DrawString(this.Label, cellStyle.Font, new SolidBrush(this.LabelForeColor), tx, py);
"
  source += "				graphics.EndContainer(container);
"
  source += "			}
"
  source += "		}
"
  source += "		public ImageTextCellColumn ImageTextCellColumn
"
  source += "		{
"
  source += "			get { return this.OwningColumn as ImageTextCellColumn; }
"
  source += "		}
"
  source += "	}
"
  source += "}
"
  
  		csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
  		compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
  
  		compilerParams.ReferencedAssemblies.AddRange #("System.dll","System.Windows.Forms.dll","System.Drawing.dll");
  
  		compilerParams.GenerateInMemory = true
  		compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
  		
  		if (compilerResults.Errors.Count > 0 ) then
  		(
  			errs = stringstream ""
  			for i = 0 to (compilerResults.Errors.Count-1) do
  			(
  				err = compilerResults.Errors.Item[i]
  				format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs 
  			)
  			MessageBox (errs as string) title: "Errors encountered while compiling C# code"
  			format "%
" errs
  			undefined
  		)
  		else
  		(
  			DataGridViewExtensionAssembly = compilerResults.CompiledAssembly
  --			DataGridViewExtensionAssembly.CreateInstance "ImageTextCellColumn"
  		)
  	)
  )
  --global DataGridViewExtension = if DataGridViewExtension == undefined then CreateDataGridViewExtensionAssembly() else DataGridViewExtension
  global DataGridViewExtensionOps = CreateDataGridViewExtensionAssembly forceRecompile:on
  
  try(form.close()) catch()
  form = dotnetobject "MaxCustomControls.Maxform"
  form.Text = "DataGridView ImageTextCell"	
  
  form.StartPosition = form.StartPosition.Manual
  form.Location = dotnetobject "System.Drawing.Point" 200 100
  form.Size = dotnetobject "System.Drawing.Size" 800 660
  
  addc = dotnetobject "Button"
  addc.text = "Add Column"
  addc.Dock = addc.Dock.Top	
  
  delc = dotnetobject "Button"
  delc.text = "Remove Column"
  delc.Dock = addc.Dock.Top	
  	
  addr = dotnetobject "Button"
  addr.text = "Add Row"
  addr.Dock = addc.Dock.Top	
  
  delr = dotnetobject "Button"
  delr.text = "Remove Row"
  delr.Dock = addc.Dock.Top	
  
  gv = dotnetobject "DataGridView"
  cc = DataGridViewExtensionAssembly.CreateInstance "DataGridViewExtension.Style"
  cc.SetDoubleBuffer gv
  font = gv.font 
  gv.font = dotNetObject "System.Drawing.Font" font.FontFamily font.Size font.style.Bold
  	
  
  --bc = dotNetObject "System.Windows.Forms.DataGridViewButtonColumn"
  --bc = dotNetObject "System.Windows.Forms.DataGridViewImageColumn"
  bc = DataGridViewExtensionAssembly.CreateInstance "DataGridViewExtension.ImageTextCellColumn"
  bc.LabelBackColor = (dotnetclass "System.Drawing.Color").FromARGB 70 (dotnetclass "System.Drawing.Color").DarkRed
  bc.LabelForeColor = (dotnetclass "System.Drawing.Color").FromARGB 200 (dotnetclass "System.Drawing.Color").Black
  --bc.LabelForeColor = (dotnetclass "System.Drawing.Color").White
  --bc.LabelBackColor = (dotnetclass "System.Drawing.Color").Transparent
  
  --bc.LabelAlign = bc.LabelAlign.BottomRight
  
  p = dotnetobject "System.Windows.Forms.Padding" 2
  p.Bottom = 16
  bc.DefaultCellStyle.Padding = p
  bc.ImageLayout = bc.ImageLayout.Normal
  
  /* Flat Settings */
  bc.DefaultCellStyle.BackColor = bc.DefaultCellStyle.BackColor.Beige 
  --bc.FlatStyle = bc.FlatStyle.Flat 
  
  fn addColumn s e =
  (
  	gv = s.parent.controls.item[0]
  	gv.SuspendLayout()
  	gv.columns.add (bc.clone())
  	gv.ResumeLayout()
  )	
  dotNet.addEventHandler addc "Click" addColumn
  fn removeColumn s e =
  (
  	gv = s.parent.controls.item[0]
  	gv.SuspendLayout()
  	gv.ColumnCount = amax (gv.ColumnCount-1) 1
  	gv.ResumeLayout()
  )	
  dotNet.addEventHandler delc "Click" removeColumn
  fn addRow s e =
  (
  	gv = s.parent.controls.item[0]
  	gv.SuspendLayout()
  	s.parent.controls.item[0].RowCount += 1
  	gv.ResumeLayout()
  )	
  dotNet.addEventHandler addr "Click" addRow
  fn removeRow s e =
  (
  	gv = s.parent.controls.item[0]
  	gv.SuspendLayout()
  	gv.RowCount = amax (gv.RowCount-1) 1
  	gv.ResumeLayout()
  )	
  dotNet.addEventHandler delr "Click" removeRow
  
  fn CellClick s e = 
  (
  	cell = s.rows.item[e.rowindex].cells.item[e.columnindex]
  	format "button: %
" cell.value
  )
  fn CellFormatting s e =
  (
  	c = e.rowindex*s.ColumnCount + e.ColumnIndex
  	i = mod c DGV_Icons.count
  	bmp = DGV_Icons[i+1]
  	
  	cell = s.rows.item[e.rowindex].cells.item[e.columnindex]
  	cell.ImageLayout = if cell.Size.width < bmp.width or cell.Size.height < bmp.height then cell.ImageLayout.Zoom
  		else cell.ImageLayout.Normal
  	if not cell.ImageTextCellColumn.ShowLabel do cell.ShowLabel = off
  	e.value = bmp
  	cell.Description = bmp.tag
  --	cell.Description = (e.rowindex as string) + " - " + (e.columnindex as string) --+ "
cell"
  	cell.Label = ((c+1) as integer) as string + " - " + (filenamefrompath cell.Description)
  	cell.ToolTipText = bmp.tag
  )
  fn updateGridView s e = 
  (
  	gv.SuspendLayout()
  	for r=0 to s.RowCount-1 do for i=0 to s.ColumnCount-1 do
  	(
  		cell = s.rows.item[r].cells.item[i]
  		v = r*s.ColumnCount + i
  --		if cell.value != v do cell.value = v
  	)
  	gv.ResumeLayout()
  )
  fn changeGridViewRowHeight gv height = 
  (
  	gv.SuspendLayout()
  	gv.RowTemplate.Height = height
  	for r=0 to gv.RowCount-1 do gv.rows.item[r].Height = height
  	gv.ResumeLayout()
  )
  
  gv.ColumnHeadersDefaultCellStyle.Alignment = gv.ColumnHeadersDefaultCellStyle.Alignment.MiddleCenter
  gv.ReadOnly = on
  gv.MultiSelect = on
  	
  --dotNet.addEventHandler gv "CellPainting" CellPainting
  
  dotNet.addEventHandler gv "CellFormatting" CellFormatting
  dotNet.addEventHandler gv "ColumnAdded" updateGridView
  dotNet.addEventHandler gv "ColumnRemoved" updateGridView
  dotNet.addEventHandler gv "RowsAdded" updateGridView
  dotNet.addEventHandler gv "RowsRemoved" updateGridView
  dotNet.addEventHandler gv "CellClick" CellClick
  
  gv.Dock = gv.Dock.Fill
  
  gv.RowTemplate.Height = 128
  gv.AutoSize = on
  	
  gv.AutoSizeColumnsMode = gv.AutoSizeColumnsMode.Fill
  --gv.AutoSizeRowsMode = gv.AutoSizeRowsMode.AllCells
  gv.AutoSizeRowsMode = gv.AutoSizeRowsMode.None
  gv.RowHeadersWidthSizeMode = gv.RowHeadersWidthSizeMode.EnableResizing
  	
  for k=1 to 4 do gv.columns.add (bc.clone())
  
  gv.RowCount = 251
  
  gv.ColumnHeadersVisible = gv.ShowEditingIcon = gv.RowHeadersVisible = off	
  gv.AllowUserToaddRows = gv.AllowUserToDeleteRows = gv.AllowUserToResizeColumns = off
  gv.AllowUserToResizeRows = on
  
  form.controls.addrange #(gv, delr, addr, delc, addc)
  
  form.showmodeless()
  
  
 the viewer shows [b]1000 GIF images[/b] from MAX 2010  .[b].\\ui\\Ribbon\\Tooltips\\Images\\[/b] directory.



 [b]Merry Christmas and Happy New Year all you guys![/b]
 
 denisT
 [b][]( http://www.google.com/search?q=merry+christmas&hl=en&client=firefox-a&hs=vI9&sa=X&rls=org.mozilla:en-US:official&prmd=ivnsub&source=univ&tbs=nws:1&tbo=u&ei=sD8STbb_JYKglAf7wfC_DA&oi=news_group&ct=title&resnum=1&ved=0CD4QqAIwAA) [/b]
28 Replies

Works good. Good job.

Wow, that’s a thing of great beauty. Nice work Denis.

Whilst I cannot trump that, I wanted to post a dotnet class that I use for testing Managedservices.MaxscriptSDK output from a dotnet class library. I have found it useful to preview the code that gets sent to 3dsmax from the dotnet assembly, as the syntax can sometimes catch you out if you are trying to embed variables into the code string.

C# version –

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using ManagedServices.MaxscriptSDK;
using System.Windows.Forms;

namespace Integration
{
	public class MaxScriptOps
	{
		public void Execute(string ExecuteString, bool TestMode)
		{
			if (TestMode) {
				MessageBox.Show("Execute (" + Strings.Chr(34) + ExecuteString + Strings.Chr(34) + ")");
			} else {
				ExecuteMaxscriptCommand("Execute (" + Strings.Chr(34) + ExecuteString + Strings.Chr(34) + ")");
			}
		}

		public void PrintToListener(string caption, string text, bool TestMode)
		{
			if (TestMode) {
				MessageBox.Show("Print @" + Strings.Chr(34) + caption + " - " + text + Strings.Chr(34) + "% - %\
");
			} else {
				ExecuteMaxscriptCommand("Print @" + Strings.Chr(34) + caption + " - " + text + Strings.Chr(34) + "% - %\
");
			}
		}

		public void FormatToListener(string caption, string text, bool TestMode)
		{
			if (TestMode) {
				MessageBox.Show("Format" + Strings.Chr(34) + "% - %\
" + Strings.Chr(34) + " " + Strings.Chr(34) + caption + Strings.Chr(34) + " " + Strings.Chr(34) + text + Strings.Chr(34));
			} else {
				ExecuteMaxscriptCommand("Format" + Strings.Chr(34) + "% - %\
" + Strings.Chr(34) + " " + Strings.Chr(34) + caption + Strings.Chr(34) + " " + Strings.Chr(34) + text + Strings.Chr(34));
			}
		}
	}
}

vb version –

Imports ManagedServices.MaxscriptSDK
Imports System.Windows.Forms

Namespace Integration
    Public Class MaxScriptOps
        Public Sub Execute(ByVal ExecuteString As String, ByVal TestMode As Boolean)
            If TestMode Then
                MessageBox.Show("Execute (" & Chr(34) & ExecuteString & Chr(34) & ")")
            Else
                ExecuteMaxscriptCommand("Execute (" & Chr(34) & ExecuteString & Chr(34) & ")")
            End If
        End Sub

        Public Sub PrintToListener(ByVal caption As String, ByVal text As String, ByVal TestMode As Boolean)
            If TestMode Then
                MessageBox.Show("Print @" & Chr(34) & caption & " - " & text & Chr(34) & "% - %
")
            Else
                ExecuteMaxscriptCommand("Print @" & Chr(34) & caption & " - " & text & Chr(34) & "% - %
")
            End If
        End Sub

        Public Sub FormatToListener(ByVal caption As String, ByVal text As String, ByVal TestMode As Boolean)
            If TestMode Then
                MessageBox.Show("Format" & Chr(34) & "% - %
" & Chr(34) & " " & Chr(34) & caption & Chr(34) & " " & Chr(34) & text & Chr(34))
            Else
                ExecuteMaxscriptCommand("Format" & Chr(34) & "% - %
" & Chr(34) & " " & Chr(34) & caption & Chr(34) & " " & Chr(34) & text & Chr(34))
            End If
        End Sub
    End Class
End Namespace

And this is a dotnet class to perform Rendering and Viewport capture from a dotnet assembly. I use it in Rig Studio to retrieve the render or view capture from max into my usercontrol.

c# version


using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class RenderOps
{

	private Size _GetMaxRenderResolution;
	public Size MaxRenderResolution {
		get { return _GetMaxRenderResolution; }
		set { _GetMaxRenderResolution = value; }
	}

	public RenderOps()
	{
		ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("Fn LR_RenderRigselectorBackground captureVpt usecustombg custombgcolor_R custombgcolor_G custombgcolor_B savealpha = ;" + "(Local ViewCap=undefined;pngio.setAlpha savealpha;local cv = getViewSize();local ratio;" + "case of ;" + "( ;" + "(cv.x > cv.y):(ratio = cv.y/cv.x);" + "(cv.x = cv.y):(ratio = 1));" + "if not captureVpt then;" + "(if usecustombg then(local tempBGcol = backgroundColor;" + "backgroundColor = color custombgcolor_R custombgcolor_G custombgcolor_B;" + "viewcap  = render progressbar:on vfb:off;" + "backgroundColor =tempBGcol);" + "else viewcap = render vfb:off progressbar:on);" + "else;" + "(VptDib =gw.getViewportDib();" + "ViewCap = bitmap renderwidth renderheight color:white;" + "ViewportRatio = VptDib.width/VptDib.height as float;" + "RenderRatio = renderwidth/renderheight as float;" + "case of((ViewportRatio <= RenderRatio):(;" + "CapturetoRenderHeightRatio =VptDib.width/RenderRatio as float;" + "TopEdge = ((VptDib.Height-CapturetoRenderHeightRatio)/ 2) as integer;" + "FullViewcap = bitmap vptdib.width CapturetoRenderHeightRatio color:white;" + "pasteBitmap VptDib FullViewcap (box2 0 TopEdge VptDib.width VptDib.height) [0,0];" + "Copy FullViewcap ViewCap);" + "(ViewportRatio > RenderRatio):(CapturetoRenderHeightRatio =VptDib.height*RenderRatio as float;" + "LeftEdge = ((VptDib.width-CapturetoRenderHeightRatio)/ 2) as integer;" + "FullViewcap = bitmap CapturetoRenderHeightRatio VptDib.height color:white;" + "pasteBitmap VptDib FullViewcap (box2 LeftEdge 0 VptDib.width VptDib.height) [0,0];" + "Copy FullViewcap ViewCap);" + "default:());" + "close VptDib);" + "if viewcap != undefined then (setclipboardbitmap viewcap;close ViewCap;return true)else(return false))");

		this.MaxRenderResolution = StoreCurrentResolution();

	}

	public bool Render(Color BackgroundColor)
	{
		try {
			return ManagedServices.MaxscriptSDK.ExecuteBooleanMaxscriptQuery("LR_RenderRigselectorBackground False True " + BackgroundColor.R.ToString() + " " + BackgroundColor.G.ToString() + " " + BackgroundColor.B.ToString() + " True");
		} catch (Exception ex) {
			return false;
		}
	}

	public bool Capture(Size ImageSize)
	{
		try {
			return ManagedServices.MaxscriptSDK.ExecuteBooleanMaxscriptQuery("LR_RenderRigselectorBackground True True 0 0 0 True");
		} catch (Exception ex) {
			return false;
		}
	}

	public object StoreCurrentResolution()
	{
		int renderwidth = ManagedServices.MaxscriptSDK.ExecuteIntMaxscriptQuery("RenderWidth");
		int renderheight = ManagedServices.MaxscriptSDK.ExecuteIntMaxscriptQuery("RenderHeight");
		Size RenderResolution = new Size(renderwidth, renderheight);
		return RenderResolution;
	}

	public bool SetMaxRenderResolution(Size DialogSize)
	{
		try {
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("If renderSceneDialog.isOpen() Then renderSceneDialog.close()");
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderHeight = " + DialogSize.Height.ToString());
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderWidth = " + DialogSize.Width.ToString());
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("renderSceneDialog.Open()");
			return true;
		} catch (Exception ex) {
			return false;
		}
	}

	public bool RestoreMaxRenderResolution()
	{
		try {
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("If renderSceneDialog.isOpen() Then renderSceneDialog.close()");
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderHeight = " + this.MaxRenderResolution.Height.ToString());
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderWidth = " + this.MaxRenderResolution.Width.ToString());
			ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("renderSceneDialog.Open()");
			return true;
		} catch (Exception ex) {
			return false;
		}
	}
}

vb version

Public Class RenderOps

    Private _GetMaxRenderResolution As Size
    Public Property MaxRenderResolution() As Size
        Get
            Return _GetMaxRenderResolution
        End Get
        Set(ByVal value As Size)
            _GetMaxRenderResolution = value
        End Set
    End Property

    Public Sub New()
        ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand _
            ("Fn LR_RenderRigselectorBackground captureVpt usecustombg custombgcolor_R custombgcolor_G custombgcolor_B savealpha = ;" & _
            "(Local ViewCap=undefined;pngio.setAlpha savealpha;local cv = getViewSize();local ratio;" & _
            "case of ;" & _
            "( ;" & _
            "(cv.x > cv.y):(ratio = cv.y/cv.x);" & _
            "(cv.x = cv.y):(ratio = 1));" & _
             "if not captureVpt then;" & _
             "(if usecustombg then(local tempBGcol = backgroundColor;" & _
              "backgroundColor = color custombgcolor_R custombgcolor_G custombgcolor_B;" & _
              "viewcap  = render progressbar:on vfb:off;" & _
              "backgroundColor =tempBGcol);" & _
              "else viewcap = render vfb:off progressbar:on);" & _
              "else;" & _
               "(VptDib =gw.getViewportDib();" & _
                "ViewCap = bitmap renderwidth renderheight color:white;" & _
                "ViewportRatio = VptDib.width/VptDib.height as float;" & _
                "RenderRatio = renderwidth/renderheight as float;" & _
                "case of((ViewportRatio <= RenderRatio):(;" & _
                "CapturetoRenderHeightRatio =VptDib.width/RenderRatio as float;" & _
                "TopEdge = ((VptDib.Height-CapturetoRenderHeightRatio)/ 2) as integer;" & _
                "FullViewcap = bitmap vptdib.width CapturetoRenderHeightRatio color:white;" & _
                "pasteBitmap VptDib FullViewcap (box2 0 TopEdge VptDib.width VptDib.height) [0,0];" & _
                "Copy FullViewcap ViewCap);" & _
                "(ViewportRatio > RenderRatio):(CapturetoRenderHeightRatio =VptDib.height*RenderRatio as float;" & _
                "LeftEdge = ((VptDib.width-CapturetoRenderHeightRatio)/ 2) as integer;" & _
                "FullViewcap = bitmap CapturetoRenderHeightRatio VptDib.height color:white;" & _
                "pasteBitmap VptDib FullViewcap (box2 LeftEdge 0 VptDib.width VptDib.height) [0,0];" & _
                "Copy FullViewcap ViewCap);" & _
                "default:());" & _
                "close VptDib);" & _
                "if viewcap != undefined then (setclipboardbitmap viewcap;close ViewCap;return true)else(return false))")

        Me.MaxRenderResolution = StoreCurrentResolution()

    End Sub

    Public Function Render(ByVal BackgroundColor As Color) As Boolean
        Try
            Return ManagedServices.MaxscriptSDK.ExecuteBooleanMaxscriptQuery("LR_RenderRigselectorBackground False True " & BackgroundColor.R.ToString() & " " & BackgroundColor.G.ToString() & " " & BackgroundColor.B.ToString() & " True")
        Catch ex As Exception
            Return False
        End Try
    End Function

    Public Function Capture(ByVal ImageSize As Size) As Boolean
        Try
            Return ManagedServices.MaxscriptSDK.ExecuteBooleanMaxscriptQuery("LR_RenderRigselectorBackground True True 0 0 0 True")
        Catch ex As Exception
            Return False
        End Try
    End Function

    Public Function StoreCurrentResolution()
        Dim renderwidth As Integer = ManagedServices.MaxscriptSDK.ExecuteIntMaxscriptQuery("RenderWidth")
        Dim renderheight As Integer = ManagedServices.MaxscriptSDK.ExecuteIntMaxscriptQuery("RenderHeight")
        Dim RenderResolution As Size = New Size(renderwidth, renderheight)
        Return RenderResolution
    End Function

    Public Function SetMaxRenderResolution(ByVal DialogSize As Size) As Boolean
        Try
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("If renderSceneDialog.isOpen() Then renderSceneDialog.close()")
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderHeight = " & DialogSize.Height.ToString())
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderWidth = " & DialogSize.Width.ToString())
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("renderSceneDialog.Open()")
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function

    Public Function RestoreMaxRenderResolution() As Boolean
        Try
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("If renderSceneDialog.isOpen() Then renderSceneDialog.close()")
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderHeight = " & Me.MaxRenderResolution.Height.ToString())
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("RenderWidth = " & Me.MaxRenderResolution.Width.ToString())
            ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("renderSceneDialog.Open()")
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function
End Class

I also echo Denis’s festive cheer. Happy Xmas everyone. Remember, christmas is not just about giving, sharing and being with family and friends. It’s equally about getting pissed up and falling over.

Dang dude… that’s awesome! Very smooth results you have going on there… fast loading too, and I love the resizing of the thumbs as u resize the window and whatnot.

Going to have to look at this more closely now

Thanks!

 lo1

Very impressive! Sharing the C# code really allows me to learn a lot from it.

I have a couple of questions about the assembly:

  1. Are there any benefits to compiling in realtime other than the comfort of not having to distribute a DLL with your script and easier development? For the end user, would a precompiled DLL run faster?

  2. Is it necessary to be using it within a dotnet form? Could you use it in a max rollout as a dotNetControl UI item, or if necessary, as a child control of a dotnet panel implemented as a dotNetControl UI item?

Actually you’ve answered your question yourself. I’m using on-fly compiling just to make the code more transparent and easier for distribution. Also it helps me to debug the code because I don’t have to unload DLL every time to check a changes.

For the end user, would a precompiled DLL run faster?

No. Preloaded or precompliled DLLs have to work exactly same. Some difference might take a place because the compilers themselves are different a bit.

Is it necessary to be using it within a dotnet form? Could you use it in a max rollout as a dotNetControl UI item?

I didn’t modify standard DataGridView control. So you can use dotnetcontrol for it in standart MAX dialog. I use dotnet Forms usually in situation where the dialog and its children needs scaling.

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

Posts: 0

I should have phrased my question differently. I intended to ask, would it not be more reasonable to use a precompiled DLL with a finalized tool to save the on-the-fly compilation time, or would you consider the time difference negligible since the C# code is relatively small in this case?

(@denist)
Joined: 11 months ago

Posts: 0

If we talking about script loading time the loading with assembly compiling is slower. But I prefer to use on-fly compiling for small asssemblies any way. I put them in stdplugs/stdscripts and compile them all on MAX loading. Compare to max loading time it takes nothing.

 lo1

I checked, and the compilation of the assembly only takes about 70ms or so. I’d expected it to be heavier for some reason.

I hope you don’t mind, I modified your code a bit so the column number would be recalculated based on a threshold (maxCellWidth variable) whenever the control is resized, the images don’t loop infinitely, embedded it in a Maxscript rollout and made some other cosmetic modifications to my liking. Not really an innovation, but wrapped up to a more useful state for my current needs. Here is the code, in case anyone finds it useful. Thanks again for sharing this code. Happy holidays.

global DGV_Icons
fn getGIFFiles = if DGV_Icons == undefined or true do
(
	local path = (getDir #ui) + "Icons\\"
	local files = getFiles (path + "*.bmp")
	DGV_Icons = for f in files collect 
	(
		local bmp = dotNetObject "System.Drawing.Bitmap" f
		bmp.tag = f
		bmp
	)
)
getGIFFiles()

global DataGridViewExtensionAssembly
fn CreateDataGridViewExtensionAssembly forceRecompile:on =
(
	if forceRecompile or not iskindof ::DataGridViewExtensionAssembly dotnetobject or (::DataGridViewExtensionAssembly.GetType()).name != "Assembly" do
	(
		source = ""
		source += "using System;
"
		source += "using System.Reflection;
"
		source += "using System.Runtime.InteropServices;
"
		source += "using System.Drawing;
"
		source += "using System.Windows.Forms;
"
		source += "namespace DataGridViewExtension
"
		source += "{
"
		source += "	public class Style
"
		source += "	{
"
		source += "		public void SetStyle(Control control, ControlStyles styles, bool newValue)
"
		source += "		{
"
		source += "			object[] args = { styles, newValue };
"
		source += "			typeof(Control).InvokeMember(\"SetStyle\",
"
		source += "					BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
"
		source += "					null, control, args);
"
		source += "		}
"
		source += "		public bool SetSelectable(Control control, bool newValue)
"
		source += "		{
"
		source += "			SetStyle(control, ControlStyles.Selectable, newValue);
"
		source += "			return newValue;
"
		source += "		}
"
		source += "		public void SetDoubleBuffer(Control control)
"
		source += "		{
"
		source += "			SetStyle(control, ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
"
		source += "		}
"
		source += "	}
"
		source += "	public class ImageTextCellColumn : DataGridViewImageColumn
"
		source += "	{
"
		source += "		private Boolean showLabel;
"
		source += "		private String label;
"
		source += "		private ContentAlignment labelAlign;
"
		source += "		private Color labelBackColor;
"
		source += "		private Color labelForeColor;
"
		source += "		public ImageTextCellColumn()
"
		source += "		{
"
		source += "			this.ShowLabel = true;
"
		source += "			this.LabelForeColor = Color.White;
"
		source += "			this.LabelBackColor = Color.FromArgb(100, Color.Black);
"
		source += "			this.CellTemplate = new ImageTextCell();
"
		source += "		}
"
		source += "		public override object Clone()
"
		source += "		{
"
		source += "			ImageTextCellColumn c = base.Clone() as ImageTextCellColumn;
"
		source += "			c.ShowLabel = this.showLabel;
"
		source += "			c.Label = this.label;
"
		source += "			c.LabelAlign = this.labelAlign;
"
		source += "			c.LabelForeColor = this.labelForeColor;
"
		source += "			c.LabelBackColor = this.labelBackColor;
"
		source += "			return c;
"
		source += "		}
"
		source += "		private ImageTextCell ImageTextCellTemplate
"
		source += "		{
"
		source += "			get { return this.CellTemplate as ImageTextCell; }
"
		source += "		}
"
		source += "		public Boolean ShowLabel
"
		source += "		{
"
		source += "			get { return this.showLabel; }
"
		source += "			set { this.showLabel = value; }
"
		source += "		}
"
		source += "		public String Label
"
		source += "		{
"
		source += "			get { return this.label; }
"
		source += "			set { this.label = value; }
"
		source += "		}
"
		source += "		public ContentAlignment LabelAlign
"
		source += "		{
"
		source += "			get { return this.labelAlign; }
"
		source += "			set { this.labelAlign = value; }
"
		source += "		}
"
		source += "		public Color LabelForeColor
"
		source += "		{
"
		source += "			get { return this.labelForeColor; }
"
		source += "			set { this.labelForeColor = value; }
"
		source += "		}
"
		source += "		public Color LabelBackColor
"
		source += "		{
"
		source += "			get { return this.labelBackColor; }
"
		source += "			set { this.labelBackColor = value; }
"
		source += "		}
"
		source += "	}
"
		source += "	public class ImageTextCell : DataGridViewImageCell
"
		source += "	{
"
		source += "		private Boolean showLabel;
"
		source += "		private String label;
"
		source += "		private Color labelBackColor;
"
		source += "		private Color labelForeColor;
"
		source += "		public ImageTextCell()
"
		source += "		{
"
		source += "			this.ShowLabel = true;
"
		source += "		}
"
		source += "		public override object Clone()
"
		source += "		{
"
		source += "			ImageTextCell c = base.Clone() as ImageTextCell;
"
		source += "			c.ShowLabel = this.showLabel;
"
		source += "			c.Label = this.label;
"
		source += "			c.LabelForeColor = this.labelForeColor;
"
		source += "			c.LabelBackColor = this.labelBackColor;
"
		source += "			return c;
"
		source += "		}
"
		source += "		public Boolean ShowLabel
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return showLabel; }
"
		source += "				else return (this.showLabel & this.ImageTextCellColumn.ShowLabel);
"
		source += "			}
"
		source += "			set { if (this.showLabel != value) { this.showLabel = value; } }
"
		source += "		}
"
		source += "		public String Label
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return label; }
"
		source += "				else if (this.label != null)
"
		source += "				{
"
		source += "					return this.label;
"
		source += "				}
"
		source += "				else
"
		source += "				{
"
		source += "					return this.ImageTextCellColumn.Label;
"
		source += "				}
"
		source += "			}
"
		source += "			set { if (this.label != value) { this.label = value; } }
"
		source += "		}
"
		source += "		public Color LabelForeColor
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return labelForeColor; }
"
		source += "				else if (this.labelForeColor != Color.Empty)
"
		source += "				{
"
		source += "					return this.labelForeColor;
"
		source += "				}
"
		source += "				else
"
		source += "				{
"
		source += "					return this.ImageTextCellColumn.LabelForeColor;
"
		source += "				}
"
		source += "			}
"
		source += "			set { if (this.labelForeColor != value) { this.labelForeColor = value; } }
"
		source += "		}
"
		source += "		public Color LabelBackColor
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return labelBackColor; }
"
		source += "				else if (this.labelBackColor != Color.Empty)
"
		source += "				{
"
		source += "					return this.labelBackColor;
"
		source += "				}
"
		source += "				else
"
		source += "				{
"
		source += "					return this.ImageTextCellColumn.LabelBackColor;
"
		source += "				}
"
		source += "			}
"
		source += "			set { if (this.labelBackColor != value) { this.labelBackColor = value; } }
"
		source += "		}
"
		source += "		protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
"
		source += "			DataGridViewElementStates cellState, object value, object formattedValue, string errorText,
"
		source += "			DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
"
		source += "		{
"
		source += "			// Paint the base content
"
		source += "			base.Paint(graphics, clipBounds, cellBounds, rowIndex,
"
		source += "				cellState, value, formattedValue, errorText,
"
		source += "				cellStyle, advancedBorderStyle, paintParts);
"
		source += "			if (this.ShowLabel && this.Label != null)
"
		source += "			{
"
		source += "				// Draw the image clipped to the cell.
"
		source += "				System.Drawing.Drawing2D.GraphicsContainer container = graphics.BeginContainer();
"
		source += "				SizeF ss = TextRenderer.MeasureText(this.Label, cellStyle.Font);
"
		source += "				ss = SizeF.Add(ss, new SizeF(0, 2));
"
		source += "				Single px = cellBounds.X;
"
		source += "				Single tx, py;
"
		source += "				switch (this.ImageTextCellColumn.LabelAlign)
"
		source += "				{
"
		source += "					case ContentAlignment.BottomCenter:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.MiddleCenter:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) / 2 + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.TopCenter:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.TopLeft:
"
		source += "						{
"
		source += "							tx = px;
"
		source += "							py = cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.BottomRight:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					default:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "				}
"
		source += "				Rectangle rect = new Rectangle((int)px, (int)py, (int)(cellBounds.Width-1), (int)ss.Height);
"
		source += "				graphics.SetClip(rect);
"
		source += "				graphics.FillRectangle(new SolidBrush(this.LabelBackColor), rect);
"
		source += "				graphics.DrawString(this.Label, cellStyle.Font, new SolidBrush(this.LabelForeColor), tx, py);
"
		source += "				graphics.EndContainer(container);
"
		source += "			}
"
		source += "		}
"
		source += "		public ImageTextCellColumn ImageTextCellColumn
"
		source += "		{
"
		source += "			get { return this.OwningColumn as ImageTextCellColumn; }
"
		source += "		}
"
		source += "	}
"
		source += "}
"
		
		local compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"  
		compilerParams.ReferencedAssemblies.AddRange #("System.dll","System.Windows.Forms.dll","System.Drawing.dll");  
		compilerParams.GenerateInMemory = true
		local compilerResults = (dotnetobject "Microsoft.CSharp.CSharpCodeProvider").CompileAssemblyFromSource compilerParams #(source)
		
		if (compilerResults.Errors.Count > 0 ) then
		(
			local errs = stringstream ""
			for i = 0 to (compilerResults.Errors.Count-1) do
			(
				local err = compilerResults.Errors.Item[i]
				format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs 
			)
			MessageBox (errs as string) title: "Errors encountered while compiling C# code"
			format "%
" errs
			undefined
		)
		else
		(
			DataGridViewExtensionAssembly = compilerResults.CompiledAssembly
		)
	)
)
CreateDataGridViewExtensionAssembly forceRecompile:on

fn initializeGridView =
(
	global maxCellWidth=150
	global gv = dotnetobject "DataGridView"
	
	local cc = DataGridViewExtensionAssembly.CreateInstance "DataGridViewExtension.Style"
	cc.SetDoubleBuffer gv
	
	local font = gv.font 
	gv.font = dotNetObject "System.Drawing.Font" font.FontFamily font.Size font.style.Bold
	
	global bc = DataGridViewExtensionAssembly.CreateInstance "DataGridViewExtension.ImageTextCellColumn"
	bc.LabelBackColor = (dotnetclass "System.Drawing.Color").FromARGB 255 (dotnetclass "System.Drawing.Color").Lime
	bc.LabelForeColor = (dotnetclass "System.Drawing.Color").FromARGB 255 (dotnetclass "System.Drawing.Color").Black
	bc.LabelAlign = bc.LabelAlign.BottomCenter
  
	local p = dotnetobject "System.Windows.Forms.Padding" 2
	p.Bottom = 16
	bc.DefaultCellStyle.Padding = p
	bc.ImageLayout = bc.ImageLayout.Normal
	bc.DefaultCellStyle.BackColor = bc.DefaultCellStyle.BackColor.Gray 
	bc.DefaultCellStyle.nullValue = undefined
	
	dotNet.addEventHandler gv "CellFormatting" CellFormatting
	dotNet.addEventHandler gv "SelectionChanged" CellSelectionChanged		
)

fn reAdjustColumns =
(
	local ts=timestamp()
	local mem=heapfree
	if (local newColumnCount = amax (gv.width/maxIconWidth) 1) != gv.ColumnCount do	
	(
		gv.SuspendLayout()		
		while newColumnCount > gv.ColumnCount do gv.columns.add (bc.clone())
		gv.ColumnCount = newColumnCount
		gv.RowCount = ceil (DGV_Icons.count as float/newColumnCount)
		gv.ResumeLayout()
	)
	format "Readjust Columns: Time: %ms, Memory: %kb
" (timestamp()-ts) ((mem-heapfree)/1000.0)
)

fn CellSelectionChanged s e = 
(
	format "button: %
" s.selectedCells.item[0].label
)

fn CellFormatting s e =
(
	local c = e.rowindex*s.ColumnCount + e.ColumnIndex + 1
	local cell = s.rows.item[e.rowindex].cells.item[e.columnindex]
	if c <= DGV_Icons.count then
	(
		local bmp = DGV_Icons[c]		
		cell.ImageLayout = if cell.Size.width < bmp.width or cell.Size.height < bmp.height then cell.ImageLayout.Zoom	else cell.ImageLayout.Normal
		cell.ShowLabel = cell.ImageTextCellColumn.ShowLabel
		e.value = bmp
		cell.Description = cell.ToolTipText = bmp.tag
		cell.Label = c as string + " - " + (getfilenamefile bmp.tag)
	)
	else
	(
		e.value = undefined
		cell.Description = cell.ToolTipText = ""
		cell.ShowLabel = off
	)
)

try(destroyDialog denisTImageViewer)catch()
rollout denisTImageViewer "test" 
(
	dotNetControl panel "System.Windows.Forms.Panel" pos:[0,0]
	
	on denisTImageViewer open do
	(
		panel.width = denisTImageViewer.width
		panel.height = denisTImageViewer.height
		initializeGridView()		
		local numCols = panel.width/maxCellWidth
		for k=1 to numCols do gv.columns.add (bc.clone())		
		gv.ColumnHeadersDefaultCellStyle.Alignment = gv.ColumnHeadersDefaultCellStyle.Alignment.MiddleCenter
		gv.ColumnHeadersVisible = gv.ShowEditingIcon = gv.RowHeadersVisible = gv.MultiSelect = off	
		gv.AllowUserToaddRows = gv.AllowUserToDeleteRows = gv.AllowUserToResizeColumns = off
		gv.AllowUserToResizeRows = gv.ReadOnly = gv.AutoSize = on
		gv.Dock = gv.Dock.Fill  
		gv.RowTemplate.Height = 128
		gv.AutoSizeColumnsMode = gv.AutoSizeColumnsMode.Fill
		gv.AutoSizeRowsMode = gv.AutoSizeRowsMode.None
		gv.RowHeadersWidthSizeMode = gv.RowHeadersWidthSizeMode.EnableResizing
		gv.RowCount = ((DGV_Icons.count)/numCols)
		gv.GridColor=gv.Gridcolor.black
		panel.controls.add gv
	)
	
	on denisTImageViewer resized val do
	(
		panel.width=val[1]
		panel.height=val[2]
		reAdjustColumns()
	)
)
createDialog denisTImageViewer style:#(#style_titlebar, #style_border, #style_sysmenu,#style_resizing) width:600 height:400

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

My assemblies are much more heavier. I have 5 basic assemblies: Window, Control, Mouse, File, and FormsExtension. It takes ~1sec to compile them.

I hope you don’t mind, I modified your code…
…made some other cosmetic modifications to my liking.

That’s exactly what I want to see. I just try to show (with your guys help) how picked right .NET control might be easy adjusted to fit any needs.

Very cool updates

I get an error however when I try to resize the window

--  Frame:
 --   val: [600,400]
 >> MAXScript Rollout Handler Exception: -- Incompatible types: 600, and undefined <<

if (local newColumnCount = amax (gv.width/maxIconWidth) 1) != gv.ColumnCount do	

Also, this is the same question I had for another recent thumbnail viewer, but would it be possible/easy enough to add .TGA/.DDS/.PSD support?

Thanks!

 lo1

Woops, my bad, sorry. Below is corrected code.
About the other file formats, I don’t suppose this would support them as it is using the system.drawing.bitmap class, but you can easily do what lonerobot’s acclaimed Hitchhiker does, and use the clipboard to get those types of images. Other possible solutions would be to use a 3rd party DLL to read those formats, which while I’m sure they exist, I don’t know any of those.

global DGV_Icons
fn getGIFFiles = if DGV_Icons == undefined or true do
(
	local path = (getDir #ui) + "Icons\\"
	local files = getFiles (path + "*.bmp")
	DGV_Icons = for f in files collect 
	(
		local bmp = dotNetObject "System.Drawing.Bitmap" f
		bmp.tag = f
		bmp
	)
)
getGIFFiles()

global DataGridViewExtensionAssembly
fn CreateDataGridViewExtensionAssembly forceRecompile:on =
(
	if forceRecompile or not iskindof ::DataGridViewExtensionAssembly dotnetobject or (::DataGridViewExtensionAssembly.GetType()).name != "Assembly" do
	(
		source = ""
		source += "using System;
"
		source += "using System.Reflection;
"
		source += "using System.Runtime.InteropServices;
"
		source += "using System.Drawing;
"
		source += "using System.Windows.Forms;
"
		source += "namespace DataGridViewExtension
"
		source += "{
"
		source += "	public class Style
"
		source += "	{
"
		source += "		public void SetStyle(Control control, ControlStyles styles, bool newValue)
"
		source += "		{
"
		source += "			object[] args = { styles, newValue };
"
		source += "			typeof(Control).InvokeMember(\"SetStyle\",
"
		source += "					BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
"
		source += "					null, control, args);
"
		source += "		}
"
		source += "		public bool SetSelectable(Control control, bool newValue)
"
		source += "		{
"
		source += "			SetStyle(control, ControlStyles.Selectable, newValue);
"
		source += "			return newValue;
"
		source += "		}
"
		source += "		public void SetDoubleBuffer(Control control)
"
		source += "		{
"
		source += "			SetStyle(control, ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
"
		source += "		}
"
		source += "	}
"
		source += "	public class ImageTextCellColumn : DataGridViewImageColumn
"
		source += "	{
"
		source += "		private Boolean showLabel;
"
		source += "		private String label;
"
		source += "		private ContentAlignment labelAlign;
"
		source += "		private Color labelBackColor;
"
		source += "		private Color labelForeColor;
"
		source += "		public ImageTextCellColumn()
"
		source += "		{
"
		source += "			this.ShowLabel = true;
"
		source += "			this.LabelForeColor = Color.White;
"
		source += "			this.LabelBackColor = Color.FromArgb(100, Color.Black);
"
		source += "			this.CellTemplate = new ImageTextCell();
"
		source += "		}
"
		source += "		public override object Clone()
"
		source += "		{
"
		source += "			ImageTextCellColumn c = base.Clone() as ImageTextCellColumn;
"
		source += "			c.ShowLabel = this.showLabel;
"
		source += "			c.Label = this.label;
"
		source += "			c.LabelAlign = this.labelAlign;
"
		source += "			c.LabelForeColor = this.labelForeColor;
"
		source += "			c.LabelBackColor = this.labelBackColor;
"
		source += "			return c;
"
		source += "		}
"
		source += "		private ImageTextCell ImageTextCellTemplate
"
		source += "		{
"
		source += "			get { return this.CellTemplate as ImageTextCell; }
"
		source += "		}
"
		source += "		public Boolean ShowLabel
"
		source += "		{
"
		source += "			get { return this.showLabel; }
"
		source += "			set { this.showLabel = value; }
"
		source += "		}
"
		source += "		public String Label
"
		source += "		{
"
		source += "			get { return this.label; }
"
		source += "			set { this.label = value; }
"
		source += "		}
"
		source += "		public ContentAlignment LabelAlign
"
		source += "		{
"
		source += "			get { return this.labelAlign; }
"
		source += "			set { this.labelAlign = value; }
"
		source += "		}
"
		source += "		public Color LabelForeColor
"
		source += "		{
"
		source += "			get { return this.labelForeColor; }
"
		source += "			set { this.labelForeColor = value; }
"
		source += "		}
"
		source += "		public Color LabelBackColor
"
		source += "		{
"
		source += "			get { return this.labelBackColor; }
"
		source += "			set { this.labelBackColor = value; }
"
		source += "		}
"
		source += "	}
"
		source += "	public class ImageTextCell : DataGridViewImageCell
"
		source += "	{
"
		source += "		private Boolean showLabel;
"
		source += "		private String label;
"
		source += "		private Color labelBackColor;
"
		source += "		private Color labelForeColor;
"
		source += "		public ImageTextCell()
"
		source += "		{
"
		source += "			this.ShowLabel = true;
"
		source += "		}
"
		source += "		public override object Clone()
"
		source += "		{
"
		source += "			ImageTextCell c = base.Clone() as ImageTextCell;
"
		source += "			c.ShowLabel = this.showLabel;
"
		source += "			c.Label = this.label;
"
		source += "			c.LabelForeColor = this.labelForeColor;
"
		source += "			c.LabelBackColor = this.labelBackColor;
"
		source += "			return c;
"
		source += "		}
"
		source += "		public Boolean ShowLabel
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return showLabel; }
"
		source += "				else return (this.showLabel & this.ImageTextCellColumn.ShowLabel);
"
		source += "			}
"
		source += "			set { if (this.showLabel != value) { this.showLabel = value; } }
"
		source += "		}
"
		source += "		public String Label
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return label; }
"
		source += "				else if (this.label != null)
"
		source += "				{
"
		source += "					return this.label;
"
		source += "				}
"
		source += "				else
"
		source += "				{
"
		source += "					return this.ImageTextCellColumn.Label;
"
		source += "				}
"
		source += "			}
"
		source += "			set { if (this.label != value) { this.label = value; } }
"
		source += "		}
"
		source += "		public Color LabelForeColor
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return labelForeColor; }
"
		source += "				else if (this.labelForeColor != Color.Empty)
"
		source += "				{
"
		source += "					return this.labelForeColor;
"
		source += "				}
"
		source += "				else
"
		source += "				{
"
		source += "					return this.ImageTextCellColumn.LabelForeColor;
"
		source += "				}
"
		source += "			}
"
		source += "			set { if (this.labelForeColor != value) { this.labelForeColor = value; } }
"
		source += "		}
"
		source += "		public Color LabelBackColor
"
		source += "		{
"
		source += "			get
"
		source += "			{
"
		source += "				if (this.OwningColumn == null || this.ImageTextCellColumn == null) { return labelBackColor; }
"
		source += "				else if (this.labelBackColor != Color.Empty)
"
		source += "				{
"
		source += "					return this.labelBackColor;
"
		source += "				}
"
		source += "				else
"
		source += "				{
"
		source += "					return this.ImageTextCellColumn.LabelBackColor;
"
		source += "				}
"
		source += "			}
"
		source += "			set { if (this.labelBackColor != value) { this.labelBackColor = value; } }
"
		source += "		}
"
		source += "		protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
"
		source += "			DataGridViewElementStates cellState, object value, object formattedValue, string errorText,
"
		source += "			DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
"
		source += "		{
"
		source += "			// Paint the base content
"
		source += "			base.Paint(graphics, clipBounds, cellBounds, rowIndex,
"
		source += "				cellState, value, formattedValue, errorText,
"
		source += "				cellStyle, advancedBorderStyle, paintParts);
"
		source += "			if (this.ShowLabel && this.Label != null)
"
		source += "			{
"
		source += "				// Draw the image clipped to the cell.
"
		source += "				System.Drawing.Drawing2D.GraphicsContainer container = graphics.BeginContainer();
"
		source += "				SizeF ss = TextRenderer.MeasureText(this.Label, cellStyle.Font);
"
		source += "				ss = SizeF.Add(ss, new SizeF(0, 2));
"
		source += "				Single px = cellBounds.X;
"
		source += "				Single tx, py;
"
		source += "				switch (this.ImageTextCellColumn.LabelAlign)
"
		source += "				{
"
		source += "					case ContentAlignment.BottomCenter:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.MiddleCenter:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) / 2 + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.TopCenter:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.TopLeft:
"
		source += "						{
"
		source += "							tx = px;
"
		source += "							py = cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					case ContentAlignment.BottomRight:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "					default:
"
		source += "						{
"
		source += "							tx = (cellBounds.Width - ss.Width) / 2 + px;
"
		source += "							py = (cellBounds.Height - ss.Height-1) + cellBounds.Y;
"
		source += "							break;
"
		source += "						}
"
		source += "				}
"
		source += "				Rectangle rect = new Rectangle((int)px, (int)py, (int)(cellBounds.Width-1), (int)ss.Height);
"
		source += "				graphics.SetClip(rect);
"
		source += "				graphics.FillRectangle(new SolidBrush(this.LabelBackColor), rect);
"
		source += "				graphics.DrawString(this.Label, cellStyle.Font, new SolidBrush(this.LabelForeColor), tx, py);
"
		source += "				graphics.EndContainer(container);
"
		source += "			}
"
		source += "		}
"
		source += "		public ImageTextCellColumn ImageTextCellColumn
"
		source += "		{
"
		source += "			get { return this.OwningColumn as ImageTextCellColumn; }
"
		source += "		}
"
		source += "	}
"
		source += "}
"
		
		local compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"  
		compilerParams.ReferencedAssemblies.AddRange #("System.dll","System.Windows.Forms.dll","System.Drawing.dll");  
		compilerParams.GenerateInMemory = true
		local compilerResults = (dotnetobject "Microsoft.CSharp.CSharpCodeProvider").CompileAssemblyFromSource compilerParams #(source)
		
		if (compilerResults.Errors.Count > 0 ) then
		(
			local errs = stringstream ""
			for i = 0 to (compilerResults.Errors.Count-1) do
			(
				local err = compilerResults.Errors.Item[i]
				format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs 
			)
			MessageBox (errs as string) title: "Errors encountered while compiling C# code"
			format "%
" errs
			undefined
		)
		else
		(
			DataGridViewExtensionAssembly = compilerResults.CompiledAssembly
		)
	)
)
CreateDataGridViewExtensionAssembly forceRecompile:on

fn initializeGridView =
(
	global maxCellWidth=150
	global gv = dotnetobject "DataGridView"
	
	local cc = DataGridViewExtensionAssembly.CreateInstance "DataGridViewExtension.Style"
	cc.SetDoubleBuffer gv
	
	local font = gv.font 
	gv.font = dotNetObject "System.Drawing.Font" font.FontFamily font.Size font.style.Bold
	
	global bc = DataGridViewExtensionAssembly.CreateInstance "DataGridViewExtension.ImageTextCellColumn"
	bc.LabelBackColor = (dotnetclass "System.Drawing.Color").FromARGB 255 (dotnetclass "System.Drawing.Color").Lime
	bc.LabelForeColor = (dotnetclass "System.Drawing.Color").FromARGB 255 (dotnetclass "System.Drawing.Color").Black
	bc.LabelAlign = bc.LabelAlign.BottomCenter
  
	local p = dotnetobject "System.Windows.Forms.Padding" 2
	p.Bottom = 16
	bc.DefaultCellStyle.Padding = p
	bc.ImageLayout = bc.ImageLayout.Normal
	bc.DefaultCellStyle.BackColor = bc.DefaultCellStyle.BackColor.Gray 
	bc.DefaultCellStyle.nullValue = undefined
)

fn reAdjustColumns =
(
	local ts=timestamp()
	local mem=heapfree
	if (local newColumnCount = amax (gv.width/maxCellWidth) 1) != gv.ColumnCount do	
	(
		gv.SuspendLayout()		
		while newColumnCount > gv.ColumnCount do gv.columns.add (bc.clone())
		gv.ColumnCount = newColumnCount
		gv.RowCount = ceil (DGV_Icons.count as float/newColumnCount)
		gv.ResumeLayout()
	)
	format "Readjust Columns: Time: %ms, Memory: %kb
" (timestamp()-ts) ((mem-heapfree)/1000.0)
)

fn CellSelectionChanged s e = 
(
	format "button: %
" s.selectedCells.item[0].label
)

fn CellFormatting s e =
(
	local c = e.rowindex*s.ColumnCount + e.ColumnIndex + 1
	local cell = s.rows.item[e.rowindex].cells.item[e.columnindex]
	if c <= DGV_Icons.count then
	(
		local bmp = DGV_Icons[c]		
		cell.ImageLayout = if cell.Size.width < bmp.width or cell.Size.height < bmp.height then cell.ImageLayout.Zoom	else cell.ImageLayout.Normal
		cell.ShowLabel = cell.ImageTextCellColumn.ShowLabel
		e.value = bmp
		cell.Description = cell.ToolTipText = bmp.tag
		cell.Label = c as string + " - " + (getfilenamefile bmp.tag)
	)
	else
	(
		e.value = undefined
		cell.Description = cell.ToolTipText = ""
		cell.ShowLabel = off
	)
)

try(destroyDialog denisTImageViewer)catch()
rollout denisTImageViewer "test" 
(
	dotNetControl panel "System.Windows.Forms.Panel" pos:[0,0]
	
	on denisTImageViewer open do
	(
		panel.width = denisTImageViewer.width
		panel.height = denisTImageViewer.height
		initializeGridView()		
		dotNet.addEventHandler gv "CellFormatting" CellFormatting
		dotNet.addEventHandler gv "SelectionChanged" CellSelectionChanged		
		local numCols = panel.width/maxCellWidth
		for k=1 to numCols do gv.columns.add (bc.clone())		
		gv.ColumnHeadersDefaultCellStyle.Alignment = gv.ColumnHeadersDefaultCellStyle.Alignment.MiddleCenter
		gv.ColumnHeadersVisible = gv.ShowEditingIcon = gv.RowHeadersVisible = gv.MultiSelect = off	
		gv.AllowUserToaddRows = gv.AllowUserToDeleteRows = gv.AllowUserToResizeColumns = off
		gv.AllowUserToResizeRows = gv.ReadOnly = gv.AutoSize = on
		gv.Dock = gv.Dock.Fill  
		gv.RowTemplate.Height = 128
		gv.AutoSizeColumnsMode = gv.AutoSizeColumnsMode.Fill
		gv.AutoSizeRowsMode = gv.AutoSizeRowsMode.None
		gv.RowHeadersWidthSizeMode = gv.RowHeadersWidthSizeMode.EnableResizing
		gv.RowCount = ((DGV_Icons.count)/numCols)
		gv.GridColor=gv.Gridcolor.black
		panel.controls.add gv
	)
	
	on denisTImageViewer resized val do
	(
		panel.width=val[1]
		panel.height=val[2]
		reAdjustColumns()
	)
)
createDialog denisTImageViewer style:#(#style_titlebar, #style_border, #style_sysmenu,#style_resizing) width:600 height:400

4 Replies
(@denist)
Joined: 11 months ago

Posts: 0

some ideas about fixed cell size grid:

  1. i would use a DataGridView resize event. It should flicker less
  2. you have to take into account at least the width of grid’s vertical scrollbar.
 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

You’re right about the scrollbar, I modified it to take into consideration its size if it is visible.

I’m not sure I fully understand what you mean in your first comment. The control flickers no matter what whenever I resize the maxscript dialog, even if the datagridview itself is not being resized! Have I misunderstood your intention?

(@denist)
Joined: 11 months ago

Posts: 0

do the size adjustment of a grid columns at first fared resize event. Check what event happens first: Dialog resized or any DataGridView resize event. Use the first happend one. Avoid controls double-redraw.

 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

The dialog resize event fires first, but interestingly enough, the DGV resize event fires 3 times consecutively after every dialog resize event. I conclude that I should redraw on dialog resize and not on DGV resize.

Page 1 / 2