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
}
}
Related
Is there a way to distinguish whether the Enter event on a control was raised by keyboard (Tab, Shift+Tab) or by direct mouse click?
I need to perform an action only when the user is moving to the control using Tab, but not when the user directly clicks on the control. I have tried to intercept the mouse click directly, but it seems the Enter event is raised before Click.
Instead of tracking the Tab key, you can use the WM_MOUSEACTIVATE message to detect activation of the control with the mouse. You could either sub-class each control type you use and override the WndProc method or use a NativeWindow listener class like the one presented below. Depending on how many types of controls you use, it may be less work and clutter to just sub-class those controls to provide a property that indicates that the control was selected using the mouse. It is your decision to make, but the pattern will be the same.
This code is a slight modification of the example shown in the MS documentation.
public class MouseActivateListener : NativeWindow
{
private Control parent;
public MouseActivateListener(Control parent)
{
parent.HandleCreated += this.OnHandleCreated;
parent.HandleDestroyed += this.OnHandleDestroyed;
parent.Leave += Parent_Leave;
this.parent = parent;
if (parent.IsHandleCreated)
{
AssignHandle(parent.Handle);
}
}
private void Parent_Leave(object sender, EventArgs e)
{
MouseActivated = false;
}
private void OnHandleCreated(object sender, EventArgs e)
{
AssignHandle(((Form)sender).Handle);
}
private void OnHandleDestroyed(object sender, EventArgs e)
{
ReleaseHandle();
}
public bool MouseActivated { get; set; }
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
const Int32 WM_MouseActivate = 0x21;
base.WndProc(ref m);
if (m.Msg == WM_MouseActivate && m.Result.ToInt32() < 3)
{
MouseActivated = true;
}
}
}
Example Usage:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MouseActivateListener textBox1Listener;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
textBox1Listener = new MouseActivateListener(textBox1);
}
private void textBox1_Enter(object sender, EventArgs e)
{
if (textBox1Listener.MouseActivated)
{
MessageBox.Show("Mouse Enter");
}
else
{
MessageBox.Show("Tab Enter");
}
}
}
You can use the Form.KeyPreview event and store the last key press in a variable. Then in your control's Enter event, check the value of the key that was pressed last. If this is a tab, do whatever you need to:
private Keys lastKeyCode;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
this.lastKeyCode = e.KeyCode;
}
Then in the Enter event, check it:
if (lastKeyCode == Keys.Tab)
{
// Whatever...
}
Intercepting WM_KEYUP and WM_KEYDOWN directly with a message filter to retrieve the state of the Tab key worked. This seems excessive for such a seemingly straightforward task, but apparently the Tab key is suppressed from most windows forms events.
Would be happy to take a cleaner answer, but for now, this is it:
class TabMessageFilter : IMessageFilter
{
public bool TabState { get; set; }
public bool PreFilterMessage(ref Message m)
{
const int WM_KEYUP = 0x101;
const int WM_KEYDOWN = 0x100;
switch (m.Msg)
{
case WM_KEYDOWN:
if ((Keys)m.WParam == Keys.Tab) TabState = true;
break;
case WM_KEYUP:
if ((Keys)m.WParam == Keys.Tab) TabState = false;
break;
}
return false;
}
}
class MainForm : Form
{
TabMessageFilter tabFilter;
public MainForm()
{
tabFilter = new TabMessageFilter();
Application.AddMessageFilter(tabFilter);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
Application.RemoveMessageFilter(tabFilter);
base.OnFormClosed(e);
}
void control_Enter(object sender, EventArgs e)
{
if (tabFilter.TabState) // do something
else // do domething else
}
}
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();
}
}
}
So I need to move my form no matter what element is clicked (I need to drag form by pressing and holding button, form is 100% transparent) , I tried to do this:
private void MessageForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
this.DragMove();
}
but I was quite surprised that there in no DragMove() method, it was renamed or what I am missing?
And if this is not possible, is there any other way to do that?
You will need something like this:
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void MessageForm_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
Basically, it acts like dragging the title bar/window caption when you drag anywhere in the window. This is great for borderless windows.
EDIT:
If you use a button as the control for moving the form, you will need to be careful when attaching your click event handler as you are overriding the Windows Forms event loop for that control.
By moving/adding the ReleaseCapture and SendMessage calls to the MouseDown event of a control, you can use it to drag the window. Any control can be used to drag the window as long as you update the MouseDown event to be similar to the code above.
Tested and working: this.DragMove(), alternative
private void Form1_Load(object sender, EventArgs e)
{
FormCommonSetting(this);
}
public void FromCommonSetting(Form _Form)
{
_Form.StartPosition = FormStartPosition.CenterScreen;
_Form.FormBorderStyle = FormBorderStyle.None;
_Form.MaximizeBox = false;
_Form.ShowInTaskbar = true;
_Form.AutoSize = false;
}
protected override void WndProc(ref Message _Message)
{
switch (_Message.Msg)
{
case 0x84:
base.WndProc(ref _Message);
if ((int)_Message.Result == 0x1)
_Message.Result = (IntPtr)0x2;
return;
}
base.WndProc(ref _Message);
}
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();
}
....
I need to have my edit box work the same for both tab and the enter key.
I have found lots of problems doing this in the application. Is there some way that I can send a tab key to the form/edit box.
(Note that this has to be in the Compact Framework.)
Solution:
Here is what I ended up using:
// This class allows us to send a tab key when the the enter key is pressed for the mooseworks mask control.
public class MaskKeyControl : MaskedEdit
{
[DllImport("coredll.dll", EntryPoint = "keybd_event", SetLastError = true)]
internal static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
public const Int32 VK_TAB = 0x09;
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyData == Keys.Enter)
{
keybd_event(VK_TAB, VK_TAB, 0, 0);
return;
}
base.OnKeyDown(e);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == '\r')
e.Handled = true;
base.OnKeyPress(e);
}
}
I am giving the answer to Hans because his code got me moving toward the right solution.
You could try this control:
using System;
using System.Windows.Forms;
class MyTextBox : TextBox {
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyData == Keys.Enter) {
(this.Parent as ContainerControl).SelectNextControl(this, true, true, true, true);
return;
}
base.OnKeyDown(e);
}
protected override void OnKeyPress(KeyPressEventArgs e) {
if (e.KeyChar == '\r') e.Handled = true;
base.OnKeyPress(e);
}
}