I have Two Winform Applications and when I try to Copy paste Text from that ProcessCmdKey Works Correctly if i made a check its not pasted ..
But when i try to paste my text in notepad its getting pasted ... I just want to Achieve COPY and PASTE of Text in same application
If I Focus on other Windows forms Text has not to be pasted... is there any way ..
private const Keys CopyKeys = Keys.Control | Keys.C;
private const Keys PasteKeys = Keys.Control | Keys.V;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
bool bVal = false;
Process[] p2 = Process.GetProcesses();
foreach (Process pro in p2)
{
if (string.Compare(pro.ProcessName, "TestForm.vshost", true) == 0 && (keyData == CopyKeys) || (keyData == PasteKeys))
{
bVal = true; // Text will be pasted
return true;
}
else
return base.ProcessCmdKey(ref msg, keyData); // Text will not be pasted
}
return bVal;
}
This works correctly. When i-I try to achieve same the same for Notepad wordpad. It getting pasted.
If you really want to be sure that other applications can't get the data in the clipboard you need to use a custom format and put your data in the clipboard yourself.
This is just an example how to do it. You need more work to have a working solution because you need to intercept the Ctrl+C yourself and put your data in the clipboard instead of using the predefined data formats that (by definition) are available for every application
public void cmdTest_Click(object sender, EventArgs e)
{
Clipboard.SetData("MyCustomFormat", new MyData("This text should not be pasted"));
if(Clipboard.ContainsData("MyCustomFormat"))
{
MyData result = Clipboard.GetData("MyCustomFormat") as MyData;
MessageBox.Show(result.MyValue);
}
}
[Serializable]
class MyData
{
string _internalValue;
public MyData(string newValue)
{ _internalValue = newValue;}
public string MyValue
{
get{return _internalValue;}
}
}
If you follow this method other applications cannot use your custom format (of course, if security is a real concern more tweaking will be required)
You can clear the Clipboard text when your application is minimized or lost focus.
Related
I am in the process of creating a POS system using C# and I have an issue with Textbox to read bar-code.
I want to read bar-code from the scanner either when the textbox has focus or not. Again I want the textbox to have capability to search for product manually that is user input the bar-code and then press the enter key the bar code captured should be used to query MySQL.
I have used this code to read bar-code from scanner when my textbox has focus or not but the problem is that when I want to search for product manually using enter key the method to query db is getting invoked twice and I don't understand why. Need help to prevent the function from getting invoked twice as well as provide functionality to search bar-code on enter and when textbox has no focus that is get input from scanner
private string _barcode = "";
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)//read when no focus
{
char c = (char)keyData;
if (char.IsNumber(c))
_barcode += c;
if (c == (char)Keys.Return)
{
read_scanner(_barcode);
_barcode = "";
}
return base.ProcessCmdKey(ref msg, keyData);
}
This my code to search manually
private void txtbarcode_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// onQuery = true;
read_scanner(txtbarcode.Text);
}
}
And here is my method which is getting invoked twice when I press enter key
Product product;
public void read_scanner(string barcode)//this method is getting invoked twice when i search product manually
{
//
product = HibernateDao.getRecord("from Product u where u.barcode='"+barcoded+"'");
if (product != null)
{
pos_datagrid.Rows.Add(barcode, product.product_name, product.product_desc, null, "1", null, product_Cost);
}
else
{
AppUtil.showErrorBox("Invalid bar code!!");
}
}
The ProcessCmdKey is a virtual method on all Forms that listens to all keys and return true if it was a command key and false for other keys, so you might not need to implement KeyDown at all.
documentation here
I've changed the code a little to make use of a StringBuilder and add the values to that StringBuilder.
StringBuilder _barcodeBuilder = new StringBuilder();
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData != Keys.Return)
{
switch (keyData)
{
case Keys.NumPad0:
_barcodeBuilder.Append(0);
break;
case Keys.NumPad1:
_barcodeBuilder.Append(1);
break;
case Keys.NumPad2:
_barcodeBuilder.Append(2);
break;
case Keys.NumPad3:
_barcodeBuilder.Append(3);
break;
//and so on for the rest of the numpad keys
default:
_barcodeBuilder.Append((char)keyData);
break;
}
}
else
{
MessageBox.Show(this, _barcodeBuilder.ToString());
//read_scanner(_barcodeBuilder.ToString());
textBox1.Clear();
_barcodeBuilder = new StringBuilder();
}
return base.ProcessCmdKey(ref msg, keyData);
}
Numpad keys are a bit strange, so you can handle them with a switch statement.
The source of your problem is unclear. Although if you want to track the source of what triggers your method, use System.Environment.StackTrace and output that as a debug message. You might have to use the "Debug" configuration for that.
I have a TextBox component in C# WinForms.
When I Right-click on it, I would like to disable the paste option, whilst still allowing users to Cut and Copy.
I have investigated a few options, neither of which fully meet my requirements -
If I use this option, it will prevent Cut and Copy along with Paste which I do not want.
txt.ShortcutsEnabled = false;
If I override the ContextMenu of TextBox, I will have to write the Cut and Copy Features myself in the new context menu.
txt.ContextMenu = new ContextMenu(); // or some other
Are there any options I can use to disable only the Paste option of the default context menu, retaining Cut and Copy?
Assuming the Paste menu item is always the fifth element in the textbox context menu (zero-based and a separator counts as item too), you could subclass the TextBox class (here: CustomMenuTextBox) and override the WndProc method to disable that specific menu item:
public static class User32
{
[DllImport("user32.dll")]
public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
}
public class CustomMenuTextBox : TextBox
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0093 /*WM_UAHINITMENU*/ || m.Msg == 0x0117 /*WM_INITMENUPOPUP*/ || m.Msg == 0x0116 /*WM_INITMENU*/)
{
IntPtr menuHandle = m.Msg == 0x0093 ? Marshal.ReadIntPtr(m.LParam) : m.WParam;
// MF_BYPOSITION and MF_GRAYED
User32.EnableMenuItem(menuHandle, 4, 0x00000400 | 0x00000001);
}
base.WndProc(ref m);
}
}
Based on Add item to the default TextBox context menu.
The following two steps disable the Copy/Paste feature in a textbox:
Disable the default menu and associate the textbox with an empty
context menu that has no menu items (mouse actions).
The user can still use the shortcut keys on the keyboard and perform
these operations.
So, override the ProcessCmdKey method as shown below:
// Constants
private const Keys CopyKeys = Keys.Control | Keys.C;
private const Keys PasteKeys = Keys.Control | Keys.V;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if((keyData == CopyKeys) || (keyData == PasteKeys))
{
return true;
}
else
{
return base.ProcessCmdKey(ref msg, keyData);
}
}
Note: Return true, which supresses the base class functionality.
OR You can use :
ContextMenuStrip mnu = new ContextMenuStrip();
ToolStripMenuItem mnuCopy = new ToolStripMenuItem("Copy");
ToolStripMenuItem mnuCut = new ToolStripMenuItem("Cut");
mnuCopy.Click += new EventHandler(mnuCopy_Click);
mnuCut.Click += new EventHandler(mnuCut_Click);
mnu.MenuItems.AddRange(new MenuItem[] { mnuCopy, mnuCut});
txt.ContextMenu = mnu;
Note : You can't disable Past option in default context menu for that you have to add contextMenuStrip in your form.
this.contextMenuStrip1.Items.AddRange(new
System.Windows.Forms.ToolStripItem[] {
this.Undo,
this.Cut,
this.Copy,
this.Paste,
this.Delete,
this.SelectAll});
this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening);
this.txt.ContextMenuStrip = this.contextMenuStrip1;
Hope Useful for you link
If you only need Cut Copy and Paste options, Maybe it is better create your custom contentMenuStrip, you can do that visually in Visual Studio and it is very easy to implement the copy cut and paste options. Then you can control in your program when you want to have any option enable or not.
For example this code in the Opening event of your custom ContentMenuStrip, disable copy and cut when you haven't selected text in a text-box, and only enable Paste if your clipboard contain text or images.
private void contextSuperEditor_Opening(object sender, CancelEventArgs e)
{
if (tbText.SelectionLength > 0)
{
MenuCopy.Enabled = true;
MenuCut.Enabled = true;
MenuPaste.Enabled = false;
}
else
{
MenuCopy.Enabled = false;
MenuCut.Enabled = false;
if (Clipboard.ContainsText() | Clipboard.ContainsImage())
{
MenuPaste.Enabled = true;
}
}
}
To keep myself interested, I try to put little Easter Eggs in my projects (mostly to amuse myself). I've seen some websites where you can type a series of letters "aswzaswz" and you get a "secret function" - how would I achieve this in C#?
I've assigned a "secret function" in the past by using modifier keys
bool showFunThing = (Control.ModifierKeys & Keys.Control) == Keys.Control;
but wanted to get a bit more secretive (without the modifier keys) I just wanted the form to detect a certain word typed without any input ... I've built a method that I think should do it:
private StringBuilder _pressedKeys = new StringBuilder();
protected override void OnKeyDown(KeyEventArgs e)
{
const string kWord = "fun";
char letter = (char)e.KeyValue;
if (!char.IsLetterOrDigit(letter))
{ return; }
_pressedKeys.Append(letter);
if (_pressedKeys.Length == kWord.Length)
{
if (_pressedKeys.ToString().ToLower() == kWord)
{
MessageBox.Show("Fun");
_pressedKeys.Clear();
}
}
base.OnKeyDown(e);
}
Now I need to wire it up but I can't figure out how I'm supposed to raise the event in the form designer ... I've tried this:
this.KeyDown +=new System.Windows.Forms.KeyEventHandler(OnKeyDown);
and a couple of variations on this but I'm missing something because it won't fire (or compile). It tells me that the OnKeyDown method is expecting a certain signature but I've got other methods like this where I haven't specified arguments.
I fear that I may have got myself confused so I am turning to SO for help ... anyone?
EDIT: The ProcessCmdKey seems to be the way that works with the following:
private StringBuilder _pressedKeys = new StringBuilder();
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const string kWord = "fun";
char letter = (char)keyData;
if (!char.IsLetterOrDigit(letter))
{return true;}
_pressedKeys.Append(letter);
if (_pressedKeys.Length == kWord.Length)
{
if (_pressedKeys.ToString().ToLower() == kWord)
{
MessageBox.Show("Fun");
_pressedKeys.Clear();
}
_pressedKeys.Clear();
}
return true;
}
Thanks all!
Try this:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.P|Keys.Control))
{
//do my prank
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
This will fire when you press CTRL + P.
refer: ProcessCmdKey
This method is called during message preprocessing to handle command
keys. Command keys are keys that always take precedence over regular
input keys. Examples of command keys include accelerators and menu
shortcuts. The method must return true to indicate that it has
processed the command key
You are overriding a virtual method, so you do not need to handle the KeyDown event. If you debug, you should hit a breakpoint in you overriden method if something calls the virtual method.
Are you sure you are overriding the correct method in the correct class though? Just a thought.
I have a MaskedTextBox control that, in our case, is collecting social insurance (tax) numbers (without a ValidatingType though since the string representation including the mask literals). A social insurance number is 3 groups of 3 digits separated by dashes. Sometimes spaces may be typed or entered instead of the dashes.
The configuration of the textbox is:
Mask: 999-999-999
ValidationType: null / not required
SkipLiterals: true
CutCopyMaskFormat: IncludeLiterals (only relevant when cut/copy FROM textbox)
TextMaskFormat: IncludeLiterals
-- Let me know if there other properties that you think could be important!
Problem
When pasting the following tax number "450 622 097" because of the spaces it doesn't match the mask. So I end up with "450- 62-2 9" in the text box. Pasting "450-622-097" will successfully paste into the box.
I want to be able to intercept the paste event in order to possibly fix it up to replace the spaces with dashes.
Alternatively, could we make the mask accept dashes OR spaces (but always output dashes)?
Non-solutions
MaskInputRejected event - I can't seem to get a handle on what was originally input (i.e. what's being rejected) so as to compare it with what's sitting at the top of the Clipboard. It merely returns how it was rejected
Validating event - Already occurs after the mask has been applied. I.e. the value of "450- 62-2 9" is in the textbox now.
Use custom ValidatingType with static Parse function - Again, occurs after the mask has been applied.
Detecting Key-Down event - Then if key series is Ctrl-V then manually handle and pass in a cleaned up version of the clipboard text. Could work, but then what about paste via the right click context menu?
Any other ideas?
While this is a hammer solution, there are limitations to the mask string and i don't see another way around it. What you need is to capture the paste event and process the text before it gets in the textbox. See below a simplistic example
class MyMaskedTextbox : MaskedTextBox
{
const int WM_PASTE = 0x0302;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PASTE:
if (Clipboard.ContainsText())
{
string text = Clipboard.GetText();
text = text.Replace(' ', '-');
//put your processing here
Clipboard.SetText(text);
}
break;
}
base.WndProc(ref m);
}
}
As per #anchandra's response and subsequent comments here is the class to enable processing of the text on a per-control basis.
public class MyMaskedTextBox : MaskedTextBox
{
private const int WM_PASTE = 0x0302;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PASTE:
if (Clipboard.ContainsText())
{
string text = Clipboard.GetText();
var args = OnPasting(text);
if (args.Cancel)
{
// Swallow it up!
return;
}
// If value changed, then change what we'll paste from the top of the clipboard
if (!args.Value.Equals(text, StringComparison.CurrentCulture))
{
Clipboard.SetText(args.Value);
}
}
break;
}
base.WndProc(ref m);
}
public event EventHandler<PastingEventArgs> Pasting;
protected virtual PastingEventArgs OnPasting(string value)
{
var handler = Pasting;
var args = new PastingEventArgs(value);
if (handler != null)
{
handler(this, args);
}
return args;
}
}
public class PastingEventArgs : CancelEventArgs
{
public string Value { get; set; }
public PastingEventArgs(string value)
{
Value = value;
}
}
And simple usage of the Pasting event to strip out spaces as per:
private void sinTextBox_Pasting(object sender, PastingEventArgs e)
{
e.Value = e.Value.Replace(" ", String.Empty);
}
I'm using a HtmlEditor control inside a Windows Form.
I got the control from this page:
http://windowsclient.net/articles/htmleditor.aspx
I want to extend the controls functionality by allowing the user to paste images from the clipboard. Right now you can paste plain and formatted text, but when trying to paste an image it does nothing.
Basically what I thought was to detect when the user presses Ctrl+V on the editor, check the clipboard for images and if there's an image, insert it manually to the editor.
The problem with this approach is that I cannot get the OnKeyDown or OnKeyPress events of the form to be raised.
I have the KeyPreview property set to true on the form, but still the events aren't raised.
I also tried to Subclass the form and the editor (as explained here) to intercept the WM_PASTE message, but it isn't raised either.
Any ideas on how to achieve this?
Thanks a lot
I spent all day on this problem and finally have a solution. Trying to listen for the WM_PASTE message doesn't work because Ctrl-V is being PreProcessed by the underlying mshtml Control. You can listen for OnKeyDown/Up etc to catch a Ctrl-V but this won't stop the underlying Control from proceeding with its default Paste behavior. My solution is to prevent the PreProcessing of the Ctrl-V message and then implementing my own Paste behavior. To stop the control from PreProcessing the CtrlV message I had to subclass my Control which is AxWebBrowser,
public class DisabledPasteWebBrowser : AxWebBrowser
{
const int WM_KEYDOWN = 0x100;
const int CTRL_WPARAM = 0x11;
const int VKEY_WPARAM = 0x56;
Message prevMsg;
public override bool PreProcessMessage(ref Message msg)
{
if (prevMsg.Msg == WM_KEYDOWN && prevMsg.WParam == new IntPtr(CTRL_WPARAM) && msg.Msg == WM_KEYDOWN && msg.WParam == new IntPtr(VKEY_WPARAM))
{
// Do not let this Control process Ctrl-V, we'll do it manually.
HtmlEditorControl parentControl = this.Parent as HtmlEditorControl;
if (parentControl != null)
{
parentControl.ExecuteCommandDocument("Paste");
}
return true;
}
prevMsg = msg;
return base.PreProcessMessage(ref msg);
}
}
Here is my custom method to handle Paste commands, yours might do something similar with the Image data from the Clipboard.
internal void ExecuteCommandDocument(string command, bool prompt)
{
try
{
// ensure command is a valid command and then enabled for the selection
if (document.queryCommandSupported(command))
{
if (command == HTML_COMMAND_TEXT_PASTE && Clipboard.ContainsImage())
{
// Save image to user temp dir
String imagePath = Path.GetTempPath() + "\\" + Path.GetRandomFileName() + ".jpg";
Clipboard.GetImage().Save(imagePath, System.Drawing.Imaging.ImageFormat.Jpeg);
// Insert image href in to html with temp path
Uri uri = null;
Uri.TryCreate(imagePath, UriKind.Absolute, out uri);
document.execCommand(HTML_COMMAND_INSERT_IMAGE, false, uri.ToString());
// Update pasted id
Guid elementId = Guid.NewGuid();
GetFirstControl().id = elementId.ToString();
// Fire event that image saved to any interested listeners who might want to save it elsewhere as well
if (OnImageInserted != null)
{
OnImageInserted(this, new ImageInsertEventArgs { HrefUrl = uri.ToString(), TempPath = imagePath, HtmlElementId = elementId.ToString() });
}
}
else
{
// execute the given command
document.execCommand(command, prompt, null);
}
}
}
catch (Exception ex)
{
// Unknown error so inform user
throw new HtmlEditorException("Unknown MSHTML Error.", command, ex);
}
}
Hope someone finds this helpful and doesn't waste a day on it like me today.