I have a cefSharp:ChromiumWebBrowser that loads various web pages for our WPF application.
One of these web pages handles keyboard shortcuts like (Alt+S and Alt+C). If the page is called from an external browser these shortcuts work as expected.
But when the shortcuts are used in the cefSharp:ChromiusWebBrowser Control they don't work.
I tried to figure out whether the Shortcuts get handled by the UserControl that contains the browser control by using
private bool _altKeyPressed = false;
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (_altKeyPressed)
{
_altKeyPressed = false;
if (e.SystemKey == Key.S || e.SystemKey == Key.C)
{
e.Handled = false;
}
}
if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt)
{
_altKeyPressed = true;
}
base.OnPreviewKeyDown(e);
}
I tried it with e.Handled = true and e.Handled = false. This code gets called but changing the Handled Property brought no improvement.
I also tried the same approach by hooking up to the PreviewKeyDown EventHandler like this
<cefSharp:ChromiumWebBrowser x:Name="_browser" PreviewKeyDown="_browser_OnPreviewKeyDown">
I am not showing the code for _browser_OnPreviewKeyDown because it is the same as in the OnPreviewKeyDown. Also this code gets called and has no change in behavior whether Handled is set to true or false.
Does anyone know how I can make the Chromium Control behave the same as an external browser in terms of Shortcuts?
Update
The browser did not have a keyboard handler. So I made one.
Please see the comments in OnKeyEvent to see where I am stuck at the moment.
Thank you
public class KeyboardHandler : IKeyboardHandler
{
private bool _cefAltKeyPressed;
public bool OnPreKeyEvent(IWebBrowser chromiumWebBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut)
{
const int KEY_C = 67;
const int KEY_S = 83;
bool result = true;
if (_cefAltKeyPressed)
{
if (windowsKeyCode == KEY_C || windowsKeyCode == KEY_S)
{
isKeyboardShortcut = true;
result = false;
}
_cefAltKeyPressed = false;
}
if ((modifiers & CefEventFlags.AltDown) != 0 && type == KeyType.RawKeyDown)
{
_cefAltKeyPressed = true;
}
return result;
}
public bool OnKeyEvent(IWebBrowser chromiumWebBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
// With the code in OnPreKeyEvent, OnKeyEvent is only called, when Alt + S or Alt + C is pressed in the browser
// So what am I supposed to do with this Event now?
// I do not want to implement a search (Alt + S) or clear (Alt + C) functionality here, since that is part of the web site
// I just want the website to be able to receive the Alt + S and Alt + C keystrokes and allow it to handle it
return false;
}
}
Related
I am having quite an issue in C# right now I am trying to code a function that detects when the F8 button is pushed and set the bool F8Pushed to true then when it is pushed again set F8Pushed to false.
Here is the code I have so far:
static bool IsKeyPressed() //This Function Returns True if F8 Is Pushed and False if F8 is up
{
bool is_pressed = (GetAsyncKeyState(119) & 0x8000) != 0;
return is_pressed;
}
static void CheckHotKey() //This is the Function that I am calling the other function from for debugging.
{
while (true)
{
Console.WriteLine(IsKeyPressed());
}
}
Now the problem that I am having and cannot resolve is that I cant find a way to get the variable to copy its self to another variable and be able to go back to false if that makes sense. I can get a bool set to true if IsKeyPressed() == true however I cannot figure out how to get it back to false when it returns true again.
Thanks in advance!
EDIT:
Thanks for you help guys however I am still having some trouble heres an update.
static bool IsKeyPressed()
{
is_pressed = (GetAsyncKeyState(119) & 0x8000) != 0 && !is_pressed;
return is_pressed;
}
static void CheckHotKeys()
{
while (true)
{
IsKeyPressed();
if(is_pressed)
{
F8Pushed = true;
}
Console.WriteLine(F8Pushed);
if(IsKeyPressed())
{
F8Pushed = false;
}
Console.WriteLine(F8Pushed);
}
}
I managed to get it to work kinda however it is very buggy and alot of times the key stroke doesnt detect any ideas?
I'm not sure whether I fully understand what you are trying to accomplish. Your code contains so many problematic parts, that I choose to write a completely new code:
class Program
{
const byte VK_F8 = 0x77;
const byte VK_ESC = 0x1b;
static bool globalAppState = false;
static void Main(string[] args)
{
bool lastState = IsKeyPressed(VK_F8);
while (!IsKeyPressed(VK_ESC))
{
bool newState = IsKeyPressed(VK_F8);
if (lastState != newState)
{
if (newState)
{
Console.WriteLine("F8: pressed");
globalAppState = !globalAppState;
}
else
Console.WriteLine("F8: released");
lastState = newState;
}
}
}
static bool IsKeyPressed(byte keyCode)
{
return ((GetAsyncKeyState(keyCode) & 0x8000) != 0);
}
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(int vKey);
}
Function IsKeyPressed(VK_F8) tells you always the current state (pressed/released) of the specified key.
When you need to do some action only on change (from pressed to released, or from released to pressed) replace the console output functions with your specific task.
When you need some multi-threading like processing the event in a new thread, that is a different question... (outside of this scope)
EDIT: Added change of variable on each new key pressed event. This is dirty solution...
You have to make that variable is_pressed as global to keep current state. then make a Try like this:
static bool is_pressed;
static bool IsKeyPressed()
{
is_pressed = (GetAsyncKeyState(119) & 0x8000) != 0 && !is_pressed;
return is_pressed;
}
Where && !is_pressed will toggles the value for you every time
Assuming you're storing the result of the key press in a boolean:
bool isKeyPressed = true;
You could then do this:
isKeyPressed == IsKeyPressed() && !isKeyPressed;
We are working on providing touch resizing support for our control in WinForms and our requirement was to show the touch resizing PopUp when touching the app and closing the PopUp when an MouseUp or MouseDown event occurs.
We can differ the touch by using the constant value WM_GESTURE = 0x0119, but PointerUp and PointerDown are also becoming TRUE when touched and we're not able to differ the mouse touch from the other events.
Is there any way to specifically identify the mouse?
switch (m.Msg)
{
case WM_TOUCH:
IsTouchEnabled = true;
break;
case WM_POINTERUP:
IsTouchEnabled = false;
break;
case WM_POINTERDOWN:
IsTouchEnabled = false;
break;
}
Thanks
You can differentiate the touch down and mouse down by using GetMessageExtraInfo method like below.
protected override void OnMouseDown(MouseEventArgs e)
{
Console.WriteLine("IsTouch: " + IsTouch());
base.OnMouseDown(e);
}
public bool IsTouch()
{
uint extra = GetMessageExtraInfo();
bool isTouchOrPen = ((extra & 0xFFFFFF00) == 0xFF515700);
if (!isTouchOrPen)
return false;
bool isTouch = ((extra & 0x00000080) == 0x00000080);
return isTouch;
}
[DllImport("user32.dll")]
private static extern uint GetMessageExtraInfo();
You may find if the CapsLock key has been pressed subscribing to the KeyDown/KeyUp event. And then toggle the state of the CapsLock based on that input. The problem with this approach is that you need the initial state of the CapsLock key to start toggling that.
One application of this could be giving the user a notification on a Login Page (this is what i need).
By the way i'm using Silverlight 5.
EDIT
The solution posted here says:
You can however find out if Capslock is on by making use of
KeyEventArgs.PlatformKeyCode that's actually send at onKeyDown.You can
look up the Virtual Key-code for capslock in here:
http://msdn.microsoft.com/en-us/library/ms927178.aspx
With this solution you can't determine the CapsLock state, because KeyEventArgs.PlatformKeyCode returns "an integer value that represents the key that is pressed or released (depending on which event is raised)". So if CapsLock is On and Key A is pressed then KeyEventArgs.PlatformKeyCode = 65, and on the other hand if CapsLock is off and Key A is pressed then KeyEventArgs.PlatformKeyCode = 65.
In other words you can't determine if the CapsLock is enabled or not based on the KeyEventArgs.PlatformKeyCode property.
The answer to this question also seems to have a solution, it checks two things:
the letter typed is Upper Case and Shift isn't pressed
the letter typed is Lower Case and Sift is pressed
Both of this cases implies that the CapsLock is On, but there is also a problem with this solution, given a KeyEventArgs you can know the pressed key in the keyboard but can't know the Char outputted by that key.
I'd suggest using a Behavior for this detection since you can hook into the PasswordChanged and KeyDown events to determine if the Caps Lock is on. Here is a quick behavior I wrote to detect if the Caps Lock is on. You can bind to the CapsLockOn behavior and use something like a data state behavior to hide/show your warning message.
public class DetectCapsLockBehavior : Behavior<PasswordBox>
{
private int _lastKey;
private ModifierKeys _modifiers;
[Category("Settings")]
public bool CapsLockOn
{
get { return (bool)GetValue(CapsLockOnProperty); }
set { SetValue(CapsLockOnProperty, value); }
}
public static readonly DependencyProperty CapsLockOnProperty = DependencyProperty.Register("CapsLockOn", typeof(bool), typeof(DetectCapsLockBehavior), new PropertyMetadata(null));
protected override void OnAttached()
{
AssociatedObject.PasswordChanged += new RoutedEventHandler(AssociatedObject_PasswordChanged);
AssociatedObject.KeyDown += new KeyEventHandler(AssociatedObject_KeyDown);
}
void AssociatedObject_KeyDown(object sender, KeyEventArgs e)
{
_lastKey = e.PlatformKeyCode;
_modifiers = Keyboard.Modifiers;
}
void AssociatedObject_PasswordChanged(object sender, RoutedEventArgs e)
{
if (_lastKey >= 0x41 && _lastKey <= 0x5a)
{
var lastChar = AssociatedObject.Password.Last();
if (_modifiers != ModifierKeys.Shift)
{
CapsLockOn = char.ToLower(lastChar) != lastChar;
}
else
{
CapsLockOn = char.ToUpper(lastChar) != lastChar;
}
}
}
}
NOTE: This is sample code, so there could be bugs. Just trying to demonstrate how it could be done.
region KeysDetection
bool bCaps = false;
bool bIns = false;
bool bNum = false;
public void FloatableWindow_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.CapsLock:
bCaps = !bCaps;
lbl_caps.Opacity = (bCaps) ? 1 : 0.5;
break;
case Key.Insert:
bIns = !bIns;
lbl_ins.Opacity = (bIns) ? 1 : 0.5;
break;
case Key.Unknown:
{
if (e.PlatformKeyCode == 144)
{
{
bNum = !bNum;
lbl_num.Opacity = (bNum) ? 1 : 0.5;
}
}
break;
}
}
}
#endregion
Assuming that I'm in a function that is called in a Timer on in Windows Forms class... how can I tell if the user is currently attempting to "Drag" something?
example:
public void SomeMethod()
{
// This doesn't exist of course :)
if (Mouse.IsDragging) ...
}
EDIT: I should specify that I know that I can override DragEnter and DragLeave to set my own private variable... but I'm asking/looking for a '.Nety' solution if one exists.
Easy:
bool mDragging;
...
mDragging = true;
DoDragDrop("test", DragDropEffects.All);
mDragging = false;
Universal:
public static bool IsDragging()
{
StackFrame[] frames = new StackTrace(false).GetFrames();
foreach (StackFrame frame in frames)
{
System.Reflection.MethodBase mb = frame.GetMethod();
if (mb.Module.Name == "System.Windows.Forms.dll" && mb.Name == "DoDragDrop")
return true;
}
return false;
}
Difficult question. The answer is probably no, if all I found in the Intertubes is right, but it is worth a try. I need to override the Ctrl + Shift + Esc and the Ctrl + Esc combinations. It would be good to be able to override the Win key combinations, but I have a low level hook that does such, I only wish I didn't need it. If I can manage to block the start menu and the task manager entirely by policy, the overrides will no longer be needed but I couldn't find the correct policy to do so.
You can override Ctrl + Esc (I just tried in AutoHotkey, it works), but not Ctrl + Shift + Esc, no more than Ctrl + Alt + Del.
So using policies is probably the way to go... No experience in this field, I fear.
In case someone comes here looking for a non-AutoHotKey, here is a c# way.
It is possible to do this using a keyboard hook. A good hook class for this can be found on this CodeProject Article
Using the below code will prevent the WIN+LEFT or WIN+RIGHT from occurring. You can use this to override whichever keys you'd like.
This will even override hotkeys which you added via RegisterHotKey Win API.
Once you have those classes in your project you can add handlers to the static HookManager class like below.
//It's worth noting here that if you subscribe to the Key_Press event then it will break the international accent keys.
HookManager.KeyPress += HookManager_KeyPress;
HookManager.KeyDown += HookManager_KeyDown;
HookManager.KeyUp += HookManager_KeyUp;
You can also add mouse events, but for simplicity I'm just showing the keyboard hook.
I've also created a generic list so that I know which keys are currently down and I remove those keys from the list on the KeyUp event.
public static List<Keys> keysDown = new List<Keys>();
private static void HookManager_KeyDown(object sender, KeyEventArgs e)
{
//Used for overriding the Windows default hotkeys
if(keysDown.Contains(e.KeyCode) == false)
{
keysDown.Add(e.KeyCode);
}
if (e.KeyCode == Keys.Right && WIN())
{
e.Handled = true;
//Do what you want when this key combination is pressed
}
else if (e.KeyCode == Keys.Left && WIN())
{
e.Handled = true;
//Do what you want when this key combination is pressed
}
}
private static void HookManager_KeyUp(object sender, KeyEventArgs e)
{
//Used for overriding the Windows default hotkeys
while(keysDown.Contains(e.KeyCode))
{
keysDown.Remove(e.KeyCode);
}
}
private static void HookManager_KeyPress(object sender, KeyPressEventArgs e)
{
//Used for overriding the Windows default hotkeys
}
public static bool CTRL()
{
//return keysDown.Contains(Keys.LShiftKey)
if (keysDown.Contains(Keys.LControlKey) ||
keysDown.Contains(Keys.RControlKey) ||
keysDown.Contains(Keys.Control) ||
keysDown.Contains(Keys.ControlKey))
{
return true;
}
else
{
return false;
}
}
public static bool SHIFT()
{
//return keysDown.Contains(Keys.LShiftKey)
if (keysDown.Contains(Keys.LShiftKey) ||
keysDown.Contains(Keys.RShiftKey) ||
keysDown.Contains(Keys.Shift) ||
keysDown.Contains(Keys.ShiftKey))
{
return true;
}
else
{
return false;
}
}
public static bool WIN()
{
//return keysDown.Contains(Keys.LShiftKey)
if (keysDown.Contains(Keys.LWin) ||
keysDown.Contains(Keys.RWin))
{
return true;
}
else
{
return false;
}
}
public static bool ALT()
{
//return keysDown.Contains(Keys.LShiftKey)
if (keysDown.Contains(Keys.Alt))
{
return true;
}
else
{
return false;
}
}
So you need do override Hotkeys on your application?
Then the answer is probably yes, how?
No idea, but if this(http://www.inchwest.com/mapkeyboard.aspx) program can, so can you