try(destroydialog ::rlList)catch()
rollout rlList ""
(
dotNetControl lvObjects "System.Windows.Forms.ListView" width:250 height:150 pos:[10,10]
dotNetControl btnA "Button" width:125 height:25 pos:[10,160]
dotNetControl btnB "Button" width:125 height:25 pos:[135,160]
on rlList open do
(
-- Setup the listview
lvObjects.View = (dotNetClass "System.Windows.Forms.View").Details
lvObjects.fullRowSelect = true
lvObjects.Columns.add ("Objects")
lvObjects.columns.item[0].width = rlList.width - 24
-- Add items to listview
for x=1 to 5 do
(
local newItem = dotNetObject "System.Windows.Forms.ListViewItem" ("Col." + x as string)
lvObjects.items.add newItem
)
)
on lvObjects ColumnClick e do
(
clearlistener()
for i = 0 to lvObjects.Items.count-1 do lvObjects.Items.item[i].Selected = true
)
on rlList resized val do (
w = val[1]
h = val[2]
lvObjects.width = (w-20)
lvObjects.height = (h-40)
lvObjects.columns.item[0].width = w - 24
local bWidth = lvObjects.width / 2
local bPosY = lvObjects.pos[2] + lvObjects.height
btnA.width = bWidth
btnB.width = bWidth
btnA.pos = [btnA.pos[1], bPosY]
btnB.pos = [btnA.pos[1] + bWidth, bPosY]
)
)
createDialog rlList 270 190 style:#(#style_SysMenu, #style_ToolWindow, #style_resizing)
This is the long hard way using a max rollout.
Using DotNetObjects would make this as simple as setting a single property.
the real problem is how to avoid showing and flickering of the horizontal scroll bar.
for WS_HSCROLL the order of messages is different. the same code doesn’t work for the horizontal scroll bar.
actually the code is not absolutely correct but the overriding the WndProc is the only way that I found.
If you don’t mind showing, I’m open to doing it with DotNetObjects. Feel free to show that example. I am not locked on using the max rollout.
I usually just avoid using them because the setup require more work to avoid issues like gc and window parenting.
On second thought forget what I said. To do this without handling the resize handler you need a TableLayoutPanel, and that’s a PITA to set up in maxscript.
This seems like a lot when all I’m really after is the ability to have a horizontal scroll and resizeable window.
Downside is that there is no stored Selection focus on the listview. I saw that people change the background color to match the selection highlight to make it appear to not have lost focus.
Another bugger is that I can not multi-line select by click and drag. It wants to select only a single object in the list.
What are your guys thoughts on this?
Ways to improve this or just stick the maxscript dialog?
--Destroy dialog if it already exists.
try(destroyDialog theRollout)catch()
--Create a rollout
rollout theRollout "The Rollout" width:300
(
--Create the dotNet listview control
dotNetControl lv "system.windows.forms.listView" pos:[10,40]
--Create a button for testing.
button btnDelete "Delete Objects" height:25 width:100 pos:[10,10]
button btnUpdate "Update" height:25 width:70 pos:[120,10]
fn populateList = (
lv.items.clear()
for node in objects as array do
(
item = lv.items.add node.name
item.tag = dotnetmxsvalue node
)
)
fn ListViewReturnSelectedIndexs ListView = (
local RetArray = #()
local tnPropColl = getProperty ListView #selectedItems
for Row = 0 to ( tnPropColl.count-1) do
(
local tnProp = tnPropColl.get_item Row
append RetArray tnProp.Index --index up for maxs arrays which start at 1
)
RetArray
)
on btnUpdate pressed do (populateList())
on btnDelete pressed do (
selIdxs = ListViewReturnSelectedIndexs lv
_objCol = for i in selIdxs collect (lv.items.item[i].tag.value)
delete _objCol
populateList()
)
--Innitialize the listview control
fn initLv theLv=
(
--Setup the forms view
theLv.view=(dotNetClass "system.windows.forms.view").details
theLv.FullRowSelect=true --Set so full width of listView is selected and not just first column.
theLv.GridLines=true --Show lines between the items.
theLv.MultiSelect=true --Allow for multiple selections.
)
--Add columns.
fn addColumns theLv columnsAr=
(
w=(theLv.width/columnsAr.count)-21 --Calculate the width of each column.
for x in columnsAr do --Loop through all the column names to be added.
(
theLv.columns.add x w --Add each new column to the listview control.
)
)
fn resizeUI = (
lv.width = (theRollout.width-20)
lv.height = (theRollout.height-50)
lv.columns.item[0].width = (lv.width - 21)
)
on theRollout resized val do (
resizeUI()
)
on theRollout open do
(
initLv lv
addColumns lv #("Object")
populateList()
resizeUI()
)
)
--Create a dialog and assign the rollout to it.
createDialog theRollout 200 200 style:#(#style_SysMenu, #style_ToolWindow, #style_resizing)
here is how to keep selection after the losing focus:
theLv.HideSelection = off
theLv.BackColor = (dotnetclass "System.Drawing.SystemColors").Menu
The flickering you get with dotNet controls within rollouts is pretty nasty. Personally I much prefer using a form and then using the anchor property to get automatic resizing. This way there is zero flickering and the resize animation is very smooth.
Something like this:
mf = dotNetObject "MaxCustomControls.MaxForm"
lv = dotNetObject "listview"
btn = dotNetObject "button"
mf.size = dotNetObject "System.Drawing.Size" 500 250
btn.size = dotNetObject "System.Drawing.Size" 460 30
btn.location = dotNetObject "System.Drawing.Point" 10 10
lv.size = dotNetObject "System.Drawing.Size" 460 150
lv.location = dotNetObject "System.Drawing.Point" 10 50
lv.view=(dotNetClass "system.windows.forms.view").details
lv.columns.add "Column 1" (mf.width-200)
anchorStyle = (dotNetClass "System.Windows.Forms.AnchorStyles")
btn.anchor = dotnet.combineEnums anchorStyle.top anchorStyle.left anchorStyle.right
lv.anchor = dotnet.combineEnums anchorStyle.top anchorStyle.bottom anchorStyle.left anchorStyle.right
mf.controls.add btn
mf.controls.add lv
mf.show()
function resizeColumn = lv.columns.item[0].width = mf.width-200
dotNet.addEventHandler mf "Resize" resizeColumn
here is a template that shows how to make this kind of UI (rollout, resizable LV, docked on top Buttons, one Button with fixed size):
try(destroyDialog resizeRollout) catch()
rollout resizeRollout "The Rollout" width:200
(
dotNetControl panel "Panel" width:0 height:0 pos:[2,2]
local lv, delete_bt, update_bt
fn makeUI =
(
panel.Backcolor = ((dotnetClass "ManagedServices.CuiUpdater").GetInstance()).getMaxColor 0
lv = dotnetobject "ListView"
lv.Dock = lv.Dock.Fill
lv.View = lv.View.Details
lv.FullRowSelect = lv.GridLines = lv.MultiSelect = on
lv.HideSelection = off
lv.BackColor = (dotnetclass "System.Drawing.SystemColors").Menu
lv.Columns.Add "Name"
items = for k=0 to 11 collect (dotnetobject "ListViewItem" ("Node " + k as string))
lv.Items.AddRange items
fn onClientSizeChanged s e =
(
s.Columns.Item[0].Width = s.ClientSize.Width-1
)
dotnet.addEventHandler lv "ClientSizeChanged" onClientSizeChanged
pn = dotnetobject "Panel"
pn.Backcolor = pn.Backcolor.Transparent
pn.Height = 24
pn.Dock = pn.Dock.Top
bt = dotnetobject "Button"
bt.Backcolor = bt.Backcolor.Transparent
bt.Text = "Delete"
bt.Height = 24
bt.Dock = bt.Dock.Fill
delete_bt = bt
bt = dotnetobject "Button"
bt.Backcolor = bt.Backcolor.Transparent
bt.Text = "Update"
bt.Height = 24
bt.Width = 60
bt.Dock = bt.Dock.Right
update_bt = bt
pn.Controls.AddRange #(delete_bt, update_bt)
panel.Controls.AddRange #(lv, pn)
)
fn resizeUI size: =
(
if size == unsupplied do size = getdialogsize resizeRollout
panel.width = size.x-4
panel.height = size.y-4
)
on resizeRollout resized val do resizeUI()
on resizeRollout open do
(
makeUI()
resizeUI()
)
)
createDialog resizeRollout 200 200 style:#(#style_SysMenu, #style_ToolWindow, #style_resizing)