[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]
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!
Very impressive! Sharing the C# code really allows me to learn a lot from it.
I have a couple of questions about the assembly:
-
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?
-
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.
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?
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.
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
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!
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
some ideas about fixed cell size grid:
- i would use a DataGridView resize event. It should flicker less
- you have to take into account at least the width of grid’s vertical scrollbar.
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?
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.
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.