.NET Forum / .NET Framework / Interop / July 2007
DSO Framer event not firing: axFramerControl1_PreviewKeyDown
|
|
Thread rating:  |
Brian - 25 Mar 2007 13:56 GMT Hi!
We are using DSOFramer to host MS Word within our WinForm-based smart client app.
Anywhere in our app, pressing F1 raises our context-sensitive help dialog. When our users are inside MS Word within our app and press F1, we bring up a Help dialog that explains what they should be typing in within that segment of the Word document. And we give a link to open up Word's Help, if that's what they want.
However, as we have it implemented now, there's a race condition. Sometimes it works perfect. Sometimes, the MS Word process gets the F1 before we can take it... at which point Word's help opens up immediately (simultaneously with our dialog).
We've tried to fix this by using the following event handler exposed by DSOFramer:
private void axFramerControl1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { if (e.KeyData == Keys.F1) e.IsInputKey = false; }
However, after hooking it up, we can never get it to step into. We don't think its ever getting fired.
Has anyone been able to use this event handler successfully?
Any suggestions on how to intercept the F1 key consistently?
Thanks,
Brian
Walter Wang [MSFT] - 26 Mar 2007 06:27 GMT Hi Brian,
Word still runs in its own process even you're hosting the ole document in your WinForm (you can observe the WinWord.exe process in task manager). Therefore, it's difficult for WinForm's PreviewKeyDown to intercept the F1 key from seeing by WinWord. We will need a low level keyboard hook in your process to intercept the key.
#SetWindowsHookEx Function () http://msdn2.microsoft.com/en-us/library/ms644990.aspx
I've created following class to do hook the keyboard:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; using System.Windows.Forms;
namespace WindowsApplication1 { class KeyboardHook : IDisposable { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private IntPtr _hookID = IntPtr.Zero;
public event KeyEventHandler KeyDown;
public KeyboardHook() { _hookID = SetHook(new LowLevelKeyboardProc(HookCallback)); }
#region IDisposable Members
public void Dispose() { UnhookWindowsHookEx(_hookID); }
#endregion
private IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } }
private delegate IntPtr LowLevelKeyboardProc( int nCode, IntPtr wParam, IntPtr lParam);
private IntPtr HookCallback( int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { int vkCode = Marshal.ReadInt32(lParam); Keys key = (Keys)vkCode; if (KeyDown != null) { KeyEventArgs args = new KeyEventArgs(key); KeyDown(this, args); if (args.Handled) { return new IntPtr(1); // indicate processed } } } return CallNextHookEx(_hookID, nCode, wParam, lParam); }
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); } }
To install the hook, modify your Program.cs as:
static class Program { public static KeyboardHook kh;
[STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); using (kh = new KeyboardHook()) { Application.Run(new Form1()); } } }
The class KeyboardHook will raise an event KeyDown whenever a key is intercepted, however, according to documentation:
#LowLevelKeyboardProc Function () http://msdn2.microsoft.com/en-us/library/ms644985.aspx
It's recommended not to cause too much delay when handling the hook message; and I understand you're probably using a modal dialog when the F1 is pressed, therefore I suggest use a timer to delay the showing of the modal dialog:
public partial class Form1 : Form { public Form1() { InitializeComponent();
Program.kh.KeyDown += new KeyEventHandler(kh_KeyDown); }
private bool fInCall = false; private Timer tmrDelayedCall;
void kh_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.F1 && !fInCall) { e.Handled = true; fInCall = true; tmrDelayedCall = new Timer(); tmrDelayedCall.Interval = 1; tmrDelayedCall.Tick += new EventHandler(tmrDelayedCall_Tick); tmrDelayedCall.Start(); } }
void tmrDelayedCall_Tick(object sender, EventArgs e) { tmrDelayedCall.Stop(); MessageBox.Show("F1"); fInCall = false; } }
Intercepting all keys in the hook and raise events for them may not be necessary if you only need to intercept the F1 key, you can check the key in the hook and raise event accordingly.
Please try this and let me know the result on your side. Thanks.
Sincerely, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. If you are using Outlook Express, please make sure you clear the check box "Tools/Options/Read: Get 300 headers at a time" to see your reply promptly.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT] - 28 Mar 2007 11:25 GMT Hi Brian,
Have you seen my last reply? What do you think of the suggestion?
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Brian - 03 Apr 2007 20:49 GMT > Hi Brian, > > Have you seen my last reply? What do you think of the suggestion? Yes, Walter... I thought I responded to your note with a big thank you... but I guess it didn't go out... sorry.
We will be testing what you gave us thoroughly in the coming week; I'll let you know how it works... or if we have additional questions.
Thanks!!
Brian
Walter Wang [MSFT] - 04 Apr 2007 02:04 GMT Hi Brian,
Thanks for your follow-up. Please feel free to reply here if the issue is still not solved or you need anything else.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Brian - 22 May 2007 04:26 GMT > Thanks for your follow-up. Please feel free to reply here if the issue is > still not solved or you need anything else. Here is a note from my colleague who is trying out your code... he's going to continue playing with it to get a clearer idea of what is happening... but I thought you might be able to give some guidance...
When attempting to test this code I am receiving an error when I first hit a key:
CallbackOnCollectedDelegate was detected Message: A callback was made on a garbage collected delegate of type 'TCPSM!TCPSM.Utility.KeyboardHook+LowLevelKeyboardProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
I placed the hook field in at the Program class level (as the example showed) so it should not have been collected during the life of the application run. Not sure why this is happening. I will go back try this with a simpler test app to see if I can get it working.
-J
Walter Wang [MSFT] - 22 May 2007 09:05 GMT Hi Brian,
Please modify the original code:
public KeyboardHook() { _hookID = SetHook(new LowLevelKeyboardProc(HookCallback)); }
to:
private LowLevelKeyboardProc m_callback; public KeyboardHook() { m_callback = new LowLevelKeyboardProc(HookCallback); _hookID = SetHook(m_callback); }
This should fix it.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT] - 25 May 2007 03:07 GMT Hi Brian,
Does the fix worked for you? The reason of this fix is to keep the delegate at class level and the GC will not collect it later.
Let me know if there's anything unclear.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Brian - 22 Jun 2007 22:47 GMT [Originally sent on May 23, 2007]
> Hi Brian, > > Please modify the original code: ...
> This should fix it. And indeed it did! Thanks. Works... and its nice to be using a managed hook vs. what we were doing.
Many thanks!!
Brian
Walter Wang [MSFT] - 25 Jun 2007 02:45 GMT Hi Brian,
Thanks for the confirmation.
Have a nice day.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
yepuri.jyothi@gmail.com - 10 Jul 2007 08:42 GMT Hi Walter,
I am also facing same issue as Brain. We have hosted Word using DSO Framer in our Application.
When user clicks certain shortcut like Ctrl+s, ESC, F5...application should respond to these events...but Word is responding to these events.
I have tried your solution, but its working only for single Keys not for Ctrl+S. Also i need to bubble the event to be handled by my Form.
Control order is some thing like this
Application Form TabControl Panel Axframer Word
We tried with ProcessCmdKey. but not working
Thanks jyothi
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|