word add-in, KeyDown handling on combobox in customui - c#

Blockquote
Need some help with CustomUI in Word add-in.
I have a
<combobox />
in my custom ui.
How can I handle Enter pressing by user ?
I need to perform some actions when user presses Enter in that ComboBox.
Can I add KeyDown event somehow or maybe cast IRibbonControl to something useful?
UPDATE :
Made decision not to include that functionality. But still interested in solution for that problem.

Even WindowSelectionChange event wont help you. It works for other Key press but not for Enter and Backspace (As I am aware of).
You have to use low level keyboard hook
EDITED**
There is a callback when any of the key been pressed it will be called.
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr) WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
//Check if the enter key is pressed
if (vkCode == (int) Keys.Enter )
// Do here whatever you need
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

Related

SetWindowsHookEx not working properly

I have tried to make a global mousehotkey with SetWindowsHookEx() so when I press the right mouse button it executes some code. My problem is that when the callback function gets executed, it gives me a weird number for the right button that keeps changing everytime the code gets executed.
private static IntPtr ButtonHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
int button = Marshal.ReadInt32(lParam);
if (nCode >= 0 && wParam == (IntPtr)WM_RBUTTONDOWN)
{
if (button == 0x02)
{
_m.rtbLog.AppendText("Test");
}
}
return CallNextHookEx(MainWindow._hookId, nCode, wParam, lParam);
}
When I read lParam it gives me like a number around 600 and changes everytime the code gets executed even though it should be 0x2.
How can I fix this :P.
EDIT: It works perfectly when I do it with keys
0x02 means WM_MOUSEMOVE, which should come from wParam rather lParam. The lParam means MOUSEHOOKSTRUCT, which will frequently change as for containing x- and y-coordinates of the cursor. Just refer to [MouseProc callback function][1] and [MOUSEHOOKSTRUCT structure][2]
[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms644988(v=vs.85).aspx
[2] https://msdn.microsoft.com/en-us/library/windows/desktop/ms644968(v=vs.85).aspx

Multiple character inputs for single physical press

I am attempting to process the windows messages for keyboard events and pass them into an awesomium webview. The webview has native handling for windows events, but the host program must capture them, and send them on.
I am using .net and the com interop to capture and send on the messages. The key events are passed on to the best of my knowledge, but the input is variable. For example, there are varying numbers of characters being entered in a text box for a single press.
Here is a sample of the code I am using (credit to Sekhat on the awesomium site) :
private void CreateHook()
{
uint threadId = Win32.GetWindowThreadProcessId(hWnd, IntPtr.Zero);
//hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_CALLWNDPROC, wndProcDelegate, IntPtr.Zero, threadId);
hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_GETMESSAGE, wndProcDelegate, IntPtr.Zero, threadId);
}
private int WndProcHook(int nCode, IntPtr wParam, ref Win32.Message lParam)
{
if (nCode >= 0)
{
Win32.TranslateMessage(ref lParam);
WndProc(ref lParam);
}
return Win32.CallNextHookEx(hHook, nCode, wParam, ref lParam);
}
wndProcDelegate = WndProcHook;
Am I handling the events wrong, leading to the variable number of inputs? I beleive the relevant parts are above, but can post the rest if needed.
On a side note, when I use WH_KEYBOARD instead of WH_GETMESSAGE an AccessViolationException is thrown. Is the KEYBOARD event the right one to use? Thank you for any assistance.
EDIT: I have done some further investigation and discovered that multiple messages of type 0x102 (WM_CHAR) are being passed to my program. The number passed matches the number of characters that awesomium is then outputting. Should I limit this to only the first message? While this may work, I would still like to know why this is happening.
I have managed to devise a working fix:
if (message.msg == 256)
{
accept = true;
}
if (accept && message.msg == 258)
{
view.InjectKeyboardEventWin((int)message.msg, (int)message.wparam, (int)message.lparam);
accept = false;
}
if (message.msg != 258)
{
view.InjectKeyboardEventWin((int)message.msg, (int)message.wparam, (int)message.lparam);
}
This code checks for a key down, and if found, set accept to true. The char message is only processed if a key down has been received since the last one. This allows text entry, while preserving other messages. I am still interested in discovering the root cause however.

Detect keyup on winform without any control

