XPTable (CLR.ahk) Implementation

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
kczx3
Posts: 1674
Joined: 06 Oct 2015, 21:39

XPTable (CLR.ahk) Implementation

13 Oct 2016, 19:49

To avoid further robbery of Lexikos' post in the Scripts and Functions forum, I am posting here for help.

I have been trying to learn and implement the XPTable custom control, for the past couple days. I have gotten quite a bit and it's impressive what we can do with this control. I am trying to figure out handling of the events now. I have zero C# or .NET experience and besides AHK, I have worked with PHP, JS, and HTML/CSS for about 6 months. I have managed to build the XPTable from its most recent source using .NET 4.5.1. Here is the DLL.

I was only able to get ImageColumn's working by creating a wrapper class using System.Drawing.Image and only the FromFile() method. Bitmap's didn't work for some reason using FromhBitmap(), so if you don't that image then try a different path to an image.

I was assuming I could just use the code that Lexikos posted about handling events and it would just work :). Silly me! The part that does work is using the AddHandler() method, but I get an error immediately upon having the mouse enter a cell with the following text:
************** Exception Text **************
System.InvalidOperationException: This type has a ComVisible(false) parent in its hierarchy, therefore QueryInterface calls for IDispatch or class interfaces are disallowed.
at System.StubHelpers.MngdSafeArrayMarshaler.ConvertContentsToNative(IntPtr pMarshalState, Object& pManagedHome, IntPtr pNativeHome, Object pOriginalManaged)
at XPTable.Models.Table.OnCellToolTipPopup(CellToolTipEventArgs e)
at XPTable.Renderers.CellRenderer.OnMouseEnter(CellMouseEventArgs e)
at XPTable.Models.Table.OnCellMouseEnter(CellMouseEventArgs e)
at XPTable.Models.Table.RaiseCellMouseEnter(CellPos cellPos)
at XPTable.Models.Table.OnMouseMove(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseMove(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
So it seems the event is firing and something is attempting to be ran. I have tried looking through the assembly and don't see any instance of ComVisible being set to false (other than in some of the samples). So I guess it could be some of the System assemblies that are being used... From what I can tell, ComVisible is set to True by default.

Anyways, here is my code thus far. You can get EventHelper.cs from the above link of Lexikos'.

Code: Select all

#SingleInstance Force
#Include CLR.ahk

FileRead, eventHelperCode, EventHelper.cs

xptables := CLR_LoadLibrary("XPTable.dll")
drawing := CLR_LoadLibrary("System.Drawing")
headerFont := CLR_CreateObject(drawing, "System.Drawing.Font", "Tahoma", 16)
rowFont := CLR_CreateObject(drawing, "System.Drawing.Font", "Tahoma", 10)

loadImgCode =
(
using System;
using System.Drawing;
class loadImg {
	public Image test(string filename) {
		Image image = (Image)Image.FromFile(filename);
		return image;
	}
}
)
imageCode := CLR_CompileC#(loadImgCode, "System.dll | System.Drawing.dll")
imageObj := CLR_CreateObject(imageCode, "loadImg")

helperAsm := CLR_CompileC#(eventHelperCode)
helper := helperAsm.CreateInstance("EventHelper")
; handler := helper.MakeHandler("" RegisterCallback("EventHandler"))

; Type names must be fully qualified.
table := CLR_CreateObject(xptables,"XPTable.Models.Table")
helper.AddHandler(table, "CellToolTipPopup", "" RegisterCallback("EventHandler"))
; table.add_CellToolTipPopup(handler)
columnModel := CLR_CreateObject(xptables,"XPTable.Models.ColumnModel")
columnModel.HeaderHeight := 50
tableModel  := CLR_CreateObject(xptables,"XPTable.Models.TableModel")
tableModel.RowHeight := 25

table.ColumnModel := columnModel
table.TableModel := tableModel
HeaderRenderer := CLR_CreateObject(xptables, "XPTable.Renderers.GradientHeaderRenderer")
HeaderRenderer.StartColor := 0xc0c0c0
HeaderRenderer.EndColor := 0xd5b031
table.HeaderRenderer := HeaderRenderer
table.HeaderFont := headerFont
table.AlternatingRowColor := 0x808080
table.BorderColor := 0x808080
table.BorderStyle := 2
table.EnableHeaderContextMenu := True
table.GridLines := 4
table.GridColor := 0x808080
; table.GridLinesContraintedToData := True
table.SelectionBackColor := 0xe28f4f
table.ShowSelectionRectangle := False
table.SelectionStyle := 1
table.EnableToolTips := True

;**************************************************************************************************
; Add our columns to the columnModel
;**************************************************************************************************
Columns := columnModel.Columns
Columns.Add(col0 := CLR_CreateObject(xptables, "XPTable.Models.GroupColumn", "", 20))
col0.Editable := False
col0.Selectable := False
col0.Sortable := False
col0.ToggleOnSingleClick := True
Columns.Add(col1 := CLR_CreateObject(xptables, "XPTable.Models.ImageColumn", "", 20))
col1.DrawText := True
col1.Resizable := False
Columns.Add(CLR_CreateObject(xptables, "XPTable.Models.TextColumn", "Text", 100))
Columns.Add(CLR_CreateObject(xptables, "XPTable.Models.CheckBoxColumn", "CheckBox", 125))
Columns.Add(CLR_CreateObject(xptables, "XPTable.Models.ButtonColumn", "Button", 100))
Columns.Add(CLR_CreateObject(xptables, "XPTable.Models.ProgressBarColumn", "Progress", 100))

;**************************************************************************************************
; Add a row to the tableModel
;**************************************************************************************************
rows := tableModel.Rows
rows.Add(row1 := CLR_CreateObject(xptables, "XPTable.Models.Row"))
; row1.Editable := ComObject(0xB, False)

;**************************************************************************************************
; Add our cells to the previously created row
;**************************************************************************************************
cells := row1.cells
Cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
Cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
Cells.Add(cell1 := CLR_CreateObject(xptables, "XPTable.Models.Cell", "MyCell1"))
; cell1.Editable := False
Cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell", "MyCheckbox1", ComObject(0xB, -1)))
Cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell", "MyButton1"))
Cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell", 75))

;**************************************************************************************************
; Style our row
;**************************************************************************************************
rowStyle := CLR_CreateObject(xptables, "XPtable.Models.RowStyle")
rowStyle.Font := rowFont
; rowStyle.ForeColor := 0xFF0000
; rowStyle.BackColor := 0x0000FF
row1.RowStyle := rowStyle

;**************************************************************************************************
; Second row 
;**************************************************************************************************
rows.Add(row2 := CLR_CreateObject(xptables, "XPTable.Models.Row"))
cells := row2.cells
cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
cells.Add(cell1 := CLR_CreateObject(xptables, "XPTable.Models.Cell", "This is a test for text that spans multiple columns"))
; cell1.ColSpan := 4

;**************************************************************************************************
; Sub Row
;**************************************************************************************************
subRow := CLR_CreateObject(xptables, "XPTable.Models.Row")
subRow.cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
subRow.Cells.Add(subrowCell := CLR_CreateObject(xptables, "XPTable.Models.Cell", "", imageObj.test(A_WinDir "\system32\@WindowsHelloFaceToastIcon.png")))
subRow.Cells.Add(subrowCell := CLR_CreateObject(xptables, "XPTable.Models.Cell", "SubRow Cell 1"))
; subrowCell.ColSpan := 4
row2.SubRows.Add(subRow)

;**************************************************************************************************
; Fourth row 
;**************************************************************************************************
rows.Add(row4 := CLR_CreateObject(xptables, "XPTable.Models.Row"))
cells := row4.cells
cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
cells.Add(CLR_CreateObject(xptables, "XPTable.Models.Cell"))
cells.Add(cell1 := CLR_CreateObject(xptables, "XPTable.Models.Cell", "This is a test for text that spans multiple columns"))
cell1.ToolTipText := "TEST"
cell1.ColSpan := 4

;**************************************************************************************************
; Release our references
;**************************************************************************************************
columnModel := ""
tableModel := ""

;**************************************************************************************************
; Position the table within its Parent
;**************************************************************************************************
table.Left := 10
table.Top := 10
table.Width := 500
table.Height := 200

hwnd := table.Handle
Gui, +LastFound
DllCall("SetParent", UInt, hwnd, UInt, WinExist())
Gui, Show, W520 H220, XPTable Example

; table.CellToolTipPopup()

return

GuiClose:
ExitApp

EventHandler(pprm) {
	prm := ComObject(0x200C, pprm)
	
	msgbox, 0, Event Raised, % "`nSender: " prm[0].ToString()
		. "`nEventArgs: " prm[1].ToString()
}
Hoping there may be some unfortunate soul to see this post and know enough to assist (other than Lexikos, he helps enough as it is!). Thanks all.
lexikos
Posts: 9780
Joined: 30 Sep 2013, 04:07
Contact:

Re: XPTable (CLR.ahk) Implementation

13 Oct 2016, 22:15

Sounds like maybe a "security" feature of later .NET versions (I don't use .NET regularly.)

You can try creating a C#/VB helper class which consumes the event and calls your script object/function.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 81 guests