I have been working on a touch screen application. I need to know if there exists a ready touch screen keyboard that I can use as a Controller for my application.
I tried using the windows ready keyboard but it is too small for a touch screen.
Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.System) + Path.DirectorySeparatorChar + "osk.exe");
any ideas how to start building one in minimal time will be greatly appreciated....
New Question
I have copied this code from someone and did some modifications to it :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
class Win32
{
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern bool SetWindowPos(
int hWnd, // window handle
int hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
uint uFlags); // window positioning flags
public const int HWND_BOTTOM = 0x0001;
public const int HWND_TOP = 0x0000;
public const int SWP_NOSIZE = 0x0001;
public const int SWP_NOMOVE = 0x0002;
public const int SWP_NOZORDER = 0x0004;
public const int SWP_NOREDRAW = 0x0008;
public const int SWP_NOACTIVATE = 0x0010;
public const int SWP_FRAMECHANGED = 0x0020;
public const int SWP_SHOWWINDOW = 0x0040;
public const int SWP_HIDEWINDOW = 0x0080;
public const int SWP_NOCOPYBITS = 0x0100;
public const int SWP_NOOWNERZORDER = 0x0200;
public const int SWP_NOSENDCHANGING = 0x0400;
}
namespace Keyboard
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.KeyText.MouseDoubleClick += new MouseEventHandler(KeyText_MouseDoubleClick);
}
private Process process;
private string getKeyboardText()
{
KeyScreen k = new KeyScreen();
k.ShowDialog();
if (k.DialogResult.ToString().Equals("OK"))
return k.Text1;
else
return null;
}
void KeyText_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.KeyText.Text = getKeyboardText();
}
private void KeyBtn_Click(object sender, EventArgs e)
{
this.showKeypad();
//Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.System) + Path.DirectorySeparatorChar + "osk.exe");
}
private void showKeypad()
{
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = "c:\\Windows\\system32\\osk.exe";
process.StartInfo.Arguments = "";
process.StartInfo.WorkingDirectory = "c:\\";
process.Start(); // Start Onscreen Keyboard
process.WaitForInputIdle();
Win32.SetWindowPos((int)process.MainWindowHandle,
Win32.HWND_BOTTOM,
300, 300, 1200, 600,
Win32.SWP_SHOWWINDOW | Win32.SWP_NOZORDER);
}
}
}
This works just fine I have a nice keypad (good size for a touch screen), However, i am not familiar with C# and VB at all.... change the Text in a textbox according to the touch screen keyboard I show.
Thanks,
To create your own on screen keyboard you basically need to do the following.
1- Create a windows keyboard application that you can interact with but does not steal the input focus from the current control in which every application you where currently working.
2- The keyboard application should send key presses to the currently active control in response to clicking of buttons in the keyboard application.
The following answer I provided previously provides a simple demonstration of how to do this using WinForms.
C# - Sending keyboard events to (last) selected window
Basically the window is created with the WS_EX_NOACTIVATE style, which prevents the window from becomming active and steeling input focus. Then in response to button clicks it uses SendKeys to send the approriate key press message to the control that has input focus.
The following answer shows how to apply the WS_EX_NOACTIVATE style to a WPF application.
Trying to create a WPF Touch Screen Keyboard Appliaction, Can't get WPF App to Send Keys to another window? Any suggestions?
There are other solutions other than WS_EX_NOACTIVATE, but this is simple and only suffers from a minor presentational glitch when dragging the window arround. Which with some clever message processing can be overcome.
I know this is really, really old but just in case someone else's first thought was also that the built in Windows on screen keyboard is too small (as was also my first thought), you can in fact make it bigger simply by making the window it's in bigger (which you could also do programmatically).
+1 for the question and posting the code though because I'm making one simply because I need one with more direct control over it from my application.
Related
I am having the Problem, that if I alter the LParam of a WM_MOVING message to keep my Form at a certain position, which is legal according to this , the Windows Aero Shake feature gets triggered and all other Windows minimize. The behaviour can be reproduced by creating a Windows Forms Project in Visual Studio and pasting the following code into the Form:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace FormsTest
{
public partial class ShakeTest : Form
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
public const int WM_MOVING = 0x0216;
public ShakeTest()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_MOVING:
{
RECT rec;
rec.bottom = 500;
rec.left = 100;
rec.top = 100;
rec.right = 500;
Marshal.StructureToPtr(rec, m.LParam, true);
m.Result = new IntPtr(1);
}
break;
}
base.WndProc(ref m);
}
}
}
If you now grab the Window's title bar and move the mouse around a bit, the Shake gesture should get triggered, even though the Window isn't moving at all.
I tested this on Windows 10 only so far.
So my question is, can i disable the Shake feature for a certain Window or Process? If not, can i prevent Windows from thinking that im shaking the Window any other Way?
Thanks!
Frankly, I don't know if that is possible to disable Aero Shake for a particular window. But I can suggest a workaround that will prevent the Aero Shake from triggering.
There's a possibility to direct all the mouse input to only one window (and this will also hide the mouse events from the Aero Shake handler). Check the SetCapture description at MSDN. Also we will need a GetCapture and ReleaseCapture functions.
There's one remark: once you have set the mouse capture to a window - you are responsible for handling all the mouse input. So to achieve the goal you'll need to implement your own handler that will move the window. Fortunately, it's not that difficult.
Here's a code sample with a dialog that changes its size when it gets moving and restores the size when the moving is finished. Aero Shake is also never triggered.
public partial class ShakeTest : Form
{
[DllImport("user32.dll")]
static extern IntPtr SetCapture(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr GetCapture();
[DllImport("user32.dll")]
static extern bool ReleaseCapture();
public const int WM_LBUTTONUP = 0x0202;
public const int WM_MOUSEMOVE = 0x0200;
public const int WM_NCLBUTTONDOWN = 0x00A1;
public const int HTCAPTION = 2;
private Point _lastCursorPos;
private Size _origianlSize;
public ShakeTest()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
// We need to get the moment when the user clicked on a non-client area
case WM_NCLBUTTONDOWN:
// We are interested only in a click on a title bar
if ((int) m.WParam == HTCAPTION)
{
// Set the capture so all the mouse input will be handled by this window
SetCapture(Handle);
// Keep the current cursor position to use it during the moving.
_lastCursorPos = Cursor.Position;
// Keep the original window size.
_origianlSize = Size;
// And change the dialog size to whatever you want
Size = new Size(300, 300);
}
break;
// Once we got the capture, we need to handle mouse moving by ourself
case WM_MOUSEMOVE:
// Check that our window has the capture
if (GetCapture() == Handle)
{
// Change the position of a window
Left += Cursor.Position.X - _lastCursorPos.X;
Top += Cursor.Position.Y - _lastCursorPos.Y;
_lastCursorPos = Cursor.Position;
}
break;
// When the left mouse button is released - it's time to release the mouse capture
case WM_LBUTTONUP:
// Check that our window has the capture
if (GetCapture() == Handle)
{
// Release the mouse capture
ReleaseCapture();
// Restore the size
Size = _origianlSize;
}
break;
}
base.WndProc(ref m);
}
}
I have a C# winForms application that makes use of the Windows 8 keyboard.
I open the keyboard by launching tabtip.exe.
I am able to close the keyboard using a PostMessage command like this:
public static void HideOnScreenKeyboard()
{
uint WM_SYSCOMMAND = 274;
uint SC_CLOSE = 61536;
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(KeyboardWnd.ToInt32(), WM_SYSCOMMAND, (int)SC_CLOSE, 0);
}
I think using PostMessage it should be possible to simulate almost anything programmatically if you just pass the correct values.
The values used for closing the keyboard (274 and 61536) I just found on the internet.
It looks that it is possible to grab these values using Spy++, or some other tools but I am unable how to do this.
Can anybody tell me the values needed to simulate a press on the &123 key, so the keyboard switches to the numeric keyboard?
Or, does anybody know how to get these values?
I have tried Spy++, but so many messages are passing constantly that I don't know where to look.
Look at the image of the OnScreenKeyboard to see what key I mean
You could try to use SendInput to simulate a mouse click event on the &123 button of the virtual keyboard window.
Below is an example of how to use SendInput to send a mouse click (left_down + left_up) to the button but I haven't included the code to programatically find the window and get the window size.
[StructLayout(LayoutKind.Sequential)]
public struct MINPUT
{
internal uint type;
internal short dx;
internal short dy;
internal ushort mouseData;
internal ushort dwFlags;
internal ushort time;
internal IntPtr dwExtraInfo;
internal static int Size
{
get { return Marshal.SizeOf(typeof(INPUT)); }
}
}
const ushort MOUSEEVENTF_ABSOLUTE = 0x8000;
const ushort MOUSEEVENTF_LEFTDOWN = 0x0002;
const ushort MOUSEEVENTF_LEFTUP = 0x0004;
// programatically determine the position and size of the TabTip window
// compute the location of the center of the &123 key
int coordinateX = ...
int coordinateY = ...
var pInputs = new[] {
new MINPUT() {
type = 0×01; //INPUT_KEYBOARD
dx = coordinateX,
dy = coordinateY;
dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
time = 0;
dwExtraInfo = IntPtr.Zero;
},
new MINPUT() {
type = 0×01; //INPUT_KEYBOARD
dx = coordinateX,
dy = coordinateY;
dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
time = 0;
dwExtraInfo = IntPtr.Zero;
}
};
SendInput((uint)pInputs.Length, pInputs, MINPUT.Size);
Why don't you set the input scope of the edit control to numeric? New built-in edit controls with the correct properties automatically trigger the numeric mode when touched.
Rather than hacking the Touch Input Panel which appears differently in different locales, etc. set InputScope of the text box to Number and let Windows do the magic.
I have an multithreaded application that needs to be able to preform multiple mouse click at the same time.
I have an IntPtr intptr to a process on which i need to send a mouse click to.
I have tried to find this information on the web and there are some examples which i have tried. But I have not got any of them to work.
As I understand the correct way to solv my issue is to use the function
SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
hWnd is the IntPtr to the process.
Msg is the wanted action, which I want a left click, int WM_LBUTTONDBLCLK = 0x0203;
IntPtr wParam is of no intrest to this problem ( as I understand)
And the coordinates to the click is in lParam.
I construct lParam like,
Int32 word = MakeLParam(x, y);
private int MakeLParam(int LoWord, int HiWord)
{
return ((HiWord << 16) | (LoWord & 0xffff));
}
But as you might understand, I cant get this to work.
My first question is, the coordinates are they within the window of this process or are
the absolut screen coordinates?
And my second question, what am I doing wrong?
I was trying to simulate mouse clicks in C# just recently, I wrote this little helper class to do the trick:
public static class SimInput
{
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);
[Flags]
public enum MouseEventFlags : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
Absolute = 0x8000
}
public static void MouseEvent(MouseEventFlags e, uint x, uint y)
{
mouse_event((uint)e, x, y, 0, UIntPtr.Zero);
}
public static void LeftClick(Point p)
{
LeftClick((double)p.X, (double)p.Y);
}
public static void LeftClick(double x, double y)
{
var scr = Screen.PrimaryScreen.Bounds;
MouseEvent(MouseEventFlags.LeftDown | MouseEventFlags.LeftUp | MouseEventFlags.Move | MouseEventFlags.Absolute,
(uint)Math.Round(x / scr.Width * 65535),
(uint)Math.Round(y / scr.Height * 65535));
}
public static void LeftClick(int x, int y)
{
LeftClick((double)x, (double)y);
}
}
The coordinates are a fraction of 65535, which is a bit odd, but this class will handle that for you.
I'm not 100% sure I understand what you're trying to accomplish. But if you want to simulate mouse input then I'd recommend using the SendInput API.
You can provide an array of inputs to be inserted into the input stream.
See also: PInvoke reference
I don't understand why anyone would want to send multiple mouse clicks simultaneously. If it's to test your GUI, it's the wrong test. No one can physically click something multiple times in the same time space.
But going back to your question, using SendMessage won't help you, because it is basically a blocking call. Even if you tried to use PostMessage, you won't be able to accomplish simultaneous clicks, because the message queue is getting pumped from the UI thread and has messages popped off and handled sequentially.
I used this code to click left button in handle
public static void MouseLeftClick(Point p, int handle = 0)
{
//build coordinates
int coordinates = p.X | (p.Y << 16);
//send left button down
SendMessage(handle, 0x201, 0x1, coordinates);
//send left button up
SendMessage(handle, 0x202, 0x1, coordinates);
}
If you set no handle with calling - then it sends click to Desktop, so coordinates should be for whole screen, if you will set handle, then message will be sent to handle's window and you should set coordinates for window.
How about just using VirtualMouse? I use it in C# and it works great.
public partial class Form1 : Form
{
private VirtualMouse vm = new VirtualMouse();
public Form1()
{
InitializeComponent();
}
private void MouseClickHere(Point myPoint)
{
vm.ClickIt(myPoint, 150);
}
private void Clicker()
{
MouseClickHere(new Point(250,350));
}
}
I would like to create a C# console application to launch multiple instances of IE maximized on multiple monitors.
Update: Here is what I have tried so far. When I launch the second IE instance, it does not open on the second screen. I think it has something to do with the MainWindowHandle since IE may have only one main window handle that it shares with multiple windows. The last line of code actually throws an InvalidOperationException. This code works for launching notepad, but not for IE.
using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TestLauncher
{
class Launcher2
{
[DllImport("user32.dll")]
private extern static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
const int SWP_SHOWWINDOW = 0x0040;
static readonly IntPtr HWND_TOP = IntPtr.Zero;
public void Launch()
{
Process p1 = new Process();
p1.StartInfo.FileName = "iexplore.exe";
p1.StartInfo.Arguments = "microsoft.com";
p1.Start();
p1.WaitForInputIdle(2000);
System.Threading.Thread.Sleep(2000);
Rectangle monitor = Screen.AllScreens[0].WorkingArea;
SetWindowPos(p1.MainWindowHandle, HWND_TOP, monitor.Left, monitor.Top, monitor.Width, monitor.Height, SWP_SHOWWINDOW);
Process p2 = new Process();
p2.StartInfo.FileName = "iexplore.exe";
p2.StartInfo.Arguments = "google.com";
p2.Start();
p2.WaitForInputIdle(2000);
System.Threading.Thread.Sleep(2000);
Rectangle monitor2 = Screen.AllScreens[1].WorkingArea;
SetWindowPos(p2.MainWindowHandle, HWND_TOP, monitor2.Left, monitor2.Top, monitor2.Width, monitor2.Height, SWP_SHOWWINDOW);
}
}
}
If possible, I am seeking a solution that is flexible enough to launch other applications besides IE also.
I have created a custom action for my setup project and have successfully implemented a form that displays a progress bar for a download step in my install (I'm using a WebClient in my custom action code). So I have two questions that relate to each other.
Is there any way to show a download progress bar in the main setup window rather than creating a separate form that I display as I have done? I would prefer this.
If not, then what can I do to cause my form to display in front of the actual setup window when I call form.ShowDialog()? I've also called BringToFront() on it which doesn't work either. It's there, but it's always behind the main setup window. Seems there has to be some way to get the correct z-order.
Thanks for your help.
So I gave up on the idea of integrating the progress bar into the actual installer screen, but it's just plain ridiculous what it takes to get the Windows Form to display on top. I have to get a handle to the installer Window and send it to the background because bringing the progress bar window forward simply won't work. I've moved to Mac development now so coming back to this is just frustrating. I remember thinking C# .NET was pretty cool. It's got NOTHING on Cocoa/Objective-C.
It's infuriating having a method called BringToFront() that simply ignores you. Why do I have to drop down to Windows API code to do something as fundamental to a GUI as managing the the Z-Order? Z-Order? Seriously?
In case you're wondering, here's what I ended up doing (via google):
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern bool SetWindowPos(
IntPtr hWnd, // window handle
IntPtr hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
uint uFlags); // window positioning flags
public const uint SWP_NOSIZE = 0x1;
public const uint SWP_NOMOVE = 0x2;
public const uint SWP_SHOWWINDOW = 0x40;
public const uint SWP_NOACTIVATE = 0x10;
[DllImport("user32.dll", EntryPoint = "GetWindow")]
public static extern IntPtr GetWindow(
IntPtr hWnd,
uint wCmd);
public const uint GW_HWNDFIRST = 0;
public const uint GW_HWNDLAST = 1;
public const uint GW_HWNDNEXT = 2;
public const uint GW_HWNDPREV = 3;
public static void ControlSendToBack(IntPtr control)
{
bool s = SetWindowPos(
control,
GetWindow(control, GW_HWNDLAST),
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
I get a handle to the installer window and then call ControlSendToBack() on it. It works, but it sends it to the very back. I tried another method that would just send it back one position, but this wouldn't work either. Windows programming--as good as it was in 1995. Cool.
Another way of doing this is to use a BackgroundWorker. You let the Background Worker handle the downloading of the file so it doesn't prevent the UI being updated.
See this link on donnetperls