I'm creating a winform application which require the windows on screen keyboard to fill up a text box. I have 4 text boxes. I created 4 textbox click event to pop up the keyboard when user click the textbox.
public Form1()
{
InitializeComponent();
textBox1.Click += textBox1_Click;
textBox2.Click += textBox2_Click;
textBox3.Click += textBox3_Click;
textBox4.Click += textBox4_Click;
}
private void textBox1_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("osk");
}
private void textBox2_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("osk");
}
private void textBox3_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("osk");
}
private void textBox4_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("osk");
}
The problem I face is, if I first click on textbox1 after running the app, the keyboard will only able to type into textbox1. After that if I click other textBox, it won't be able to type anything in.
Same as if I first click on textbox2 after running the app, the keyboard will only able to type into textbox2. After that if I click other textBox, it won't be able to type anything in.
Do you guys know what's wrong?
I would do something like this:
Add the following class to your project:
class TouchKeyboardProvider
{
#region Private: Fields
private readonly string _virtualKeyboardPath;
#endregion
#region ITouchKeyboardProvider Methods
public TouchKeyboardProvider()
{
_virtualKeyboardPath = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles),
#"Microsoft Shared\ink\TabTip.exe");
if (!System.IO.File.Exists(_virtualKeyboardPath))
{
_virtualKeyboardPath = _virtualKeyboardPath.Replace(" (x86)", string.Empty);
}
}
public void ShowTouchKeyboard()
{
try
{
Process.Start(_virtualKeyboardPath);
}
catch (Exception ex)
{
// TODO: Log error.
Debug.WriteLine(ex.ToString());
}
}
public void HideTouchKeyboard()
{
var nullIntPtr = new IntPtr(0);
const uint wmSyscommand = 0x0112;
var scClose = new IntPtr(0xF060);
var keyboardWnd = FindWindow("IPTip_Main_Window", null);
if (keyboardWnd != nullIntPtr)
{
SendMessage(keyboardWnd, wmSyscommand, scClose, nullIntPtr);
}
}
#endregion
#region Private: Win32 API Methods
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr FindWindow(string sClassName, string sAppName);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
#endregion
}
Then update your form to look something like this:
private readonly TouchKeyboardProvider touckKeyboardProvider = new TouchKeyboardProvider();
public Form1()
{
InitializeComponent();
textBox1.Click += textBox1_Click;
textBox2.Click += textBox2_Click;
textBox3.Click += textBox3_Click;
textBox4.Click += textBox4_Click;
}
private void textBox1_Click(object sender, EventArgs e)
{
touckKeyboardProvider.ShowTouchKeyboard();
}
....
Related
I have around 10+ child forms and all the child forms have the following features
Close button: on hover displays "close" text and when mouse clicked, shows a message box to confirm the action
Minimize button: On hover, it displays "minimize" text, when the mouse is clicked, the form gets minimized
Drag anyway inside the parent form
I have to avoid using Visual Studio's default style to get a desirable customized form.
-The code below is shared by all the child forms, since the code is the same, is there a way to bind to one place and reference?
code
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
//Dtrag the form
private void DragPanel(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
}
#region controlbox
private void minimizebtn_Click(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
}
private void closebtn_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Are you sure you want to Close the window?", "Close", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
Close();
//Application.Exit();
}
}
private void closebtn_MouseHover(object sender, EventArgs e)
{
System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();
ToolTip1.SetToolTip(this.closebtn, "Close");
}
private void minimizebtn_MouseHover(object sender, EventArgs e)
{
System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();
ToolTip1.SetToolTip(this.minimizebtn, "Minimize");
}
#endregion
You could create a base class which itself derives from Form. Your actual forms should then derive from that base class.
I was looking for an answer and found an almost complete one by #LarsTech but without the exception :
https://stackoverflow.com/a/21314496/7026554
//You can still use MessageFilter and just filter for the ActiveForm:
private class MouseDownFilter : IMessageFilter {
public event EventHandler FormClicked;
private int WM_LBUTTONDOWN = 0x201;
private Form form = null;
[DllImport("user32.dll")]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
public MouseDownFilter(Form f) {
form = f;
}
public bool PreFilterMessage(ref Message m) {
if (m.Msg == WM_LBUTTONDOWN) {
if (Form.ActiveForm != null && Form.ActiveForm.Equals(form)) {
OnFormClicked();
}
}
return false;
}
protected void OnFormClicked() {
if (FormClicked != null) {
FormClicked(form, EventArgs.Empty);
}
}
}
//Then in your form, attach it:
public Form1() {
InitializeComponent();
MouseDownFilter mouseFilter = new MouseDownFilter(this);
mouseFilter.FormClicked += mouseFilter_FormClicked;
Application.AddMessageFilter(mouseFilter);
}
void mouseFilter_FormClicked(object sender, EventArgs e) {
// do something...
}
What I want is to hide the notifications panel but not when clicking on its content or the profile picture that shows it.
I have a procedure called NotificationVisible(bool IsVisible)
Any help is greatly appreciated.
So your mouseFilter_FormClicked fires whenever user clickes on form. Now the only thing you need to do is to detect the control that is placed behind the mouse cursor and with that you can deside whether you need to hide your panel or not.
You can do this with WindowFromPoint method. Check this thread.
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr WindowFromPoint(Point pnt);
void mouseFilter_FormClicked(object sender, EventArgs e) {
IntPtr hWnd = WindowFromPoint(Control.MousePosition);
if (hWnd != IntPtr.Zero) {
Control ctl = Control.FromHandle(hWnd);
if (ctl != YourPanelControl) {
HideThePanel();
}
}
}
public partial class Form3 : Form
{
private readonly KeyboardHookListener m_KeyboardHookManager;
private readonly MouseHookListener m_MouseHookManager;
[DllImport("user32")]
private static extern Int32 ClipCursor(RECT lpRect);
[DllImport("user32")]
private static extern Int32 ShowCursor(Int32 bShow);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public static implicit operator Point(POINT point)
{
return new Point(point.X, point.Y);
}
}
public static Point GetCursorPosition()
{
POINT lpPoint;
GetCursorPos(out lpPoint);
//bool success = User32.GetCursorPos(out lpPoint);
// if (!success)
return lpPoint;
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public Int32 Left;
public Int32 Top;
public Int32 Right;
public Int32 Bottom;
}
public Form3()
{
InitializeComponent();
m_KeyboardHookManager = new KeyboardHookListener(new GlobalHooker());
m_KeyboardHookManager.Enabled = true;
m_KeyboardHookManager.KeyDown += HookManager_KeyDown;
m_KeyboardHookManager.KeyUp += HookManager_KeyUp;
m_MouseHookManager = new MouseHookListener(new GlobalHooker());
m_MouseHookManager.Enabled = true;
m_MouseHookManager.MouseDown += HookManager_MouseDown;
m_MouseHookManager.MouseUp += HookManager_MouseUp;
}
private void Form3_Load(object sender, EventArgs e)
{
//ShowCursor(0);
//MoveCursor();
}
private void HookManager_KeyDown(object sender, KeyEventArgs e)
{
label1.Text = e.KeyData.ToString() + " Pressed";
}
private void HookManager_KeyUp(object sender, KeyEventArgs e)
{
label1.Text = e.KeyData.ToString() + " Released";
}
private void HookManager_MouseUp(object sender, MouseEventArgs e)
{
label1.Text = e.Button.ToString() + " Released";
}
private void HookManager_MouseDown(object sender, MouseEventArgs e)
{
label1.Text = e.Button.ToString() + " Pressed";
ShowCursor(0);
MoveCursor();
System.Threading.Thread.Sleep(5000);//5 sec
RestoreCursor(this);
ShowCursor(1);
}
private void button1_Click(object sender, EventArgs e)
{
//RestoreCursor(this);
//ShowCursor(1);
}
private void Form3_MouseMove(object sender, MouseEventArgs e)
{
//MoveCursor();
}
private RECT MouseTrap;
public void RestoreCursor(System.Windows.Forms.Form ThisForm)
{
var _with1 = MouseTrap;
_with1.Top = 0;
_with1.Left = 0;
_with1.Right = Screen.PrimaryScreen.Bounds.Width;
_with1.Bottom = Screen.PrimaryScreen.Bounds.Height;
ClipCursor(_with1);
}
private void MoveCursor()
{
// set the Current cursor, move the cursor's Position,
// and set its clipping rectangle to the form.
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(this.Left, this.Top);
Cursor.Clip = new Rectangle(this.Left, this.Top, this.Width, this.Height);
}
}
I am developing one sample application My requirement is when user clicks on anywhere on desktop for example click on Windows "Start" button then Hide the cursor for 2 sec then show the cursor after 2 sec at the same position.
For that I have written above code and used Thread.Sleep(2000) for waiting but cursor position restores to Form's left.
https://stackoverflow.com/questions/16781948/how-can-i-hook-globaly-all-the-keys-and-all-the-mouse-buttons/16782294
GlobalMouseHookDLL
you can achieve that using System.Windows.Forms.Timer.
Declare Timer on your form.
public partial class Form3 : Form
{
private Timer timer = new Timer();
Set it on Form_Load
timer.Enabled = false;
timer.Tick += Timer_Tick;
timer.Interval = 5000;
When user moves mouse, instead of Thread.Sleep activate timer. When timer ticks (when specified 5000 milliseconds pass), Timer_Tick method will execute. In it, show pointer.
private void HookManager_MouseDown(object sender, MouseEventArgs e)
{
label1.Text = e.Button.ToString() + " Pressed";
ShowCursor(0);
MoveCursor();
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
RestoreCursor(this);
ShowCursor(1);
timer.Stop();
}
Are there some ways to check charater in clipboard only digit before paste into textbox C# (Both Ctrl+V and right click -> Paste), which not using MarkedTextbox.
Add rule in textbox text change to accept number only like:
private string value;
private void textBox1_TextChanged(object sender, EventArgs e)
{
// at this moment value is still old
var oldValue = value;
if (System.Text.RegularExpressions.Regex.IsMatch(textBox1.Text, "[^0-9]"))
{
MessageBox.Show("Please enter numbers only.");
textBox1.Text = oldvalue;
}
else{
value = ((TextBox)sender).Text;
}
}
I ~think~ you want a TextBox that can only accept digits?
If yes, then set the ES_NUMBER style on the TextBox via SetWindowLong():
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form2_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
SetNumbersOnlyTextBox(this.textBox1);
}
public const int GWL_STYLE = (-16);
public const int ES_NUMBER = 0x2000;
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
public void SetNumbersOnlyTextBox(TextBox TB)
{
SetWindowLong(TB.Handle, GWL_STYLE, GetWindowLong(TB.Handle, GWL_STYLE) | ES_NUMBER);
}
}
Alternatively, you can Inherit from TextBox and set ES_NUMBER in CreateParams():
public class IntegerTextBox : TextBox
{
private const int ES_NUMBER = 0x2000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.Style = cp.Style | ES_NUMBER;
return cp;
}
}
}
I doubt there are anyways to check before pasting to TextBox, I would suggest subscribing to KeyDown and MouseClick events, and writing your own logic.
protected override void OnKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.V && e.Modifiers == Keys.Control)
{
// Your logic to read clipboard content and check length.;
}
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// You logic goes here.
}
}
You can get help from MSDN on how to read/write clipboard content.
If you literally want to only allow pastes that have digits only, then Inherit from TextBox and trap WM_PASTE, suppressing the message when desired:
public class DigitsOnlyOnPasteTextBox : TextBox
{
private const int WM_PASTE = 0x302;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE && Clipboard.ContainsText())
{
int i;
string txt = Clipboard.GetText();
foreach(char c in txt)
{
if (!char.IsNumber(c))
{
return;// suppress default behavior
}
}
}
base.WndProc(ref m); // allow normal processing of the message
}
}
In the below code, i am trying to reference an external .dll, which creates a custom taskbar in the desktop. After which i am creating tabs on the taskbar as per my requirement.
Everything works fine, but after i terminate my application for creating the taskbar, the space which is occupied by the custom taskbar is blocked. which means that, the resources are not released after exiting the application.
I am trying the force the application to dispose the unmanaged resources. But it dosent help.
How to do it?? Please refer to the code below which i am trying with...
namespace Daemon
{
public partial class MDIParent : ShellLib.ApplicationDesktopToolbar , IDisposable
{
private static MDIParent MDIParentInstance = null;
public MDIParent()
{
InitializeComponent();
timer1.Interval = 50;
timer1.Enabled = true;
}
int childCount = 1;
int iHitcount = 0;
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
private void MDIParent_FormClosed(object sender, FormClosedEventArgs e)
{
Taskbar.Show();
}
public void TabIt(string strProcessName)
{
//Get the collection of opened tab names and check against the new tabs.
//If exists, dont allow to open the same tab again.
bool found = false;
if (Global.ExistingTabProcessNames.Count > 0)
{
foreach (string currentTab in Global.ExistingTabProcessNames)
{
if (currentTab.Equals(strProcessName))
{
found = true;
}
}
}
if (found == false)
{
this.Show();
//Creating MDI child form and initialize its fields
MDIChild childForm = new MDIChild();
childForm.Text = strProcessName;
childForm.MdiParent = this;
//child Form will now hold a reference value to the tab control
childForm.TabCtrl = tabControl1;
//Add a Tabpage and enables it
TabPage tp = new TabPage();
tp.Parent = tabControl1;
tp.Text = childForm.Text;
tp.Show();
//child Form will now hold a reference value to a tabpage
childForm.TabPag = tp;
//Activate the MDI child form
childForm.Show();
childCount++;
//Activate the newly created Tabpage
tabControl1.SelectedTab = tp;
tp.Height = tp.Parent.Height;
tp.Width = tp.Parent.Width;
}
}
private void MDIParent_Load(object sender, EventArgs e)
{
Edge = AppBarEdges.Top;
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
private void tabControl1_SelectedIndexChanged(object sender, System.EventArgs e)
{
iHitcount = iHitcount + 1;
if (iHitcount != 1)
BringFront(tabControl1.SelectedTab.Text.ToString());
}
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
private void BringFront(string ExecutablePath)
{
Process[] Processes = Process.GetProcesses();
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains(ExecutablePath))
{
ShowWindowAsync(clsProcess.MainWindowHandle, SW_SHOWMAXIMIZED);
}
else
{
ShowWindowAsync(clsProcess.MainWindowHandle, SW_SHOWMINIMIZED);
}
}
}
public static MDIParent MDIParentRef
{
get
{
if (MDIParentInstance == null)
MDIParentInstance = new MDIParent();
return MDIParentInstance;
}
}
public void showScreen()
{
if (this.InvokeRequired == true)
{
this.Invoke(new MethodInvoker(this.showScreen));
}
else
{
this.Show();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (Global.TabProcessNames.Count > 0)
{
foreach (string strProcessName in Global.TabProcessNames)
{
TabIt(strProcessName);
}
}
}
}
}
The appbar is removed by the OnClosing event of ApplicationDesktopToolbar.
Are you using Application.Exit to exit your application? From MSDN:
The Application.Exit method does not raise the Form.Closed and Form.Closing events [...]