Notifications
Clear all

[Closed] dotNet UI

Oh I see now. That makes sense.
I was trying each possible way and was overlooking that the index stared at 0. Thanks Lo for the explanation on everything.

So this is what I have so far, it does everything I wanted it do do.
If you see any improvements I’d love to hear them.

One that i notice is the Activate and Deactivate could be condensed into a function, which I’ll do next.
As for any of the dotNet stuff it seems good.
I’ll have to figure out a way to get the seletion thing working like described above, it does not work for me to do a drag selection.
Corky thing I noticed is the text changes font types if you select it all and hit deactivate from the start. Other than that it seems great.


try(destroydialog ::rlListView)catch()
rollout rlListView "Listview"
(
	-- This is array holds the content for our Listview items. An oversimplification, probably.
	local _itemsArr = for i = 1 to 10 collect "Item "+ i as string
		
	local activeFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11 (dotNetClass "System.Drawing.FontStyle").Bold (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local inactiveFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel

	--pickbutton pbtnSourceObj "Source Object" pos:[10,10] width:180 height:20
	dotNetControl lvTracks "System.Windows.Forms.ListView" width:180 height:220 pos:[10,40]
	button btnActivate "Activate" width:90 height:20 pos:[10,10]
	button btnDeactivate "Deactivate" width:90 height:20 pos:[100,10]
	
	fn fnListviewTracksSetup = (
		lvTracks.clear() -- wipe out the contents of the entire listview so that we're redrawing it from scratch each time this function is called
		
		lvTracks.View = (dotNetClass "System.Windows.Forms.View").Details -- this is what allows the grid-like format to be used
		lvTracks.fullRowSelect = true -- When item is clicked, all columns in that item are selected
		lvTracks.gridLines = true-- turn on the grid lines
		lvTracks.HideSelection= false -- When this ListView loses the focus, it will still show what's selected
		lvTracks.BorderStyle=lvTracks.BorderStyle.FixedSingle -- make the border a flat solid color instead of the Windows 3D look
		lvTracks.HeaderStyle=lvTracks.HeaderStyle.Nonclickable -- Flattens the headers a bit (although they're still somewhat 3D) and keeps them from being clickable   
		lvTracks.backColor=lvTracks.backColor.FromArgb 250 250 250 -- Soften the background intensity a bit
		lvTracks.Columns.add "Tracks" 180 -- create a couple of columns and optionally specify their width
		
		-- Create the items that will go in the list view
		lvTracks.Items.AddRange (for i in _itemsArr collect (dotNetObject "ListViewItem" i))
		for i = 1 to (lvTracks.Items.count) do
		(
			itm = lvTracks.Items.Item[i-1]
			itm.tag = false
		)
	)
	
	on btnActivate pressed do
	(
		_arr = lvTracks.SelectedIndices
		_selIdxs = for i = 1 to _arr.count collect _arr.item[i-1] --need the i-1 because the collection is 0-based.
		--print _selIdxs --note that the returned indices are also 0-based because the .items of the listview are also a dotnet collection!
		
		for i = 1 to _selIdxs.count do
		(
			idx = _selIdxs[i]
			lvTracks.Items.item[idx].Font = activeFont
			lvTracks.Items.item[idx].Tag = true
		)
	)
	
	on btnDeactivate pressed do
	(
		_arr = lvTracks.SelectedIndices
		_selIdxs = for i = 1 to _arr.count collect _arr.item[i-1] --need the i-1 because the collection is 0-based.
		--print _selIdxs --note that the returned indices are also 0-based because the .items of the listview are also a dotnet collection!
		
		for i = 1 to _selIdxs.count do
		(
			idx = _selIdxs[i]
			lvTracks.Items.item[idx].Font = inactiveFont
			lvTracks.Items.item[idx].Tag = false
		)
	)

	on lvTracks MouseDoubleClick s a do
	(
		itm = s.GetItemAt a.x a.y	
		if itm  != undefined do 
		(
 			trackName = itm.text
			idx = (itm.Index + 1) --dotnet lists start with 0
			
			if itm.tag == false then
			(
				itm.font = activeFont -- bold font	
				itm.tag = true
			)else(
				itm.font = inactiveFont -- regular font
				itm.tag = false
			)
		)
	)
	
	on rlListView open do
	(
		fnListviewTracksSetup()
	)
	
)
createdialog rlListView 200 270

I see what you’ve done there. That makes sense. It was redundant and long for no reason.

 lo1

This is all the code you need for drag-selection:

	local mouseIsDown = off
	
	on lvTracks mouseDown s a do mouseIsDown = on
	on lvTracks mouseUp s a do mouseIsDown = off
		
	on lvTracks mouseMove s a do
	(
		if mouseIsDown and (local item = s.GetItemAt a.x a.y) != undefined do item.selected = on
	)

Wow, that was quick.
I was searching around and trying to figure that out and was not in the relm of the same results. I appreciate the time you’ve spent helping me out on this Rotem. I’ve sure picked up a handful of things with your help.

Is the focus a bug?
I select multiple items in the listview and then click outside of that and they are appear unselected. How can I keep them appearing as if they are selected (blue highlight)

Works!
Sadly i lose the styling of the header though. And it flickers a little bit.


try(destroydialog ::rlListView)catch()
rollout rlListView "Listview"
(
	-- This is array holds the content for our Listview items. An oversimplification, probably.
	local _itemsArr = for i = 1 to 10 collect "Item "+ i as string
	local mouseIsDown = off	
	local activeFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11 (dotNetClass "System.Drawing.FontStyle").Bold (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local inactiveFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local selColor = (dotNetClass "System.Drawing.Color").fromARGB 238 204 85 -- custom selection color (orangey-yellow)
	local lvBackColor = selColor.fromARGB 250 250 250
	
	
	--pickbutton pbtnSourceObj "Source Object" pos:[10,10] width:180 height:20
	dotNetControl lvTracks "System.Windows.Forms.ListView" width:180 height:220 pos:[10,40]
	button btnActivate "Activate" width:90 height:20 pos:[10,10]
	button btnDeactivate "Deactivate" width:90 height:20 pos:[100,10]
	
	fn fnListviewTracksSetup = (
		lvTracks.clear() -- wipe out the contents of the entire listview so that we're redrawing it from scratch each time this function is called
		
		lvTracks.View = (dotNetClass "System.Windows.Forms.View").Details -- this is what allows the grid-like format to be used
		lvTracks.OwnerDraw = true
		lvTracks.fullRowSelect = true -- When item is clicked, all columns in that item are selected
		lvTracks.gridLines = true-- turn on the grid lines
		lvTracks.HideSelection= false -- When this ListView loses the focus, it will still show what's selected
		lvTracks.BorderStyle=lvTracks.BorderStyle.FixedSingle -- make the border a flat solid color instead of the Windows 3D look
		lvTracks.HeaderStyle=lvTracks.HeaderStyle.Nonclickable -- Flattens the headers a bit (although they're still somewhat 3D) and keeps them from being clickable   
		lvTracks.backColor=lvTracks.backColor.FromArgb 250 250 250 -- Soften the background intensity a bit
		lvTracks.Columns.add "Tracks" 180 -- create a couple of columns and optionally specify their width
		
		-- Create the items that will go in the list view
		lvTracks.Items.AddRange (for i in _itemsArr collect (dotNetObject "ListViewItem" i))
		for i = 1 to (lvTracks.Items.count) do
		(
			itm = lvTracks.Items.Item[i-1]
			itm.tag = false
		)
	)
	
	on lvTracks mouseDown s a do mouseIsDown = on
	on lvTracks mouseUp s a do mouseIsDown = off
		
	on lvTracks mouseMove s a do
	(
		if mouseIsDown and (local item = s.GetItemAt a.x a.y) != undefined do item.selected = on
	)
	
	on btnActivate pressed do
	(
		_arr = lvTracks.SelectedIndices
		_selIdxs = for i = 1 to _arr.count collect _arr.item[i-1] --need the i-1 because the collection is 0-based.
		--print _selIdxs --note that the returned indices are also 0-based because the .items of the listview are also a dotnet collection!
		
		for i = 1 to _selIdxs.count do
		(
			idx = _selIdxs[i]
			lvTracks.Items.item[idx].Font = activeFont
			lvTracks.Items.item[idx].Tag = true
		)
	)
	
	on btnDeactivate pressed do
	(
		_arr = lvTracks.SelectedIndices
		_selIdxs = for i = 1 to _arr.count collect _arr.item[i-1] --need the i-1 because the collection is 0-based.
		--print _selIdxs --note that the returned indices are also 0-based because the .items of the listview are also a dotnet collection!
		
		for i = 1 to _selIdxs.count do
		(
			idx = _selIdxs[i]
			lvTracks.Items.item[idx].Font = inactiveFont
			lvTracks.Items.item[idx].Tag = false
		)
	)

	on lvTracks MouseDoubleClick s a do
	(
		itm = s.GetItemAt a.x a.y	
		if itm  != undefined do 
		(
			print itm.text
			itm.tag = if itm.tag != true then true else false
			itm.font = if itm.tag then activeFont else inactiveFont
		)
	)
	
	on rlListView open do
	(
		fnListviewTracksSetup()
	)
	
	
	-------selection color controls
	on lvTracks ItemSelectionChanged arg do
	(
		arg.Item.BackColor = if arg.isSelected then selColor else lvBackColor
	)

	on lvTracks drawitem arg do
	(
		arg.DrawBackground()
		arg.DrawText()
	)
)
createdialog rlListView 200 270

 lo1

For the column header you can add this:

on lvTracks DrawColumnHeader arg do
	(
		arg.DrawBackground()
		arg.DrawText()
	)

For the flickering, you might need to set double buffering for this control. I don’t know a way to do this without a small dynamically compiled c# assembly. Search this forum for Control.SetStyle

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

invoke the method is the way around an assembly…

(@denist)
Joined: 11 months ago

Posts: 0

 fn setDoubleBuffer control value:on = 
 (
 	type = control.GetType()
 	bf = dotnetclass "System.Reflection.BindingFlags"
 	flags = dotnet.combineEnums bf.NonPublic bf.Instance bf.InvokeMethod
 	cs = dotnetclass "ControlStyles"
 	styles = dotnet.combineEnums cs.DoubleBuffer cs.AllPaintingInWmPaint
 --	styles = dotnet.combineEnums cs.DoubleBuffer cs.UserPaint cs.AllPaintingInWmPaint cs.Opaque
 	type.InvokeMember "SetStyle" flags type.DefaultBinder control #(styles, value)
 	value
 )
 /*
 panel = dotnetobject "UserControl"
 setDoubleBuffer panel
 */
 

Alright. I’ll look into it.
Thanks again for the help.
When Applying the draw text and style it causes a weird alignment in the column label? Why is that?

Here is what I’ve got so far.


try(destroydialog ::rlListView)catch()
rollout rlListView "Listview"
(
	-- This is array holds the content for our Listview items. An oversimplification, probably.
	local _itemsArr = for i = 1 to 10 collect "Item "+ i as string
	local mouseIsDown = off	
	local activeFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11 (dotNetClass "System.Drawing.FontStyle").Bold (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local inactiveFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local selColor = (dotNetClass "System.Drawing.Color").fromARGB 238 204 85 -- custom selection color (orangey-yellow)
	local lvBackColor = selColor.fromARGB 250 250 250
	
	
	--pickbutton pbtnSourceObj "Source Object" pos:[10,10] width:180 height:20
	dotNetControl lvTracks "System.Windows.Forms.ListView" width:180 height:220 pos:[10,40]
	button btnActivate "Activate" width:90 height:20 pos:[10,10]
	button btnDeactivate "Deactivate" width:90 height:20 pos:[100,10]
	
	fn fnListviewTracksSetup = (
		lvTracks.clear() -- wipe out the contents of the entire listview so that we're redrawing it from scratch each time this function is called
		
		lvTracks.View = (dotNetClass "System.Windows.Forms.View").Details -- this is what allows the grid-like format to be used
		lvTracks.OwnerDraw = true
		lvTracks.fullRowSelect = true -- When item is clicked, all columns in that item are selected
		lvTracks.gridLines = true-- turn on the grid lines
		lvTracks.HideSelection= false -- When this ListView loses the focus, it will still show what's selected
		lvTracks.BorderStyle=lvTracks.BorderStyle.FixedSingle -- make the border a flat solid color instead of the Windows 3D look
		lvTracks.HeaderStyle=lvTracks.HeaderStyle.Nonclickable -- Flattens the headers a bit (although they're still somewhat 3D) and keeps them from being clickable   
		lvTracks.backColor=lvTracks.backColor.FromArgb 250 250 250 -- Soften the background intensity a bit
		lvTracks.Columns.add "Tracks" 180 -- create a couple of columns and optionally specify their width
		
		-- Create the items that will go in the list view
		lvTracks.Items.AddRange (for i in _itemsArr collect (dotNetObject "ListViewItem" i))
		for i = 1 to (lvTracks.Items.count) do
		(
			itm = lvTracks.Items.Item[i-1]
			itm.tag = false
			itm.font = inactiveFont
		)
	)
	

	
	on lvTracks mouseDown s a do mouseIsDown = on
	on lvTracks mouseUp s a do mouseIsDown = off
		
	on lvTracks mouseMove s a do
	(
		if mouseIsDown and (local item = s.GetItemAt a.x a.y) != undefined do item.selected = on
	)
	
	on btnActivate pressed do
	(
		_arr = lvTracks.SelectedIndices
		_selIdxs = for i = 1 to _arr.count collect _arr.item[i-1] --need the i-1 because the collection is 0-based.
		--print _selIdxs --note that the returned indices are also 0-based because the .items of the listview are also a dotnet collection!
		
		for i = 1 to _selIdxs.count do
		(
			idx = _selIdxs[i]
			lvTracks.Items.item[idx].Font = activeFont
			lvTracks.Items.item[idx].Tag = true
		)
	)
	
	on btnDeactivate pressed do
	(
		_arr = lvTracks.SelectedIndices
		_selIdxs = for i = 1 to _arr.count collect _arr.item[i-1] --need the i-1 because the collection is 0-based.
		--print _selIdxs --note that the returned indices are also 0-based because the .items of the listview are also a dotnet collection!
		
		for i = 1 to _selIdxs.count do
		(
			idx = _selIdxs[i]
			lvTracks.Items.item[idx].Font = inactiveFont
			lvTracks.Items.item[idx].Tag = false
		)
	)

	on lvTracks MouseDoubleClick s a do
	(
		itm = s.GetItemAt a.x a.y	
		if itm  != undefined do 
		(
			print itm.text
			itm.tag = if itm.tag != true then true else false
			itm.font = if itm.tag then activeFont else inactiveFont
		)
	)
	
	on rlListView open do
	(
		fnListviewTracksSetup()
	)
	
	
	-------selection color controls
	on lvTracks ItemSelectionChanged arg do
	(
		arg.Item.BackColor = if arg.isSelected then selColor else lvBackColor
	)

	on lvTracks drawitem arg do
	(
		arg.DrawBackground()
		arg.DrawText()
	)
	
	on lvTracks DrawColumnHeader s e do
	(
		e.DrawBackground()
		e.DrawText()
		
		--custom headers
		if (dotnet.CompareEnums e.State e.State.Selected) then
		(
			e.Graphics.FillRectangle (dotnetclass "System.Drawing.Brushes").LightBlue e.Bounds
		)
		else
		(
			brush = dotnetobject "System.Drawing.Drawing2D.LinearGradientBrush" e.Bounds \
				(dotnetclass "System.Drawing.Color").LightBlue \
				(dotnetclass "System.Drawing.Color").DarkBlue \
				(dotnetclass "System.Drawing.Drawing2D.LinearGradientMode").Vertical
	  
			e.Graphics.FillRectangle brush  e.Bounds
		)
		
		flags = dotnet.combineEnums (dotnetclass "TextFormatFlags").HorizontalCenter (dotnetclass "TextFormatFlags").VerticalCenter
		(dotnetclass "TextRenderer").DrawText e.Graphics e.Header.Text s.Font e.Bounds (dotnetclass "System.Drawing.Color").White flags
	)
)
createdialog rlListView 200 270

Is is possible to make the header of a listview contain an action when clicked?
In my case I’m just wanting it to select all the items in the listview.

Simple Listview snippet


try(destroydialog ::ListviewBugTest)catch()
rollout ListviewBugTest "" 
( 

	dotNetControl lv "System.Windows.Forms.ListView" width:250 height:150 align:#center pos:[10,10]

	on ListviewBugTest open do 
	( 
		-- Setup the listview
		lv.View = (dotNetClass "System.Windows.Forms.View").Details  
		lv.fullRowSelect = true  
		lv.Columns.add ("Column "+i as string)
		
		-- Add items to listview
		for x=1 to 5 do 
		(
			local newItem = dotNetObject "System.Windows.Forms.ListViewItem" ("Col." + x as string)
			lv.items.add newItem    
		)  
	) 
)
createDialog ListviewBugTest 270 170

make the column header clickable by setting ColumnHeaderStyle.Clickable, and use the ListView.ColumnClick Event

Page 11 / 18