I have a disabled control. I still want the key down and key up events to get fired off, because I would like to be aware of a certain key.
When I tested this out, it seems like none of the control's events get fired. Any ideas on how to get around this?
Lack of interaction is basic idea of disabling control, it is working as intended.
You might use KeyPreview property of Form and then launch event handlers of your disabled control from Form events.
As usually, there is n+1 ways to achieve what you seek for. So I will present only some of them.
1 - Manipulate Focus. Although easy to implement, it is also volatile as user can manipulate focus as well.
private void button_KeyDown(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Add(helpBox);
((Control)sender).Focus(); // Set focus back to control so its KeyUp will be called
}
private void button_KeyUp(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Remove(helpBox);
}
2 - Multiple calls to same event handler. Yes, it is possible. A bit more complicated and might depend on helpBox control class and/or its events. Possible issues may include multiply fired up event handler, however presented code is safe to use even if such situation will occur.
private void button_KeyDown(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Add(helpBox);
helpBox.KeyUp += button_KeyUp; //This will add KeyUp of our hosting button to hosted control, which means that said KeyUp handler can be raised by both helpBox and button
}
private void button_KeyUp(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Remove(helpBox);
helpBox.KeyUp -= button1_KeyUp; // to avoid unnecessary calls event handler can be easily "subtracted" from helpBox
}
3 - Master control by Form itself by use of KeyPreview set to true, shows controls with "help_" as helpBoxes on controls named .
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
foreach (Control c in this.Controls)
{
string hName = "help_" + c.Name;
Control[] help = this.Controls.Find(hName, true);
if (help.Length>0)
{
c.Controls.Add(help[0]);
}
}
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
foreach (Control c in this.Controls)
{
string hName = "help_" + c.Name;
Control[] help = c.Controls.Find(hName, true);
if (help.Length > 0)
{
c.Controls.Remove(help[0]);
}
}
}
}
Note: Control on-screen position depends on its parent position (relative to top-left corner of parent), in other words, by changing parent of control (which happens during Controls.Add) control will change its position.
4 - Draw it by yourself! Manipulating controls is not always best solution, instead you might want to just draw something on control.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
button1.Tag = true;
button1.Update();
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
button1.Tag = false;
button1.Update();
}
// there is no reason to re-draw it constantly, Paint event will be fired when needed
private void button1_Paint(object sender, PaintEventArgs e)
{
// remember that all Tag's start as null
if (((Control)sender).Tag != null && (bool)((Control)sender).Tag == true)
{
// and when needed just paint on control drawing area (also known as Canvas)
e.Graphics.FillRectangle(Brushes.Red, 0, 0, 100, 100);
e.Graphics.DrawString("Foo!", ((Control)sender).Font, Brushes.Beige, new PointF(5, 5));
}
}
Note: Every Control have Tag property, due to it being of object type you can store in it anything you want. Which makes it universal custom property. In case you wonder about meaning of this property: it have no meaning, it is made to be user-defined.
Related
I want to handle crtl+click event in WPF XAML code behind. I registered KeyDown event and MouseDown event, but I am not able to register for them together. What is that I am missing.
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl))
{
//do something
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
{
//do something
}
}
Thanks,
RDV
Don't bother tracking Key Up/Down events--they're not reliable (e.g., user may switch windows between pressing and releasing). Just check Keyboard.Modifiers when you process the click.
If you only want to handle Ctrl+Click and not, for example, Ctrl+Shift+Click, then check Modifiers for an exact match:
if (e.ClickCount == 1 && Keyboard.Modifiers == ModifierKeys.Control) {
}
Otherwise, do a selective bitwise match:
if (e.ClickCount == 1 && (Keyboard.Modifiers & ModifierKeys.Control) != 0) {
}
Keyboard.Modifiers should generally be consistent: it won't reflect the release of the control key until after you process the mouse event, because all input events are processed in FIFO order.
Be sure to read up on bubbling versus tunneling events (e.g., MouseDown vs. PreviewMouseDown), and how events stop routing once they are marked as Handled.
As an alternative, you may be able to use a simple MouseGesture with a MouseAction of LeftClick and Modifiers of Control. It really depends on what your UI looks like, and whether you want a chance at handling the event before any descendant controls. Using a mouse gesture should work in (mostly) the same scenarios as handling the bubbling MouseDown event. But if you need to rely on tunneling events like PreviewMouseDown, then a gesture wouldn't work.
Do something like this, with a flag:
bool _isControlPressed = false;
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl))
{
_isControlPressed = true;
}
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl))
{
_isControlPressed = false;
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1 && _isControlPressed)
{
//do something
}
}
The _isControlPressed flag is set/unset in the key down/key up events. You can then use this flag in other methods to determine the key state.
private void MeretOK_Click(object sender, EventArgs e)
{
//code
}
private void MeretTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode==Keys.Enter)
{
MeretOK_Click();
}
}
How can I start an event with a hotkey?
(I know I can just copy the code there but that is ugly)
If I just copy the code and run it I hear a beep. Why?
First, you have to allow your form to handle key events globally (set the form KeyPreview property to true) and to mark your event as internally handled. Second, if the purpose of this code is to simulate the mouse click on a specific control (programmatic click), for example a button, there is an easier way to accomplish it:
private void MeretTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
myButton.PerformClick();
}
}
I have the following problem: I have a panel which has a specific color, say red.
When the user presses his mouse, the color of this panel gets stored in a variable. Then the user moves, his mouse still pressed, over to another panel. When he releases the mouse there, this panel should get the background color of the first that had been stored in the variable. My code looks something like this:
public Color currentColor;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
private void AttempsColorChanger(object sender, MouseEventArgs e)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
}
I need to identify the sender first because there are many possible panels that can trigger this event. The first MouseDown method works totally fine, the color is stored nicely in the variable. The secon one however doesn't even get triggered when the user does what I described above. When the ser clicks on the second panel, it works (there is an MouseUp part in a click aswell I guess).
What's wrong here? Why is the event not triggered when the user holds the mouse key down before?
(This answer assumes you are using Windows Forms.)
It could be that you need to capture the mouse by setting this.Capture = true in the MouseDown of the source control. (See Control.Capture)
If you did that, the source window would get the MouseUp event, and it would be the source window that had to determine the destination window under the mouse coords. You can do that using Control.GetChildAtPoint() (see this answer on Stack Overflow).
Use Windows Forms Drag and Drop Support Instead! <- Click for more info
I'm going to suggest you bite the bullet and use the .Net Drag and Drop methods to do this. It requires some reading up, but it will be much better to use it.
You start a drag in response to a MouseDown event by calling Control.DoDragDrop().
Then you need to handle the Control.DragDrop event in the drop target control.
There's a few more things you might need to do to set it up; see the Control.DoDragDrop() documentation for an example.
(For WPF drag and drop support, see here.)
when your mouse enter the target control , mouse down triggerd ang get target BackColor! you need add an boolean flag to your code :
public Color currentColor;
bool flag=false;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
if(flag==false)
{
flag=true
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
}
//assume mouse up for panles
private void AttempsColorChanger(object sender, MouseEventArgs e)
{
if(flag==true)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
flag=flase;
}
}
and also you need change your flag in mouseMove( if )
As I mentioned in my comment Mouse Events are captured by the originating control, You would probably be better off using the DragDrop functionality built into Windows Forms. Something like this should work for you. I assigned common event handlers, so they can be assigned to all of your panels and just work.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void panel_MouseDown(object sender, MouseEventArgs e)
{
((Control)sender).DoDragDrop(((Control)sender).BackColor,DragDropEffects.All);
}
private void panel_DragDrop(object sender, DragEventArgs e)
{
((Control)sender).BackColor = (Color)e.Data.GetData(BackColor.GetType());
}
private void panel_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
}
I know it's an old question but I had the same issue and none of the above answers worked for me. In my case I had to handle the MouseMove event in the target control and check for the mouse to be released. I did set 'BringToFront' on my target panel just in case that helped at all.
public Color currentColor;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
private void panelTarget_MouseMove(object sender, MouseEventArgs e)
{
//the mouse button is released
if (SortMouseLocation == Point.Empty)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
}
}
I have added a keyPress event on a ListView. With a breakpoint on my event, I can see that most of the keys trigger the event. However, a few among which, the one I'm interested in (delete), just won't trigger my event.
Is that weird ? And no, there's no broken keys on my keyboard :D
private void listView1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Delete)
{
ListView target = (ListView)sender;
if (target.SelectedIndices != null && target.SelectedIndices.Count > 0)
{
string ric = target.SelectedItems[0].SubItems[0].Text;
//target.Items.RemoveAt(target.SelectedIndices[0]);
ListModels.getInstance().getModel("Vols").removeRic(ric);
}
}
}
The reason for this is that the KeyPress event sends a character to the control based upon the character-key you press. However, as you'd expect, the delete key does not represent a character and is thus a non-character key.
Therefore using the KeyPress event will do nothing as you have noticed. You should use the KeyDown or KeyUp Events, either of which will work absolutely fine. The nuance being whether you want your event to fire upon pressing, or letting go of a key.
You'll want to use the KeyDown event for this.
In KeyDown use the condition as follows,
if (e.KeyCode == Keys.Delete)
{
// Your Logic....
}
Use keyDown instead; keyPress is something like a full keyDown + keyUp
The problem is that if you set EditMode property to EditOnEnter it won't fire. If you use EditOnKeyStrokeOfF2 it will fire the event
If you are looking for a solution where the user should only be able to choose from the defined items, then I believe you can do it with this:
private void DropDownRank_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
See this code:
private void Form1_Load(object sender, EventArgs e)
{
listView1.KeyUp += new KeyEventHandler(ListView_KeyUp);
}
/// <summary>鍵盤觸發 ListView 清單</summary>
private void ListView_KeyUp(object sender, KeyEventArgs e)
{
ListView ListViewControl = sender as ListView;
if (e.KeyCode == Keys.Delete)
{
foreach (ListViewItem eachItem in ListViewControl.SelectedItems)
{
ListViewControl.Items.Remove(eachItem);
}
}
}
I tried all the stuff mentioned above but nothing worked for me, so im posting what i actually did and worked, in the hopes of helping others with the same problem as me:
Add an event handler in the constructor:
public partial class Test
{
public Test()
{
this.RemoveHandler(KeyDownEvent, new KeyEventHandler(Test_KeyDown));
// im not sure if the above line is needed (or if the GC takes care of it
// anyway) , im adding it just to be safe
this.AddHandler(KeyDownEvent, new KeyEventHandler(Test_KeyDown), true);
InitializeComponent();
}
//....
private void Test_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
//your logic
}
}
}
Is it possible to have a WPF window/element detect the drag'n'dropping of a file from windows explorer in C# .Net 3.5? I've found solutions for WinForms, but none for WPF.
Try the following :
private void MessageTextBox_Drop(object sender, DragEventArgs e)
{
if (e.Data is DataObject && ((DataObject)e.Data).ContainsFileDropList())
{
foreach (string filePath in ((DataObject)e.Data).GetFileDropList())
{
// Processing here
}
}
}
private void MessageTextBox_PreviewDragEnter(object sender, DragEventArgs e)
{
var dropPossible = e.Data != null && ((DataObject)e.Data).ContainsFileDropList();
if (dropPossible)
{
e.Effects = DragDropEffects.Copy;
}
}
private void MessageTextBox_PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
Unfortunately, TextBox, RichTextBox, and FlowDocument viewers always mark drag-and-drop events as handled, which prevents them from bubbling up to your handlers. You can restore drag-and-drop events being intercepted by these controls by force-handling the drag-and-drop events (use UIElement.AddHandler and set handledEventsToo to true) and setting e.Handled to false in your handler.
Turns out I couldn't drop onto my TextBox for some reason, but dropping onto buttons works fine. Got it working by adding 'AllowDrop="True"' to my window and adding drop event handler to button consisting of:
private void btnFindType_Drop(object sender, DragEventArgs e)
{
if (e.Data is System.Windows.DataObject &&
((System.Windows.DataObject)e.Data).ContainsFileDropList())
{
foreach (string filePath in ((System.Windows.DataObject)e.Data).GetFileDropList())
{
// Processing here
}
}
}
I had similar Issue, The drop events and drag enter events were not fired. The issue was with the windows User Account Settings. Set it to least secure setting and try the same code it works.