As stated in title, I have a form that doesn't have any control on itself (so I can't focus it!!! damn).
I keep it controlless because I need to show images on background and I need to move it by keeping mouse clicked.
Are there any way to detect the keyup event when this is the foreground window?should I use a global hook (and check which is the foreground image obviusly)?
Any simplier workaround?I tested with an hidden control but it's not working.
The problem of putting a control with opacity = 0 brings the possibility to "miss" the MouseDown and MouseUp events (because they could happen over the control instead of the form, but I can still redirect them)
Any suggestion?
Here is the question where I picked some resources:
Fire Form KeyPress event
Can't you just set the Form's KeyPreview to true and use the Form's KeyUp Event? (or am i missing something?)
I would override OnKeyUp as it seems to be exactly what you are asking for. Here is an example of popping up a Message Box when the Escape key is released.
protected override void OnKeyUp(KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("Escape was pressed");
e.Handled = true;
}
base.OnKeyUp(e);
}
It looks that you are seeking for GlobalHook. Please have a look at SetWindowsHookEx Native Api. You can easily write your Pinvoke statements.
Here is an example from pinvoke.net
using System.Windows.Forms;
public class MyClass
{
private HookProc myCallbackDelegate = null;
public MyClass()
{
// initialize our delegate
this.myCallbackDelegate = new HookProc(this.MyCallbackFunction);
// setup a keyboard hook
SetWindowsHookEx(HookType.WH_KEYBOARD, this.myCallbackDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
}
[DllImport("user32.dll")]
protected static extern IntPtr SetWindowsHookEx(HookType code, HookProc func, IntPtr hInstance, int threadID);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private int MyCallbackFunction(int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0) {
//you need to call CallNextHookEx without further processing
//and return the value returned by CallNextHookEx
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
// we can convert the 2nd parameter (the key code) to a System.Windows.Forms.Keys enum constant
Keys keyPressed = (Keys)wParam.ToInt32();
Console.WriteLine(keyPressed);
//return the value returned by CallNextHookEx
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
}

C# Write text when key held down

I've got a C# console application with some pieces of text that represent buttons so for example it looks like this [ D ][ E ][ F ][ G ]
When the user presses the button I want the button to be highlighted which is no problem as what im currently doing is rewriting over the button with Console.BackgroundColor set.
What I want to do is that they key be constantly highlighted while the key is held down but as soon as the key is lifted again the highlighting to be removed, if possible i'd also like multiple keys to be pressed at the same time. This is what I can't figure out how to do?
Hope that makes sense :)
Any help?
Thanks
If you are willing to add a reference to Windows.Forms, call Application.Run() to run a message queue, and call external Windows DLLs, you can do it using this code: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
That page will show you how to hook the low-level key-down keyboard event.
To also hook key-up keyboard events, you'll need to add a WM_KEYUP constant:
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
And then modify the HookCallback method:
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine("Down:" + (Keys)vkCode);
}
else if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine("Up:" + (Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
That will give you "Up" and "Down" messages for every key press. From there you should be able to incorporate it into your app.
Good luck!
Sorry but Console App only has Keyboard event (that too not actually an event unless you are in a loop and check for keypress) No KeyDown. keyPress or KeyUp events. It has no events of the GUI world.
I'm afraid AFAIK that a Console app can't detect multiple simultaneous key presses (that aren't modifier keys such as shift, or ctrl) so that isn't going to work.
With regard to highlighting a key as long as it is pressed you need to have your Console.ReadKey in a loop. Something like the following (you need to implement RemoveHighlight and HighlightKey methods yourself):
ConsoleKeyInfo currentKeyPressed;
ConsoleKeyInfo lastKeyPressed;
do
{
currentKeyPressed = Console.ReadKey();
if (lastKeyPressed.Key == currentKeyPressed.Key)
continue;
RemoveHighlight();
HighlightKey(keyPressed.Key);
lastKeyPressed = currentKeyPressed;
} while ((keyPressed.Key & ConsoleKey.Escape) != ConsoleKey.Escape);

Using a low-level keyboard hook to change keyboard characters

I'm creating a custom keyboard layout. As the beginning step, I want to have the user press a key, have my keyboard hook intercept it, and output a different key of my choosing.
I found this keyboard hook code, which I'm trying to slightly modify for my purposes:
http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
I've changed the relevant method to this:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
KBDLLHOOKSTRUCT replacementKey = new KBDLLHOOKSTRUCT();
Marshal.PtrToStructure(lParam, replacementKey);
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, true);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
I want it to declare a new KBD structure object, copy the KBD structure supplied by the keyboard hook into it, modify my object's vkCode to use a different character, and then overwrite the supplied object with my modified version. This should hopefully keep everything the same except for the fact that it writes a different character.
Unfortunately, it's not working. The original keyboard character is typed. The Visual Studio output pane also gets a A first chance exception of type 'System.ArgumentException' occurred in MirrorBoard.exe error.
What can I do here to intercept the keyboard hook and replace it with a character of my choosing?
Thanks!
The second parameter for Marshal.PtrToStructure must be a class not a struct and KBDLLHOOKSTRUCT is probably a struct.
Instead you should use it like this:
KBDLLHOOKSTRUCT replacementKey = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, false);

Categories

Resources