This might be a simple question, but I have a winforms app that is loading a ChromiumWebBrowser control (CefSharp) and I can't figure out how to capture key preview events as they are all being swallowed by the control.
The standard attaching a handler to the PreviewKeyDown event of the browser control isn't working. Is there a known workaround?
CEF is run in it's own message loop, so the standard events don't work.
The first an easiest option is to implement IKeyboardHandler, you can check the CefSharp source for a more detailed example (there's one that forwards messages to the parent window if required).
Second run with settings.MultiThreadedMessageLoop = false, and call Cef.DoMessageLoopWork() on application idle, this will integrate CEF into the same message loop as your main application. Again, the source contains examples see https://github.com/cefsharp/CefSharp/blob/cefsharp/49/CefSharp.WinForms.Example/Program.cs#L63
The third option is to hook into the CEF message loop, see https://github.com/cefsharp/CefSharp/blob/cefsharp/49/CefSharp.WinForms.Example/ChromeWidgetMessageInterceptor.cs for an example
CEF = Chromium Embedded Framework - CefSharp is just a wrapper.
Related
Another application displays a messagebox (with a unique text inside it), user chooses Yes/No.
How to detect what he pressed in c#? (best in .Net up to 3.5). I could do polling with FindWindowEx (on another thread) but how to detect what button had been pressed? Also I don't think polling is the best way to do the job.
I need to know what the user has chosen in another app, so I can react accordingly in my own app. I don't have access to the other app's source code. Also to make it clear I don't want to click any of the buttons myself. I'm not afraid of a bit of c++, winapi and pinvoke
To monitor UI events in another application you can use UI Automation. To solve your specific problem you need to subscribe to a particular event (see Subscribing to UI Automation Events). To do so call IUIAutomation::AddAutomationEventHandler with a UIA_Invoke_InvokedEventId Event Identifier.
While UI Automation can be used to solve your problem, it is an assistive technology, mainly to enable accessibility needs and automated UI testing.
You could use either Anonymous or Named Pipes or WCF(Windows Communications Foundation).
I use a webbrowser control in my application to get data from a specific web page. This web page won't work with the older IE because it specifically checks for the IE version. So I made a registry change that allows my application to work as IE 9 and everything is ok most of the time...
The problem is when a newwindow has to be opened. It won't display anything. I guess that the newwindow is acknowledged as IE 7 and I don't know how to make it disguise itself as IE9.
I also tried the other way round. I thought that if I intercepted the newwindow url then I could just send it to IE9 or open it in another instance of a webbrowser control. But the newwindow event only allows to cancel the event. You can't get any useful information out of it.
I believe that interop services is what I need but I know nothing about them.
So I've got two questions:
(1) Can I make the newwindow identify as IE9? (and how...)
(2) How can I get the newwindow url using interop services (or anything, I wouldn't care)?
It is quite strange (from my perspective) that the WebBrowser control doesn't surface the much-more-useful NewWindow3 event.
This CodeProject article describes a remarkably simple way to make it available.
In the NewWindow event, assuming your first Wb control is named WB1 and the one you want to redirect to is WB2, do the following in your WB1 NW event.
Processed = True ' This cancels the current request.
WB2.Navigate URL ' This redirects it to the second WB2 control.
Otherwise, if you want to use the NW2 (NewWindow2) event instead of the NewWindow (NW) event, do this in the NW2 event of the WB1 control.
Set ppDisp = WB2.object ' Just swaps the objects around to redirect, don't need to issue a cancel.
Also, you can do this via BeforeNavigate2 (of WB1). But slightly different code.
Cancel = True ' Cancel Request.
WB2.Navigate2 URL ' Reissue it to WB2.
Now, as long as you control where it redirects to, you can get the new window URL easily, using WB2.LocationURL or Wb2.Document.URL if i am not mistaken.
Also, if you want to change the rendering engine to IE9 (even if IE9 is installed on your computer, WB control will use IE7 rendering engine for compatibility)... there are articles online and answers on SO (including some of my previous answers) which clarify how you can alter the registry to ensure the rendering engine used by the WB control is the same as that of the installed version (IE9), otherwise, it will always use IE7. And, if you have IE4, 5 or 6 installed on a machine, it will always use IE4 for the rendering engine. I think they update teh rendering version after ever 3-4 version changes. I'm assuming during version 10, WB control rendering version will be version 10 as well.
Let me know if you need more assistance with it and i've love to know how you got along and if this helped answer your question. All my examples are in VB6, but you can transform them easily.
Cheers.
I've been looking around for quite a while, and can't seem to find a good way to do this.
Basically I have a C# process using WPF (which has no visible window), that I need to handle WM_ events in (such as WM_CLOSE or WM_DESTROY for example; so that I can elegantly shutdown when a user chooses to log off or restart their machine).
There are a number of solutions I've seen out there that suggest using System.Windows.InteropServices to call AddHook and provide it a pointer to a function that then becomes the WndProc. The problem with this is, as far as I can tell, it depends on the window actually being visible (and in this case there is no window).
Another way that's suggested but doesn't work is to override the WndProc method of a WinForm, but this process has no visible forms or windows.
I've also found things referring to a Message-only Window. Some kind of invisible window that still receives WM_ events. From what I've seen, this is only available in a Microsoft.WindowsCE.Forms assembly. I added a reference to this assembly in my project and subclassed MessageWindow as indicated at: http://msdn.microsoft.com/en-us/library/microsoft.windowsce.forms.messagewindow.aspx but it still seems to not work. The breakpoints inside the WndProc are not being hit.
Any clue?
Think about what you are asking- if you don't have a window, how could your application receive a window message (considering that messages are sent to a window's handle).
That's like saying "how can I receive email without having an email address?"
Michael Entin covers windows' behavior during shutdown here.
I am 99% sure that all processes running in a user's session are automatically closed when the user logs off anyway, so this shouldn't be an issue. If you really must handle this window message, you can create a hidden window as per Any way to create a hidden main window in C#?
This may be a long short or not even possible but no harm in asking.
What I am trying to do is monitor an application for any new windows it creates in its MDI control. I have implemented hooking in C# and can capture the MDICREATE window message but because I need to get information about the window after is has been created the MDICREATE message isn't much help because at that stage the window hasn't been created in the other application yet.
Without going into to much detail I just need to be able to see when a new window has been created.
Is this possible?
Thanks
I'm not aware of another message that gets the info that you are looking for off hand. But if that message works for you, you could hook that message and then do another scan of the windows to find the one you are missing. You can enumerate the child windows of the parent window. Use Spy++ to see the exact window hierarchy.
If you can watch for a particular function call, I would use some kind of hooking library to grab that (EasyHook comes to mind).
You can hook the MDI create function (assuming there is one), watch for that, then inn your code, call the original and do any lookups using the returned value. You'll have access to the returned value and any parameters, so you should be able to get some info out of those.
Two options off the top of my head.
Hook the WM_MDIACTIVATE event, the first time the window is being activated, use a flag to determine the first time the window is being activated.
If you need to run your code after the WM_MDICREATE or WM_MDIACTIVATE, you can post a new custom message from one of these messages, which is then handled after these messages have completed. You then write your code to handle the custom message.
I posted this answer (more of an idea really) but haven't been able to find out for sure which message triggers a WinForms Form.Load event. From Spy++ and some reading I suggested it might be WM_SHOWWINDOW, but I'd like to be sure.
Also, other than Spy++ is there a better way to see exactly which windows message triggered a .Net event? Even after switching off some event types in Spy++ the log window fills up very quickly.
Thanks.
There isn't a specific windows message which corresponds to the Load event on the Form class. The event is simply fired the before first time the window is made visible after the creation of the window handle of the Form.
It's used for initialization which requires the window handle of the Form to be created but before the Form is shown for the first time.
I'm guessing here, but it might be instructive to configure your dev environment to use Microsoft's source server, then have a look through the System.Windows.Forms code. See Shawn Burke's blog entry Configuring Visual Studio to Debug .NET Framework Source Code.