I've written a WPF touchscreen application. Within this application I've written a user control which is a touch screen keyboard.
I have all the keys working apart from the backspace. Obviously all the keys are buttons and on the backspace button click I'd like to send the back space key to the focused textbox.
I've tried the following but this just inserts a square character in my textbox:
private void buttonBackSpace_Click(object sender, RoutedEventArgs e)
{
PresentationSource source = PresentationSource.FromDependencyObject(CurrentControl);
//CurrentControl is my Textbox
KeyEventArgs ke = new KeyEventArgs(Keyboard.PrimaryDevice, source, 0, Key.Back)
{
RoutedEvent = UIElement.KeyDownEvent
};
System.Windows.Input.InputManager.Current.ProcessInput(ke);
}
Any ideas? I'm using Visual Studio 2012 & Windows 8.
I'm not sure if this is a typo or not, but I think your issue is that
KeyEventArgs ke = new KeyEventArgs(Keyboard.PrimaryDevice, source, 0, Key.Back)
Should actually be:
KeyEventArgs ke = new KeyEventArgs(Keyboard.PrimaryDevice, source, 0, Keys.Back)
I think the Keys enumeration is what you're actually looking for here.
EDIT: The above answer does not work. The below answer should, however, solve the problem.
private void buttonBackSpace_Click(object sender, RoutedEventArgs e)
{
CurrentControl.Focus();
keybd_event(BACK, 0, KEYEVENTF_KEYDOWN, 0);
keybd_event(BACK, 0, KEYEVENTF_KEYUP, 0);
}
// Virtual Keypress Function
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
public const int KEYEVENTF_KEYDOWN = 0x0001; //Key down flag
public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
public const int BACK = 0x08; // Backspace keycode.
Related
I have a multi-line text box that displays some values based on data it gets given, (Generally one value per line).
(For the purpose of having a tool tip popup with some 'alternative' data) I would like to get the word (or at the very least the line) that the mouse is hovering over so I can then find what alternative to display.
I have a few ideas of how to do this with calculations based on the text box and font sizes but I do not what to go down this road as the sizes and fonts may change frequently.
So... Is there any way of using the mouses position to grab specific text box text?
Here's an alternate solution. Add this MouseMove event to your TextBox:
private void txtHoverWord_MouseMove(object sender, MouseEventArgs e)
{
if (!(sender is TextBox)) return;
var targetTextBox = sender as TextBox;
if(targetTextBox.TextLength < 1) return;
var currentTextIndex = targetTextBox.GetCharIndexFromPosition(e.Location);
var wordRegex = new Regex(#"(\w+)");
var words = wordRegex.Matches(targetTextBox.Text);
if(words.Count < 1) return;
var currentWord = string.Empty;
for (var i = words.Count - 1; i >= 0; i--)
{
if (words[i].Index <= currentTextIndex)
{
currentWord = words[i].Value;
break;
}
}
if(currentWord == string.Empty) return;
toolTip.SetToolTip(targetTextBox, currentWord);
}
Use the GetCharIndexFromPosition method to map the mouse's position to an index in the whole Text. From that position, progress left and right till you have the whole word.
To get the mouse position, use the MouseHover event, so that you get it just when it's still and not every time (that would make things slow).
My solution uses a trick to achieve what you want.
When you double click inside a text area, it select the underlying word.
So using a RichTextBox (TextBox does flash on mouse events) on your form you can simulate double click when the middle mouse button is clicked (something like Babylon dictionary). If you want you can use MouseHover instead of MouseDown, too. It works.
public partial class Form3 : Form
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
public Form3()
{
InitializeComponent();
timer.Interval = 50;
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
MessageBox.Show(richTextBox1.SelectedText);
// do more stuff here, e.g display your tooltip for the selected word or anything else
richTextBox1.SelectionLength = 0; // remove the highlighted color of selection
}
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
private const uint MOUSEEVENTF_RIGHTUP = 0x10;
public void DoMouseDoubleClick()
{
//Call the imported function with the cursor's current position
uint X = (uint)Cursor.Position.X;
uint Y = (uint)Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
timer.Start(); // some delay is required so that mouse event reach to RichTextBox and the word get selected
}
private void richTextBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
DoMouseDoubleClick();
}
}
}
Hi i have a c# application and an embedded browser in it,its task is to find a link and then right click on it and click on properties!
mouse moves programmatically,so i need to find properties in righ click menu!
can you help me how to do this?
i tried pressing 'r' after right click but it didn't work on some computers!
so i need to do it by moving mouse!
here is my code for finding a link and right clicking:
int x = getXoffset(link);
int y = getYoffset(link);
webBrowser1.Document.Window.ScrollTo(x, y);
Linker.Win32.POINT p2 = new Linker.Win32.POINT();
webBrowser1.Focus();
p2.x = webBrowser1.Left + 10;
p2.y = webBrowser1.Top + 5;
Linker.Win32.ClientToScreen(this.Handle, ref p2);
Linker.Win32.SetCursorPos(p2.x, p2.y);
MouseOperations.GetCursorPosition();
MouseOperations.MouseEvent(MouseOperations.MouseEventFlags.LeftDown);
MouseOperations.MouseEvent(MouseOperations.MouseEventFlags.RightDown);
MouseOperations.MouseEvent(MouseOperations.MouseEventFlags.RightUp);
Any other idea for reaching properties on right click meny is welcomed
use this code:
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
public static void PressKey(Keys key, bool up)
{
const int KEYEVENTF_EXTENDEDKEY = 0x1;
const int KEYEVENTF_KEYUP = 0x2;
if (up)
{
keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);
}
else
{
keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);
}
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate("http://google.com");//Your link
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//Find your link and right click(automatically by your code)
webBrowser1.Document.MouseDown += new HtmlElementEventHandler(Document_MouseDown);
}
void Document_MouseDown(object sender, HtmlElementEventArgs e)
{
if (e.MouseButtonsPressed == MouseButtons.Right)
{
Thread.Sleep(1000);
PressKey(Keys.P, true);
PressKey(Keys.P, false);
}
}
I have a ListBox with SelectionMode = MultiExtended. I want the default behavior for the ListBox to be "append". In other words, the behavior you get when holding down the control key should be the default, passive functionality for the ListBox.
How would I do this? Do I need to subscribe to the "Mouse Down" and "Key Down" events manually? Is there a setting I'm missing?
Thanks.
Ugly solution but the best I could do.
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
public const byte KEYEVENTF_KEYUP = 0x02;
public const int VK_CONTROL = 0x11;
private void listBox1_MouseEnter(object sender, EventArgs e)
{
keybd_event(VK_CONTROL, (byte)0, 0, 0);
}
private void listBox1_MouseLeave(object sender, EventArgs e)
{
keybd_event(VK_CONTROL, (byte)0, KEYEVENTF_KEYUP, 0);
}
Use MultiSimple Mode
http://msdn.microsoft.com/en-us/library/system.windows.forms.selectionmode(v=vs.80).aspx
SelectionMode = SelectionMode.MultiSimple
I made an on screen keyboard with c# Windows Forms. I use Sendkeys.Send() function to send the keystrokes. All letters but the letter i works fine. When I press the letter i on the keyboard when Microsoft Word is open, it sends Ctrl + Alt + I and opens the print dialog. It is same in Notepad++ as well. But it works fine when I try to type in notepad.
In my code I send the keys with SendKeys.Send(value); where value is the text of the button which is pressed. I get the text with the following code:
string s = ((Button)sender).Text;
Any comments about why it does not work properly?
Edit: I have created a new windows forms project with just a button and the whole code is below. Still not working. Any idea would be appreciated.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SendKeys.Send("i");
}
// Prevent form being focused
const int WS_EX_NOACTIVATE = 0x8000000;
protected override CreateParams CreateParams
{
get
{
CreateParams ret = base.CreateParams;
ret.ExStyle |= WS_EX_NOACTIVATE;
return ret;
}
}
}
The overridden function is to prevent the form being focused. So that I can send the keystrokes to the other application which has the focus.
Two alternatives:
1-
Simulates a keypress, see http://msdn2.microsoft.com/en-us/library/system.windows.forms.sendkeys(VS.71).aspx
Sample:
public static void ManagedSendKeys(string keys)
{
SendKeys.SendWait(keys);
SendKeys.Flush();
}
2- Sends a key to a window, pressing the button for x seconds
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
public static void KeyboardEvent(Keys key, IntPtr windowHandler, int delay)
{
const int KEYEVENTF_EXTENDEDKEY = 0x1;
const int KEYEVENTF_KEYUP = 0x2;
keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);
Thread.Sleep(delay);
keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);
}
Your aren't calling the "SetForegroundWindow" Win32 API method. Therefore, your "SendKeys" call is likely sending the keys to your app, not the target app as intended.
Here's an example on MSDN:
How to: Simulate Mouse and Keyboard Events in Code
Also, here's the code from the example:
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
namespace SimulateKeyPress
{
class Form1 : Form
{
private Button button1 = new Button();
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
button1.Location = new Point(10, 10);
button1.TabIndex = 0;
button1.Text = "Click to automate Calculator";
button1.AutoSize = true;
button1.Click += new EventHandler(button1_Click);
this.DoubleClick += new EventHandler(Form1_DoubleClick);
this.Controls.Add(button1);
}
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
// Send a series of key presses to the Calculator application.
private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");
// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr.Zero)
{
MessageBox.Show("Calculator is not running.");
return;
}
// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}
// Send a key to the button when the user double-clicks anywhere
// on the form.
private void Form1_DoubleClick(object sender, EventArgs e)
{
// Send the enter key to the button, which raises the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys.Send("{ENTER}");
}
}
}
I've got this code:
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);
[Flags]
public enum MouseEventFlags
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
Absolute = 0x8000
}
public void SimMouseEvent(MouseEventFlags e, int x, int y)
{
mouse_event((uint)e, (uint)x, (uint)y, 0, UIntPtr.Zero);
}
public void SimLeftClick(int x, int y)
{
SimMouseEvent(MouseEventFlags.LeftUp | MouseEventFlags.RightUp, x, y);
}
My form looks like this:
When you click "Button" it runs this:
private void button3_Click(object sender, RoutedEventArgs e)
{
SimLeftClick(50, 50);
}
And on my Window I also have this:
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("click");
}
When I click the window it says "click" as expected, but when I click "Button" it doesn't seem to do anything.
Are the coordinates absolute, or relative? What about with multiple monitors? Do they only work on the focused application?
I would expect that 50,50 to either hit my window somewhere and trip the "click" handler or click on some random window because it missed my app completely and focus that instead... why isn't anything happening?
You handle a mouse button down message, but send a mouse button up message. A click needs to be button down followed by the same button up.
The coordinates are ignored, because you didn't pass the Move flag.
Try reading the documentation.
Fixed, with Ben's suggestions.
public void SimLeftClick(int x, int y)
{
var scr = Screen.PrimaryScreen.Bounds;
SimMouseEvent(MouseEventFlags.LeftDown | MouseEventFlags.LeftUp | MouseEventFlags.Move | MouseEventFlags.Absolute,
(int)(x / (double)scr.Width * 65535),
(int)(y / (double)scr.Height * 65535));
}