Sorry for the long post - but I want to make sure the situation is well understood.
I'm building myself a custom column for a DataGridView that has to keep track of the mouse state within the cell so basically a derivative of the ButtonColumn.
The column (cell more accurately) I built didn't perform as I had wished so I'm going more low level, and trying to first duplicate the functionality of the DataGridViewButtonColumn, and then modify the code I come up with.
If we look at how the real column works we can see that the cell knows if it wasn't the original cell clicked on (click button, move mouse to another cell in the same column and back).
I figured I can use a shared variable to keep track of which cell in the column was clicked on - but being stored in a point variable it wasn't enough (Point.Empty is 0,0 and that cell exists) so I had to implement a boolean to keep track of if it was set or not.
It was easy enough to set that to True in the OnMouseDown sub:
However it's not so easy unsetting it in MouseUp because the mouse could go up in another cell (not my code) or the form, or even Windows.
This would have to be implemented using low-level mouse hooks. I have this setup using the following:
In the constructor of MouseHook it calls SetWindowsHookEx and initializes it's own handler, and raises it's own event.
The problem now rests with closing the application (or maybe even the form - I've only tested with a single form app).
Upon disposing (and Finalizing) of the MouseHook class it attempts to unhook the handler using UnhookWindowsHookEx. This however is returning an error:
The error being thrown has the error code of 2 which turns out to be "The system cannot find the file specified".
The hook is most definitely being assigned successfully and being stored in hMouseHook. It appears as though something is being released before it has a chance to call the Unhook routine.
I have tried calling GC.KeepAlive on the delegate function being used in the SetWindowsHookEx call (stored in a local variable of the MouseHook class). I have tried placing that call in several different locations and it still doesn't work.
Any ideas on how to properly release this hook or even how to do it without the hook?
Thanks.
I'm building myself a custom column for a DataGridView that has to keep track of the mouse state within the cell so basically a derivative of the ButtonColumn.
The column (cell more accurately) I built didn't perform as I had wished so I'm going more low level, and trying to first duplicate the functionality of the DataGridViewButtonColumn, and then modify the code I come up with.
If we look at how the real column works we can see that the cell knows if it wasn't the original cell clicked on (click button, move mouse to another cell in the same column and back).
I figured I can use a shared variable to keep track of which cell in the column was clicked on - but being stored in a point variable it wasn't enough (Point.Empty is 0,0 and that cell exists) so I had to implement a boolean to keep track of if it was set or not.
Code:
Private Shared mouseDownCell As Point = Point.Empty
Private Shared mouseDownCellSet As Boolean = False
Code:
Protected Overrides Sub OnMouseDown(ByVal e As DataGridViewCellMouseEventArgs)
If ((Not MyBase.DataGridView Is Nothing) AndAlso ((e.Button = MouseButtons.Left) AndAlso DataGridViewImageButtonCell.mouseInContentBounds)) Then
DataGridViewImageButtonCell.mouseDownCell = New Point(e.ColumnIndex, e.RowIndex)
DataGridViewImageButtonCell.mouseDownCellSet = True
End If
End Sub
This would have to be implemented using low-level mouse hooks. I have this setup using the following:
Code:
Private Shared Sub globalMouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
mouseDownCellSet = False
End Sub
Private Shared colMouseHooks As New MouseHook(AddressOf globalMouseUp)
Code:
Public Event MouseUp As MouseEventHandler
Public Sub New(ByVal mouseUpHandler As MouseEventHandler)
InstallHooks()
AddHandler Me.MouseUp, mouseUpHandler
End Sub
Upon disposing (and Finalizing) of the MouseHook class it attempts to unhook the handler using UnhookWindowsHookEx. This however is returning an error:
Code:
Dim releaseResult As Boolean = True
releaseResult = Win32.UnhookWindowsHookEx(hMouseHook)
If Not releaseResult Then
Dim errCode As Integer = Marshal.GetLastWin32Error()
Throw New Win32Exception(errCode)
End If
The hook is most definitely being assigned successfully and being stored in hMouseHook. It appears as though something is being released before it has a chance to call the Unhook routine.
I have tried calling GC.KeepAlive on the delegate function being used in the SetWindowsHookEx call (stored in a local variable of the MouseHook class). I have tried placing that call in several different locations and it still doesn't work.
Any ideas on how to properly release this hook or even how to do it without the hook?
Thanks.