We've been using unhandled exceptions for ages and we register both Application.Current.DispatcherUnhandledException and AppDomain.CurrentDomain.UnhandledException
but the following repro case using Drop Event handler does not trigger any unhandled exception handler.
When I throw the exception from UI or task, some handler will be triggered, but form the documentation I don't comprehend why no handler is triggered in my scenario below as I would expect the Dispatcher calling DispatcherUnhandledException
This is VS 2015 with .net 4.5.2
Repro WPF code is very simple, only AllowDrop and Drop handler. Note: The handlers are registered in the window ctor, same behaviour when doing that in app.xaml.cs.
Just drag & drop any file into it, a message box should appear but it does not.
<Window x:Class="unhandledex_wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" AllowDrop="True" Drop="MainWindow_OnDrop">
<Grid>
</Grid>
</Window>
Code behind:
using System;using System.Threading.Tasks;using System.Windows;
namespace unhandledex_wpf
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Application.Current.DispatcherUnhandledException += ( sender, args ) => MessageBox.Show( "Exception" );
AppDomain.CurrentDomain.UnhandledException += ( sender, args ) => MessageBox.Show( "Exception" );
TaskScheduler.UnobservedTaskException += ( sender, args ) => MessageBox.Show( "Exception" );
// works Task.Run( ( )=> { throw new Exception( "foo" ); } );
}
private void MainWindow_OnDrop( object sender, DragEventArgs e )
{
throw new NotImplementedException("Catch me");
}
}
}
If you want to handle an exception during a drop event you must handle it within your Drop event handler. Please refer to Peter Ritchie's answer in the following thread on the MSDN forums for more information about why: https://social.msdn.microsoft.com/Forums/windows/en-US/8beb1aba-1699-46c7-84dc-38768c7a21f6/treeview-dragdrop-event-ignores-exceptions-help?forum=winforms
Jay Wang (MSFT) has confirmed this in the WPF forum: https://social.msdn.microsoft.com/Forums/vstudio/en-US/a336acc8-5a29-45aa-b84a-8e235a0f838a/wpf-drop-event-hides-thrown-error?forum=wpf
Related
In my WinForms app I used WebView2 to show thrird-party content.
When user clicks the link (or other navigation element) inside the webView, the target link should be opened in the default browser (not in the webView).
For most cases I was able to implement desired behaviour with NewWindowRequested and NavigationStarting events.
But for anchor navigation inside the current page (<a href="#my_anchor">) these events are not firing.
There is a SourceChanged event, which is fired in case on anchor navigation, and it even allows to determine that this is in-page navigation by checking IsNewDocument, but it does not allow to cancel the navigation.
I was thinking about js-based solution, something like subscribing to click events for all a tags or even for whole document with further filtering. But I realized that such a solution will not work in many non-trivial cases, including
dynamically created a elements
keyboard navigation (TAB to select link, Enter to initiate action, so no click event)
the cases when there are a lot of elements (img, etc) inside a element and user clicked on such an internal element
when navigation is initiated with js
So, is the way exists to handle and cancel any navigation, including anchors in the current page?
I had the same request. I'm using Win32 C++, and for me the NewWindowRequested event does fire on anchor navigation, and I added this implementation to cancel the default behaviour and open the Uri in the default browser instead...
// Register a handler for the NewWindowRequested event.
CHECK_FAILURE(m_webView->add_NewWindowRequested(
Callback<ICoreWebView2NewWindowRequestedEventHandler>(
[this](ICoreWebView2* sender, ICoreWebView2NewWindowRequestedEventArgs* args) {
// get the target Uri
LPWSTR sUri;
CHECK_FAILURE(args->get_Uri(&sUri));
// and if it was user initiated (e.g. click on an anchor tag)
BOOL bUserInit;
CHECK_FAILURE(args->get_IsUserInitiated(&bUserInit));
if (bUserInit) {
// cancel default behaviour
args->put_Handled(TRUE);
// and open Uri in default browser
ShellExecute(0, 0, sUri, 0, 0, SW_SHOW);
}
return S_OK;
})
.Get(), nullptr));
I also faced this issue, as a workaround I've made this:
//MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="MainWindow"
x:Class="WebBrowser.MainWindow"
mc:Ignorable="d"
FontSize="14" Title="WebView2 Test" Width="400" Height="400" WindowStartupLocation="Manual"
SizeToContent="Manual" Cursor="Wait"
WindowStyle="None" ResizeMode="NoResize" PreviewKeyDown="AdvertisementWindow_PreviewKeyDown">
<DockPanel>
<wv2:WebView2 Name="myWebBrowser"/>
</DockPanel>
</Window>
MainWindow.xaml.cs Source code
using System.Windows;
using System.Windows.Input;
using Microsoft.Web.WebView2.Core;
namespace WebBrowser
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string url = "https://en.wikipedia.org/wiki/Hyperlink";
public MainWindow()
{
InitializeComponent();
InitializeAsync();
myWebBrowser.NavigationStarting += MyWebBrowser_NavigationStarting;
myWebBrowser.SourceChanged += MyWebBrowser_SourceChanged;
}
private void MyWebBrowser_SourceChanged(object sender, CoreWebView2SourceChangedEventArgs e)
{
string uri = myWebBrowser.Source.ToString();
if (e.IsNewDocument == false && uri.EndsWith("#Further_reading"))
{
MessageBox.Show("You clicked #Further_reading", "Further Reading");
}
}
async void InitializeAsync()
{
await myWebBrowser.EnsureCoreWebView2Async(null);
myWebBrowser.CoreWebView2.Navigate(url);
}
private void AdvertisementWindow_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if(e.Key == Key.Escape)
{
Close();
}
}
private void MyWebBrowser_NavigationStarting(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs e)
{
//cancel the current event
if (!e.Uri.ToString().StartsWith(url))
{
e.Cancel = true;
System.Diagnostics.Process.Start(e.Uri.ToString());
}
}
}
}
This code should open each link in an external browser (the default system browser) and anchors to external pages will be opened in the external browser too. So it means that we cancel navigating in the WebView (e.Cancel = True). Regarding anchors to the same site, we can handle them in the SourceChanged event, and we don't need to stop navigating as it will stay on the same page.
I have a fairly simple C# WPF application using .NET 5. Basically it sits in the background and times specific events for the end user. The events are built from a xml file that is generated externally.
The application consists of 2 windows, one hidden that does all the thinking. If it detects that an event is due it raises a toast message which when clicked on opens the other window to show the event details to the user. All works fine and runs as expected except after a windows sleep/suspend and resume. We obviously don't want the events to add up upon sleep/suspend and so we close the hidden window and upon resume open it again. No problems there but once the system is resumed and an event is raised the visible window refuses to show. If the visible window is open when sleep/suspend happens then upon resume the whole window is frozen and refuses to respond (only way to close the window is kill the application and restart)
The APP code is as follows :-
public static Forms.NotifyIcon notifyIcon;
public static MainWindow mw;
public static ConfigWindow cw;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// Obtain the arguments from the notification
ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
// Obtain any user input (text boxes, menu selections) from the notification
ValueSet userInput = toastArgs.UserInput;
// Need to dispatch to UI thread if performing UI operations
Application.Current.Dispatcher.Invoke(delegate
{
ToastControl.HandleToast(args);
});
};
ConfNotifyIcon();
OpenApp();
}
private void ConfNotifyIcon()
{
notifyIcon = new Forms.NotifyIcon();
notifyIcon.Icon = new System.Drawing.Icon("Images/Wellformation.ico");
notifyIcon.DoubleClick += OnClick;
notifyIcon.ContextMenuStrip = new Forms.ContextMenuStrip();
notifyIcon.ContextMenuStrip.Items.Add("Open", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClick);
notifyIcon.ContextMenuStrip.Items.Add("Close", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClose);
notifyIcon.ContextMenuStrip.Items.Add(new Forms.ToolStripSeparator());
notifyIcon.ContextMenuStrip.Items.Add("Exit", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnExit);
}
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Suspend:
this.Dispatcher.BeginInvoke((Action)(() =>
{
PrepareLock();
}), null);
break;
case PowerModes.Resume:
this.Dispatcher.BeginInvoke((Action)(() =>
{
PrepareAwake();
}), null);
break;
default:
break;
}
}
private void PrepareAwake()
{
OpenApp();
ConfNotifyIcon();
notifyIcon.Visible = true;
}
private void PrepareLock()
{
notifyIcon.Dispose();
cw.Close();
}
private void OnExit(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
private void OnClose(object sender, EventArgs e)
{
mw.Close();
}
private void OnClick(object sender, EventArgs e)
{
OpenMain();
}
private void OpenMain()
{
mw = new();
mw.Show();
mw.Activate();
}
public static void OpenApp()
{
cw = new ConfigWindow();
}
The hidden Window XAML is as follows :-
<Window x:Class="WellformationDesktopApplication.ConfigWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WellformationDesktopApplication"
mc:Ignorable="d"
Title="ConfigWindow" Height="1" Width="1" Visibility="Hidden" WindowState="Minimized">
<Grid>
</Grid>
</Window>
with code as follows :-
Timer at = new();
public ConfigWindow()
{
BuildConfig();
InitializeComponent();
}
public void refreshconfig()
{
myObjects.Clear();
myObjects = NudgeManager.GetNudges();
NudgeHandler(myObjects);
}
public void BuildConfig()
{
myObjects.Clear();
myObjects = GetEvents(); // pulls a list of event names with intervals from the config file
EventHandler(myObjects); //Goes through the list of events and figures out when the next event is due based upon the interval in the configuration
ActionTimer();
}
private void ActionTimer()
{
at.Interval = 60000;
at.Elapsed += ChecktActions;
at.AutoReset = true;
at.Enabled = true;
}
private void ChecktActions(object sender, ElapsedEventArgs e)
{
//Go through the trigger times for all events and see if those time have passed, if they have raise a toast showing the event name.
//If an event is raised reset the trigger time for the event based upon the interval and reset that time.
}
and the visible window XAML is as follows :-
<Window x:Class="WellformationDesktopApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WellformationDesktopApplication"
mc:Ignorable="d"
ResizeMode="NoResize"
WindowStyle="None"
Title="MainWindow" Height="500" Width="800" Background="{x:Null}" Foreground="{x:Null}" AllowsTransparency="True">
<Grid x:Name="BG">
<TextBlock x:Name="Display" HorizontalAlignment="Left" Margin="546,13,0,0" Text="Show event name and appropriate information about the event here..." VerticalAlignment="Top" FontSize="22"/>
</Grid>
</Window>
With Code as follows :-
public MainWindow()
{
InitializeComponent();
setstyles();
this.MouseLeftButtonDown += delegate { DragMove(); };
}
We know that everything to do with the ConfigWindow works fine, we know it is closed upon suspend and a new one is opened on resume with new timings set and all the appropriate alerts working.
The issue is with MainWindow as after a suspend and resume it cannot be interacted with at all. The open button on the icon does nothing, if the window is opened is is completely frozen and cannot be interacted with in any way, and if a toast is clicked on the window does not open but the rest of the toast handling code works fine around it. This happens on Win8, Win10 and Win11.
Any help out there as I am completely at a loss for how this is happening?
Thanks
After much work and going through the code section by section commenting it out to see if it made a difference I have found the issue.
Buried deep inside the the code for the hidden window (4 calls to functions down the line) I found that the EventHandler() was also raising a listener for
SystemEvents.SessionSwitch += new SessionSwitchEventHandler(OnSessionSwitch);
With all the associated functions buried in a separate class that was not directly referenced from the window itself.
When this line was commented out everything worked fine, with it in and attached to the hidden window after Suspend/Resume of windows no UI changes would take place throughout the whole code (hence hidden window continued to working completely fine as it did not interact with the UI).
By lifting this code out into the APP space and handling it there rather than in a window the problem has gone away (though has revealed other issues that were not being handled upon Resume of Windows that I now have to fix).
So the answer is that for a WPF application listeners for SystemEvents of any type need to be housed int the APP code space and not within windows.
My English skill is poor because I'm not a native English speaker.
My application has a MainWindowView and MainWindowBehavior also MainWindowView has control(Editor) as the following code.
<MainWindowView>
<Grid>
<TabControl>
<TabItem>
<Grid>
<Editor x:Name="editor"/>
</Grid>
</TabItem>
</TabControl>
</Grid>
<i:Interaction.Behaviors>
<behaviors:MainWindowBehavior/>
</i:Interaction.Behaviors>
</MainWindowView>
MainWindowBehavior uses the property of Editor in the LoadedEventHandler of MainWindowView.
The following code shows the above logic.
protected override void OnDetaching()
{
this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
base.OnDetaching();
}
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.Loaded += AssociatedObject_Loaded;
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
this.mainWindow = sender as MainWindow;
// run time error
this.mainWindow.editor.Parser.ParsingFailed += Parser_ParsingFailed;
}
But compiler shows run time error because of the value of the Parser property of the editor is null.
I tried to initialize the parser property of the editor at the Constructer, OnApplyTemplate function, Loaded EventHandler but 3 cases all called late than Loaded EventHandler of MainWindow.
And as a result, generate run time error.
I think that the Loaded EventHandler of the editor must be called early more Loaded EventHandler of the MainWindowBehavior. But in fact, the sequence reverse.
I don't know why the sequence reverse.
How can I change the loading sequence as I thought?
Thank you for reading.
Maybe you cannot change the sequence of events, but you can sure change the way you listen to these events. I suggest you to hook-up to an event in your mainWindow that will indicate you when its editor property is set.
Your code would become:
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
this.mainWindow = sender as MainWindow;
// Here we don't access mainWindow.editor anymore, we hook-up to an event instead
this.mainWindow.OnEditorPropertyChanged += MainWindow_EditorPropertyChanged;
}
private void MainWindow_EditorPropertyChanged(object sender){
{
var mainWindow = sender as MainWindow;
if (mainWindow.editor != null) {
mainWindow.editor.Parser.ParsingFailed += Parser_ParsingFailed;
}
}
And in your MainWindow, make sure to raise an event when its editor property is set, for example:
public delegate void OnEditorPropertyChangedEventHandler(object sender);
public event OnEditorPropertyChangedEventHandler OnEditorPropertyChanged;
// Backing field
private Editor _editor;
public Editor editor {
get => _editor;
set => {
_editor = value;
OnEditorPropertyChanged?.Invoke(this); // Raise the event
}
}
I found the cause of my problem while following your advice.
I think the OnApplyTemplate function of the Editor is called early than the Loaded event of the MainWindowView. But, in fact, the OnApplyTemplate function of the Editor is not called.
I have been apprehending wrong about my problem. I'm sorry...
Now I would make my problem right.
The Editor is Custom-Control. I missed adding code in the Generic.xaml file the following code.
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/WpfControls;component/Themes/Editor.xaml"/>
</ResourceDictionary.MergedDictionaries>
Now I added the above code in the Generic.xaml and the OnApplyTemplate function of Editor is called normally also it is called early than the Loaded event of the MainWindowView.
Thank you for your help and interest in my problem.
I find when an exception occurs in MainWindow#Window_Closing method, even I set the e.cancel = true before the exception and e.handled = true in App#DispatcherUnhandledException, the application still shutdown.
I set a breakpoint in Application_Exit method and the stacktrace shows the shutdown is called by ExceptionWrapper.InternalRealCall -> Application.ShutdownCallback -> Application.ShutdownImpl -> Application.DoShutdown
Could anybody help me understand why this happens and is there any way to avoid application shutdown when exception happens in Window_Closing method? (I know I can always catch all exception in this method but I'd like to know if there is any better approach to avoid unexpected exception kill the application)
Below is sample code to reproduce this issue. Click the window close button to reproduce this issue.
Thanks.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
throw new Exception();
}
}
App.xaml.cs
public partial class App : Application
{
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
}
private void Application_Exit(object sender, ExitEventArgs e)
{
var exitCode = e.ApplicationExitCode;
}
}
App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml" DispatcherUnhandledException="Application_DispatcherUnhandledException" Exit="Application_Exit">
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Closing="Window_Closing">
It's fine catching the DispatcherUnhandledException, but that's not the end of it. If you catch it and set Handled to true, then the application just says OK, and shuts down. If Handled is set false, it says 'Still needs a bit of a check' and then if the AppDomain UnhandledException is set it calls that:
In your App.xaml.cs file:
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = false;
}
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(string.Format("Is Terminating: {0}\r\n{1}", e.IsTerminating, e.ExceptionObject.ToString()));
}
Here the CurrentDomain_UnhandledException method is only called is I set Handled to false. Either way, the apps going down.
Note that UnhandledExceptionEventArgs doesn't have a Handled property, but it does have an IsTerminating one. I'm not sure under what circumstances that would be false, though.
EDIT - Turns out that IsTerminating will only be false when compatibility is set to .NET 1.0 and 1.1 as in those versions of the framework an unhandled exception in some background threads would not cause the app to close. Since 2.0, all unhandled exceptions will cause the app to close.
If you look at the WPF source, you will see that this is by design. There is even an explicit comment to that effect:
// Event handler exception continuality: if exception occurs in Closing event handler, the
// cleanup action is to finish closing.
CancelEventArgs e = new CancelEventArgs(false);
try
{
OnClosing(e);
}
catch
{
CloseWindowBeforeShow();
throw;
}
I guess it makes sense, since you wouldn't want a bug to prevent the user closing a window.
I came across this few days back during one of my WPF projects. Yes, it is possible to prevent the application from shutting down on unhandled exceptions. Just let the application know that the exception is handled so that the application does not take additional actions. Makes sense right?
Wherever you initialize the application or have access to the Application Instance, add an event 'DispatcherUnhandledException' to the object of the instance. You will preferably have to add the event invoke function to App.xaml.cs of your WPF project.
Add this to the Constructor of App.
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
Then add the Current_DispatcherUnhandledException function within the same class.
public static void Current_DispatcherUnhandledException (object sender, DispatcherUnhandledExceptionEventArgs e)
{
var errorBox = new Core.Common.UI.WPF.MessageBox();
errorBox.Error(e.Exception.Message);
//Log to Database
var logger = Logger.NLogger.GetLogger("My-Logger");
logger.Error(e.Exception, e.Exception.Message);
e.Handled = true;
}
You could also Log the exceptions externally to DB, File System.
e.Handled = true; This line tells the application that the exception is handled and not to worry about it.
PRO TIP - Make sure no exceptions happen within the DispatcherHandledException, else the Application will still close down.
I have a pretty simple problem but I can't get it to work. I want a MessageBox to appear each time I left click inside my form. I didn't know how to capture it on the whole form so I started of trying to capture my left click inside my WebBrowser1. However, nothing really happens when trying to trigger the event.
I declared the action as WebBrowser1_Mousedown.
private void WebBrowser1_Mousedown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
MessageBox.Show("test");
}
}
What am I doing wrong?
My relevant XAML as follows:
<Window x:Class="IndianBrowser.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="488.806" Width="807.089" MouseDown="Window_MouseDown">
and now trying with the webbrowser:
<WebBrowser x:Name="WebBrowser1" HorizontalAlignment="Stretch" Height="auto" Margin="0,85,0,0" VerticalAlignment="Stretch" Width="auto" MouseDown="WebBrowser1_Mousedown"/>
If you look into MSDN documentation for WebBrowser class, you'll see that mouse events are not supported. What you can do instead is subscribe for HtmlDocument.MouseDown event.
Update
Here is small snippet that demonstrates how to do this in WPF, NOTE you will have to add reference to Microsoft.mshtml assembly:
public MainWindow()
{
InitializeComponent();
this.webBrowser1.Navigated += webBrowser1_Navigated;
this.webBrowser1.Source = new Uri("your url");
}
void webBrowser1_Navigated(object sender, NavigationEventArgs e)
{
HTMLDocumentClass document = this.webBrowser1.Document as HTMLDocumentClass;
document.HTMLDocumentEvents2_Event_onclick += document_HTMLDocumentEvents2_Event_onclick;
}
bool document_HTMLDocumentEvents2_Event_onclick(IHTMLEventObj pEvtObj)
{
// here you can check if the clicked element is your form
// if (pEvtObj.fromElement.id == "some id")
MessageBox.Show("test");
return true;
}