ALX
Well-known member
This may seem a little trivial, but I'm a nut for making an app work with the keyboard and avoid making the user reach for the mouse when ever possible.
I have a Help page for my app that is shown on a web browser control. This is easy for me as I can update the help page quickly and easily just by modifying the HTML of the Help page. It's also easier to embed images as compared to say maybe a rich textbox. I want the user to be able to close the Help segment just by pressing the Escape key as opposed to clicking the close button. My code for starters...
If I set this up without the KeyDown event, and force the user to use the 'Close' button, everything works great. With the Keydown event tho, I get an message when closing the WebBrowser: "RaceOnRCWCleanup was detected Message: An attempt has been made to free an RCW that is in use. My guess is that I'm trying to dispose an object for which the KeyDown Event is currently being processed... So I tried the following code:
My thinking was that that this gave time for the event handler to complete and exit the sub... But NO! Now I get a Cross-Thread error in CloseWebBrowser(). This is no longer just my anal attempt to avoid forcing the user to not have to reach for the mouse. I need to beat this thing! I would greatly appreciate any guidance. Thank You !
I have a Help page for my app that is shown on a web browser control. This is easy for me as I can update the help page quickly and easily just by modifying the HTML of the Help page. It's also easier to embed images as compared to say maybe a rich textbox. I want the user to be able to close the Help segment just by pressing the Escape key as opposed to clicking the close button. My code for starters...
VB.NET:
Private Sub HelpButton1_Click() ' Called from the Help Icon Click or F1
If WBPanel Is Nothing Then
RemoveHandler Me.KeyDown, AddressOf Me_KeyDown ' This gets rid the the KeyDown Handler for the hosting page
WBPanel = New Panel
' code removed here for Panel Size, Location, CloseButton details etc.
WB1 = New WebBrowser
Dim n As String = My.Computer.FileSystem.ReadAllText('HTML loaded from disk...)
With WB1
.Size = ...
.Location = ...
.DocumentText = n
.Tag = "Dynamic" ' All controls on this panel are assigned a "Dynamic" Tag
.BringToFront()
End With
WBPanel.Controls.Add(WB1) ' Add the Web Control to the panel
Me.Controls.Add(WBPanel) ' and the panel to the hosting page
WBPanel.BringToFront()
CloseButton.BringToFront()
AddHandler CloseButton.Click, AddressOf CloseWB ' CloseWB just calls CloseWebBrowser()
WB1.Document.Focus()
WBPanel.Show()
End If
End Sub
'-------------------------------------------------------------------
private Sub CloseWB() ' Called from the CloseButton Click or the Escape KeyPress
If WBPanel IsNot Nothing Then
RemoveHandler CloseLabel.Click, AddressOf CloseWB
Dim ctlList As New List(Of Control)
For Each ctl As Control In WBPanel.Controls
If ctl.Tag = "Dynamic" Then ' Create a list of all disposeable controls added to this panel
ctlList.Add(ctl)
End If
Next
For Each ctl In ctlList
Me.Controls.Remove(ctl)
ctl.Dispose() ' Here I get a 'RaceOnRCWCleanup was detected' Message when
ctl = Nothing ' KeyDown is used and the ctl = the Web Browser
Next
WBPanel.Dispose()
WBPanel = Nothing
AddHandler Me.KeyDown, AddressOf Me_KeyDown ' Restore the previously removed handler...
End If
End Sub
'-------------------------------------------------------------------
Private Sub WB1_DocumentCompleted(ByVal sender As System.Object, ByVal e As Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WB1.DocumentCompleted
AddHandler WB1.Document.Body.KeyDown, New HtmlElementEventHandler(AddressOf WB1_KeyDown)
End Sub
'-------------------------------------------------------------------
Private Sub WB1_KeyDown(ByVal sender As Object, ByVal e As HtmlElementEventArgs)
If e.KeyPressedCode = 27 Then CloseWB()
End Sub
If I set this up without the KeyDown event, and force the user to use the 'Close' button, everything works great. With the Keydown event tho, I get an message when closing the WebBrowser: "RaceOnRCWCleanup was detected Message: An attempt has been made to free an RCW that is in use. My guess is that I'm trying to dispose an object for which the KeyDown Event is currently being processed... So I tried the following code:
VB.NET:
Private Sub WB1_KeyDown(ByVal sender As Object, ByVal e As HtmlElementEventArgs)
If e.KeyPressedCode = 27 Then
RemoveHandler WB1.Document.Body.KeyDown, AddressOf WB1_KeyDown
Task.Run(Sub() CloseWebBrowser())
End If
End Sub
Private Sub CloseWebBrowser()
Dim t As New DateTime
t = Now.AddSeconds(2)
Do
If DateTime.Now > t Then
CloseWB()
Exit Do
End If
Loop
End Sub
My thinking was that that this gave time for the event handler to complete and exit the sub... But NO! Now I get a Cross-Thread error in CloseWebBrowser(). This is no longer just my anal attempt to avoid forcing the user to not have to reach for the mouse. I need to beat this thing! I would greatly appreciate any guidance. Thank You !
Last edited: