Detecting if paste event occurred inside a rich text box - c#

Is there a way by which we can find out if a clip board paste event occurred in a rich text box? This event would be used in order to do certain stuff, with the pasted block of text.
thanks
Here is my code
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_PASTE)
{
OnPasteOccurred();
MessageBox.Show("Pas");
}
if (m.Msg == 0x000F)
{
if (PaintControl)
{
base.WndProc(ref m);
}
else
{
m.Result = IntPtr.Zero;
}
}
else
{
base.WndProc(ref m);
}
}
Edit
I wish to do some syntax highlighting or indentation based on paste events, something which this particular code editor seems to be doing very efficiently. I don't know how it is doing it. Would require help in this particular direction. I am pretty sure that there must some native Win32 code or something like that can be intercepted. I have tried tracking down keys, mouse events and it is not pretty.

It's a little bit tricky to detect a paste operation in the RichTextBox.
First solution may be to detect the WM_PASTE message overriding the WndProc but unfortunately the control doesn't send that message to itself when it performs a paste operation.
Naïve detection
To detect the keyboard events may work (you have to override the OnKeyDown function) then check if the key combinations (CTRL+V and SHIFT+INS). Something like this:
protected override OnKeyDown(KeyEventArgs e)
{
bool ctrlV = e.Modifiers == Keys.Control && e.KeyCode == Keys.V;
bool shiftIns = e.Modifiers == Keys.Shift && e.KeyCode == Keys.Insert;
if (ctrlV || shiftIns)
DoSomething();
}
It works well but you can't catch the paste operation made using the mouse (right click to open the context menu) and the paste operations made via drag & drop. If you do not need them you can use this solution (at least it's simply and straightforward).
Better detection
Assumption: when user types inside the RichTextBox he inserts one character per time. How can you use this? Well, when you detect a bigger change you detected a paste operation because user can't type more than once character per time (ok, you can argue that it's not always true because of Unicode surrogates). See also VB.NET version and more details about Unicode stuff.
private int _previousLength = 0;
private void richTextBox_TextChanged(object sender, EventArgs e)
{
int currentLength = richTextBox.Text.Length;
if (Math.Abs(currentLength - _previousLength) > 1)
ProcessAllLines();
_previousLength = currentLength;
}
Please note that you can't (because of how different IMEs work) use OnKeyDown (or similar). This works well only for western languages but it has problems with Unicode stuff (because, for example, String.Length property may be increased by two Char when user typed a single character. See also this post for much more details about this (well it's a strongly suggested reading even, even if - in this case - you don't care about it). In that post you'll also find code for a better algorithm to determine string length. In short you have to replace:
int currentLength = richTextBox.Text.Length;
With this:
int currentLength = StringInfo.GetTextElementEnumerator(richTextBox.Text)
.Cast<string>()
.Count();
After all this effort you may realize that...user can even paste a single character and it may go undetected. You're right, that's why this is a better detection instead of a perfect solution.
Perfect solution
The perfect solution (if you're running on Windows 8) of course exists, the native rich edit control sends an EN_CLIPFORMAT notification message. It's intended to notify a rich edit control's parent window that a paste occurred with a particular clipboard format. You can then override the WndProc of its parent to detect the WM_NOTIFY message for this notification. Anyway it's not few lines of code, check this MSDN article for details.

Starting from .Net 3.0, there is a built-in method to detect the paste event:
DataObject.AddPastingHandler(this, OnPaste);
Just call this method in the constructor. If you want for example handle the paste event yourself as if the user entered the text manually, you can use
private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(string)))
{
var text = (string)e.DataObject.GetData(typeof(string));
var composition = new TextComposition(InputManager.Current, this, text);
TextCompositionManager.StartComposition(composition);
}
e.CancelCommand();
}

I came across this old question and I would like to share my solution (it's VB but can it be easily converted). I use it to force paste as plain text when needed:
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
If ForcePasteAsPlainText And ((e.Control = True And e.KeyCode = Keys.V) Or (e.Shift = True And e.KeyCode = Keys.Insert)) Then
MyBase.Paste(DataFormats.GetFormat(DataFormats.Text))
e.Handled = True
Return
End If
MyBase.OnKeyDown(e)
End Sub
Shadows Sub Paste()
If ForcePasteAsPlainText Then
MyBase.Paste(DataFormats.GetFormat(DataFormats.Text))
Else
MyBase.Paste()
End If
End Sub
Shadows Sub Paste(clipFormat As DataFormats.Format)
If ForcePasteAsPlainText Then
MyBase.Paste(DataFormats.GetFormat(DataFormats.Text))
Else
MyBase.Paste(clipFormat)
End If
End Sub

Related

Capture x and y of user touch, iOS Xamarin Forms

I am using Xamarin Forms (Xamarin Studio Community) to write an iOS app. I just need to capture the coordinates of user touch and release on a button.
I have searched all over Google, and I only found responses that simply did not work. They were either for Android, or Swift, or XCode, or WAY too much to make practical use of.
The closest I've seen are answers that say "There is currently no way to do that in Xamarin Forms." Which seems absurd to me because it seems like one of the most basic, fundamental things a programmer would need.
All I need is to capture the x,y from where the user touches and releases. Here are my handlers all ready to go.
thisHereButton.TouchDown += (object sender, System.EventArgs e) =>
{
//pressed
touchX = [x];
touchY=[y];
};
thisHereButton.TouchUpInside += (object sender, System.EventArgs e) =>
{
//released
releaseX = [x];
releaseY=[y];
};
That's it. If someone could provide a simple, practical answer, that would be great!
EDIT: With a bounty goes additional research, in hopes that someone can help.
I followed the advice in the comments and after some analysis, have determined that this is the chunk of code that is most relevant.
private bool touchStartedInside;
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
base.TouchesMoved(touches, evt);
// get the touch
UITouch touch = touches.AnyObject as UITouch;
if (touch != null)
{
//==== IMAGE TOUCH
if (backdrop.Frame.Contains(touch.LocationInView(View)))
{
//TouchStatus.Text = "Touches Moved";
}
//==== IMAGE DRAG
// check to see if the touch started in the drag me image
if (touchStartedInside)
{
// move the shape
float offsetX = (float)(touch.PreviousLocationInView(View).X - touch.LocationInView(View).X);
float offsetY = (float)(touch.PreviousLocationInView(View).Y - touch.LocationInView(View).Y);
txt_sizeValText.Text = "" + offsetY;
//DragImage.Frame = new RectangleF(new PointF(DragImage.Frame.X - offsetX, DragImage.Frame.Y - offsetY), DragImage.Frame.Size);
}
}
}
That is taken directly from their example. Right there in the code, it gives me what I'm looking for, as well as the bonus of the "offset" which is what I really need in the end.
So I've got this void in my code and the code still compiles, so there are no errors.
The only thing I cannot figure out is how to make use of this void. How do you call it?
If I have to use a different handler than the ones in my original post, that's fine. Whatever you can tell me about how to make this work...
You don't need to call the TouchesMoved() method. It is automatically called when the Objective C runtime calls it ( it is an override of the method to be called) - It is basically the handler of the native event. You can already get the offsets, and you can raise your own events inside that method to change your button. It is already done.

C# Windows form delete key not responding

in my C# windows form application I want the user to be able to remove a node by pressing the delete key on their keyboard and have implemented the seemingly correct code but when the delete key is pressed nothing happens.
private void treeView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys .Delete)
{
if (treeView1.SelectedNode != null)
{
treeView1.SelectedNode.Remove();
}
}
This is the code I am attempting to use to implement the desired function.
The keyboard keycode check looks fine to me, which says to me that treeView1.SelectedNode is probably returning null.
I met the problem today and have tried many ways to address it. MSDN gives the answer actually. Here are the two codes that I put in public Form1()
this.KeyPreview = true;
this.KeyDown += new KeyEventHandler(Form1_KeyDown);
I've just study C# this week, so I am trying to figure out the meaning of the codes. Just hope this approach will work for the people who needs.
If anyone can explain the code above, I will be very grateful.

Disable normal behavior of Alt key

When pressing the Alt key, normally the focus goes to the window's menu. I need to disable it globally. Because my application works with Alt key. When the user presses some key in combination with the Alt key, my application sends another key to active application. So I just need to ignore Alt when it opens the menu.
I'm new to programming and I'm looking for VB.Net or C# code.
My first answer is to NOT use the Alt key for your program and use Ctrl instead. Blocking "normal" things from happening usually leads to pain in the future.
But if you must use the Alt key I would check out this article which uses message filters to try and intercept it at the application level.
If that doesn't do what you're looking for, you might need to look into Global hooks, this link will get you started down the path. Global hooks are generally considered evil so you should only use this if the above two suggestions don't work. You must make sure that you uninstall your hooks otherwise you might find that you need to reboot your computer often to fix weird keyboard problems.
This works for me:
private class AltKeyFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
return m.Msg == 0x0104 && ((int)m.LParam & 0x20000000) != 0;
}
}
And then you add the message filter like so:
Application.AddMessageFilter(new AltKeyFilter());
You can try something like this:
public void HandleKeyDown(object sender, keyEventArgs e)
{
//do whatever you want with or without Alt
if (e.Modifiers == Keys.Alt)
e.SuppressKeyPress = true;
}
This should allow you to use Alt for whatever you want but keep it from activating the menustrip. Note that e.SuppressKeyPress = true also sets e.Handled = true.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.keyeventargs.suppresskeypress?view=windowsdesktop-5.0

C# For how long was user inactive

Some background:
I am writing a application with several forms, etc. Users have to log in in order to use most of the features, and this worked fine until now. However, now, client has requested that the user would be logged out after a certain amount of inactive time. The problem is that the user can still be active on the computer, just not in my application,. To be clear, I have to log the user out when he is inactive in my application, even if he is still interacting with the desktop.
First I thought this would be fairly simple. Just remember the time of the last action, compare it continually in a timer with current time and log out the user if the time passed is greater than the allowed time. However I have realised that finding out the last action time may not be so simple...
Of course I could copy paste something like
Program.LastActionTime = DateTime.Now;
in every OnChange, OnClick, etc, event ... However not only that this would be a great amount of work because of the size of the application ... It would also be a very bad practice and I'm sure it would be forgot at least once, making the whole thing unreliable (And appear broken, the bug would be almost impossible to reproduce!)
So, is there a better way?
One approach that I've used in the past, create a MessageFilter on your application form and check for certain types of events that indicate user activity:
public class UserActivityFilter : IMessageFilter
{
// Define WinAPI window message values (see pinvoke.net)
private int WM_LBUTTONDOWN = 0x0201;
private int WM_MBUTTONDOWN = 0x0207;
private int WM_RBUTTONDOWN = 0x0204;
private int WM_MOUSEWHEEL = 0x020A;
private int WM_MOUSEMOVE = 0x0200;
private int WM_KEYDOWN = 0x0100;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_MBUTTONDOWN || m.Msg == WM_RBUTTONDOWN || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_KEYDOWN)
{
//User activity has occurred
// Reset a flag / timer etc.
}
return false;
}
}
Then in the Main() method of the form, BEFORE the call to Run():
Application.AddMessageFilter(new UserActivityFilter());
One caveat, adding a complex message filter or adding multiple separate filters can slow down the responsiveness of your application.
In your Program.CS file, you can handle the Application.Idle event and reset your timer there. See:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle.aspx
You can override WndProc, update Program.LastActionTime on each relevant Keyboard/Mouse event message.
Hook an event handler on the MouseMove and KeyPressed events, and then check for focus inside that event?
In general it would be the best idea to derive this information from your application logic instead of raw user input, but I assume you have no flexible infrastructure (maybe using the command pattern) that could provide this information.
So I suggest just to register handlers with your main form - if you receive clicks or key events (enable Form.KeyPreview for this), your user is active and you can reset the inactivity time.
You could create a base class that all your window forms inherits from. In the base class you check and reset your timeout on every KeyPress or Click.

keyboard Events

whenever i am pressing key in my server system i ll send that keyevent to another system after that the correspondingaction should be happend in the client machine.. help me to get a better way to solve this problem
thanx in advance
If I understand it correctly then what you have doesn't sound too bad. Are you saying that:
You have a client server architecture.
At the server (presumably at command console or management application) you press a key.
The key corresponds to an action. The action needs to be invoked at the client.
You could implement this using asynchronous WCF. See here and here for more some more info. One way to look at this problem is as a distributed observer pattern. Your server is the subject and the client(s) are the observer(s).
Update: Handling Key Events in .Net
You could try adding a KeyDown event handler to your form:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control & e.KeyCode == Keys.C)
{
MessageBox.Show( "Ctrl + C pressed" );
// Swallow key event, i.e. indicate that it was handled.
e.Handled = true;
}
}
But if you have any controls on your form then you won't get the event. What you probably need to do is sniff windows messages using a message filter. E.g.
public class KeyDownMessageFilter : IMessageFilter
{
public const int WM_KEYDOWN = 0x0100;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
// Key Down
return true; // Event handled
}
return false;
}
}
Add this message filter to the application using the AddMessageFilter method. If you want to check if the CTRL key is pressed for the key down message then check the lparam.
If any of this isn't clear then let me know.
please give us more details on what you're trying to do.
To simulate key presses in Windows Forms, I'd use SendKeys class.

Categories