I am attempting to change a listview item's background colour when a mouse hovers over it
I have a mouse hover event, but how can I add a "highlight" effect upon a mouse hovering over the item?
private void pinnedAppsListBox_MouseHover(object sender, EventArgs e)
{
}
Use this:
private void pinnedAppsListBox_MouseHover(object sender, EventArgs e){
Point point = pinnedAppsListBox.PointToClient(Cursor.Position);
int index = pinnedAppsListBox.IndexFromPoint(point);
if (index < 0) return;
//Do any action with the item
pinnedAppsListBox.GetItemRectangle(index).Inflate(1,2);
}
Go to the ListView's ItemMouseHover event and add then set the property "BackColor" of the Item.
private void listView1_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
{
e.Item.BackColor = Color.Black;
}
Declare this Global variable
Use this Listview Item variable to keep track of what item was hovered on
ListViewItem lvHoveredItem;
Set the following function to turn on DoubleBuffering for your control to prevent flickering:
public static void SetDoubleBuffering(System.Windows.Forms.Control control, bool value)
{
System.Reflection.PropertyInfo controlProperty = typeof(System.Windows.Forms.Control)
.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
controlProperty.SetValue(control, value, null);
}
Where your control is loaded call this function
SetDoubleBuffering(lvTaskList, true);
Then use this code in the mousemove event of your listview
private void lvTaskList_MouseMove(object sender, MouseEventArgs e)
{
//Set the Color you want the list Item to be when mouse is over
Color oItemColor = Color.Lavender;
Color oOriginalColor = Color.blue; //Your original color
//get the Item the Mouse is currently hover
ListViewItem lvCurrentItem = lvTaskList.GetItemAt(e.X, e.Y);
if ((lvCurrentItem != null) && (lvCurrentItem != lvHoveredItem))
{
lvCurrentItem.BackColor = oItemColor;
if(lvHoveredItem != null)
{
lvHoveredItem.BackColor = oOriginalColor ;
}
lvHoveredItem = lvCurrentItem;
return;
}
if (lvCurrentItem == null)
{
if (lvHoveredItem != null)
{
lvHoveredItem.BackColor = oOriginalColor;
}
}
}
You can also add the MouseLeave Event
private void lvTaskList_MouseLeave(object sender, EventArgs e)
{
Color oOriginalColor = Color.Blue; //Your original color
//When the mouse leave the control. If a ListViewItem was highlighted then set it's original color back
if (lvHoveredItem != null)
{
lvHoveredItem.BackColor = oOriginalColor ;
}
lvHoveredItem = null;
}
If you're using a ListBox, it is quite more difficult to handle, you will need to set a MouseHover event for the ListBox and determine which item is being hovered on and then draw it manually.
See this answer.
However if you're using a ListView, you can easily add an ItemMouseHover event like this:
private void pinnedAppsListView_MouseHover(object sender, EventArgs e)
{
e.Item.BackColor = Color.Lime;
}
I have seen this question many times without a good answer.
There is no good answer that I know, but, I did it, using some hints elsewhere.
I did this using Lazarus, but you should be able to adapt it to your language.
Get the item. You may want to set variables to catch these individually.
You may also want to get the state of your mouse buttons at mousedown first.
If (ListView.GetItemAt(X,Y) <> nil) then // do this with an if else
// Next, you can get the bounding rect:
ListView.GetItemAt(X,Y).DisplayRect(drSelectBounds);
//Option: If Button up or down then
// you may have to catch this elsewhere, such as for a drag operation.
// Create and set a boolean variable:
HighLightOn := True;
ListView.Repaint; // clears previous hightlights
ListView.Canvas.Brush.Color := clBtnFace; // or your color of choice
ListView.Canvas.FillRect(Rect);
// If you are moving around in an area where GetItem is nil,
// then do this to stop flicker and remove the highlight:
If (ListView.GetItemAt(X,Y) = nil) // do this with an if else
If HighLightOn then
begin
SelectedList.Repaint;
HighLightOn := False;
end;
// If a highlight gets left behind,
// you may need to repeat this elsewhere, such as in a component exit.
// This is the basic gist of the issue.
// There can be a lot of options or things to look for,
// so you code could get more complicated.
// I am not suggesting this is the best way to implement it,
// but it is easy. Part of this code only works inside your app!
Related
I've got a MouseDown event on my GridView:
private void gdcSVNDefaultView_MouseDown(object sender, MouseEventArgs e)
{
var vw = (GridView)sender;
var hitInfo = vw.CalcHitInfo(e.Location);
DXMouseEventArgs.GetMouseArgs(e).Handled = SelectChildRows(hitInfo.RowHandle, vw);
}
private static bool SelectChildRows(int r, GridView view)
{
if (!view.IsGroupRow(r) || !view.GetRowExpanded(r))
return false;
var childRowCount = view.GetChildRowCount(r);
var first = view.GetChildRowHandle(r, 0);
var last = (first + childRowCount - 1);
view.SelectRange(first, last);
return true;
}
Screenshot of my form since not everyone is familiar with the DevExpress grids and might not know what i mean by a 'Group':
When you have a Group in the grid and click on that Group row instead of an actual 'data' row, I want to select all the child rows belonging to that Group.
The code works. If I click on a Group (for example, Type: Warning in my screenshot) and hold the mouse down I can see it select all the child rows... But as soon as I let up on the mouse, it de-selects them and selects just the group row. So if you just click quickly, like you normally would, you see them all flash quickly as as their selected state toggles.
Unfortunately, the Mouse events don't have any sort of "Handled" property I can set to make the MouseUp / Click not fire. I tried moving the code in my MouseDown to the MouseUp event and it doesn't even temporarily select everything. DX also has a "RowClick" event, tried it there... same results as the MouseUp.
Any ideas on how I can "cancel" those events?
Edit: Turns out there is a Handled property if you cast the MouseEventArgs to a DXMouseEventArgs object... But it still observes the same behavior.
Alright, so I found out that I need to set Handled in both the MouseDown and MouseUp events in order to get the behavior desired:
public class MyForm
{
private bool _b;
private void gdcSVNDefaultView_MouseDown(object sender, MouseEventArgs e)
{
var vw = (GridView)sender;
var hitInfo = vw.CalcHitInfo(e.Location);
if (hitInfo.HitTest == GridHitTest.RowGroupButton)
return;
_b = false;
if (vw.IsGroupRow(hitInfo.RowHandle))
_b = SelectChildRows(hitInfo.RowHandle, vw);
DXMouseEventArgs.GetMouseArgs(e).Handled = _b;
}
private void gdcSVNDefaultView_MouseUp(object sender, MouseEventArgs e)
{
DXMouseEventArgs.GetMouseArgs(e).Handled = _b;
}
private static bool SelectChildRows(int r, GridView view)
{
if (!view.GetRowExpanded((r)))
return false;
if (ModifierKeys != Keys.Shift && ModifierKeys != Keys.Control)
view.ClearSelection();
var childRowCount = view.GetChildRowCount(r);
var first = view.GetChildRowHandle(r, 0);
var last = (first + childRowCount - 1);
view.SelectRange(first, last);
return true;
}
}
Note: This IF block is NOT required for the core functionality. I found that if I click on multiple Groups it was adding that Range to the current Selection, which might be unexpected behavior for the end user. I added a check to see if the user is holding down the Control or Shift keys when they click the Group row. If not, then clear the current selection and select the new range
Have you tried using the Click event instead of MouseDown? Might be worth a shot. From here:
Note that the Click event also fires after the mouse button has been released. The difference is that the Click event is only raised if the mouse pointer is within the View when releasing the mouse button.
How can I get the type of pressed pointer (left mouse down or right mouse down) in a Metro style C# app? I didn't find a MouseLeftButtonDown event handler in any Metro style UI element. I should use PointerPressed event instead, but I don't know how can i get which button was pressed.
PointerPressed is enough to handle mouse buttons:
void MainPage_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Check for input device
if (e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
var properties = e.GetCurrentPoint(this).Properties;
if (properties.IsLeftButtonPressed)
{
// Left button pressed
}
else if (properties.IsRightButtonPressed)
{
// Right button pressed
}
}
}
You can use the following event to determine what pointer is used and what button is pressed.
private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
if (ptrPt.Properties.IsLeftButtonPressed)
{
//Do stuff
}
if (ptrPt.Properties.IsRightButtonPressed)
{
//Do stuff
}
}
Working on a UWP project and previous answers like
Properties.IsLeftButtonPressed/IsRightButtonPressed did not work for me. Those values are always false. I realized during the Debugging that Properties.PointerUpdateKind was changing according to mouse button. Here is the result which worked for me:
var properties = e.GetCurrentPoint(this).Properties;
if (properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.LeftButtonReleased)
{
}
else if (properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.RightButtonReleased)
{
}
else if (properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.MiddleButtonReleased)
{
}
There are more options in PointerUpdateKind like ButtonPressed varities of the ones in the example and XButton varities e.g. XButton1Pressed, XButton2Released etc.
Here's my code:
public void Repaint() {
canvas1.Children.Clear();
ObservableCollection<ClassBox> classes = viewModel.Classes;
foreach (ClassBox j in classes) {
// connect our ui element to the mouse handler if not done already
if (!j.MouseActive) {
j.Box.PreviewMouseLeftButtonUp += Handle_MouseUp;
j.Box.PreviewMouseLeftButtonDown += Handle_MouseDown;
j.Box.PreviewMouseMove += Handle_MouseMove;
j.MouseActive = true;
// Heres should the code be written (something like :)
// j.Box.SetColor(Change_Color(value));
}
canvas1.Children.Add(j.Box);
} }
So the above code presents how the boxes are being repainted when im calling the method.
Works fine but now for the next part of the code:
private void Change_ColourBox(object sender, System.Windows.RoutedEventArgs e)
{
var element = sender as FrameworkElement;
ObservableCollection<ClassBox> classes = viewModel.Classes;
foreach (ClassBox j in classes)
{
// connect our ui element to the mouse handler if not done already
if (sender == BoxStandard)
{
j.Box.Background = new SolidColorBrush(Colors.White);
j.Box.Foreground = new SolidColorBrush(Colors.Black);
Repaint();
} }
This code tell that we should change color when the button "Change_Color" is pressed.
I have implemented the buttons in XAML and I have given them names, in this case "BoxStandard".
The next code snipp is where i spawn the box via an event handler.
private void Spawn_Box(object sender, System.Windows.RoutedEventArgs e) {
viewModel.GetURController.AddAndExecute(new AddClassCommand(viewModel));
}
Im gonna line it up: I give predefined colors to my elements which they start out with. When I change the colors via the click event "Change_Color" they change to the desired color. BUT when I then spawn a new element to the canvas its in the predefined color. I want to spawn it with the changed color.
Ask if you don't understand question I can explain deeper!
The ClassBox is an object which consists of properties for the boxes. The repaint is not only for foreground/background color its also calculating the difference in positioning of the boxes
I need to determine if the value of a NumericUpDown control was changed by a mouseUp event.
I need to call an expensive function when the value of a numericupdown has changed. I can't just use "ValueChanged", I need to use MouseUp and KeyUp events.
Basically, I need to know:
Did the value of the numericUpDown change when the user let go of the
mouse? If any area which is not highlighted in red is clicked, the
answer is no. I need to IGNORE the mouse up event, when ANYWHERE but the red area is clicked.
How can I determine this by code? I find events a little confusing.
This will fire when the user releases the mouse button. You might want to investigate which mousebutton was released.
EDIT
decimal numvalue = 0;
private void numericUpDown1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && numvalue != numericUpDown1.Value)
{
//expensive routines
MessageBox.Show(numericUpDown1.Value.ToString());
}
numvalue = numericUpDown1.Value;
}
EDIT 2
This will determine if the left mousebutton is still down, if it is exit before performing expensive routine, doesn't help with keyboard button down.
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
{
return;
}
//expensive routines
}
Edit 3
How to detect the currently pressed key?
Will help solve the Any key down, Though I think the only ones that matter are the arrow keys
Problem - I need to IGNORE the mouse up event, when ANYWHERE but the red area is clicked.
Derive a custom numeric control as shown below. Get the TextArea of the Numeric Control and ignore the KeyUp.
class UpDownLabel : NumericUpDown
{
private Label mLabel;
private TextBox mBox;
public UpDownLabel()
{
mBox = this.Controls[1] as TextBox;
mBox.Enabled = false;
mLabel = new Label();
mLabel.Location = mBox.Location;
mLabel.Size = mBox.Size;
this.Controls.Add(mLabel);
mLabel.BringToFront();
mLabel.MouseUp += new MouseEventHandler(mLabel_MouseUp);
}
// ignore the KeyUp event in the textarea
void mLabel_MouseUp(object sender, MouseEventArgs e)
{
return;
}
protected override void UpdateEditText()
{
base.UpdateEditText();
if (mLabel != null) mLabel.Text = mBox.Text;
}
}
In the MainForm, update your designer with this control i.e. UpDownLabel:-
private void numericUpDown1_MouseUp(object sender, MouseEventArgs e)
{
MessageBox.Show("From Up/Down");
}
Referred from - https://stackoverflow.com/a/4059473/763026 & handled the MouseUp event.
Now, use this control instead of the standard one and hook on the
KeyUp event. You will always get the KeyUp event from the Up/Down button only i.e. RED AREA when you click the
spinner [Up/Down button, which is again a different control derived
from UpDownBase].
I think you should use Leave event that when the focus of NumericUpDown control gone, it would called.
int x = 0;
private void numericUpDown1_Leave(object sender, EventArgs e)
{
x++;
label1.Text = x.ToString();
}
Is it possible to create a toggle button in C# WinForms? I know that you can use a CheckBox control and set it's Appearance property to "Button", but it doesn't look right. I want it to appear sunken, not flat, when pressed. Any thoughts?
You can just use a CheckBox and set its appearance to Button:
CheckBox checkBox = new System.Windows.Forms.CheckBox();
checkBox.Appearance = System.Windows.Forms.Appearance.Button;
Check FlatStyle property. Setting it to "System" makes the checkbox sunken in my environment.
You may also consider the ToolStripButton control if you don't mind hosting it in a ToolStripContainer. I think it can natively support pressed and unpressed states.
thers is a simple way to create toggle button. I test it in vs2010. It's perfect.
ToolStripButton has a "Checked" property and a "CheckOnClik" property. You can use it to act as a toggle button
tbtnCross.CheckOnClick = true;
OR
tbtnCross.CheckOnClick = false;
tbtnCross.Click += new EventHandler(tbtnCross_Click);
.....
void tbtnCross_Click(object sender, EventArgs e)
{
ToolStripButton target = sender as ToolStripButton;
target.Checked = !target.Checked;
}
also, You can create toggle button list like this:
private void Form1_Load(object sender, EventArgs e)
{
arrToolView[0] = tbtnCross;
arrToolView[1] = tbtnLongtitude;
arrToolView[2] = tbtnTerrain;
arrToolView[3] = tbtnResult;
for (int i = 0; i<arrToolView.Length; i++)
{
arrToolView[i].CheckOnClick = false;
arrToolView[i].Click += new EventHandler(tbtnView_Click);
}
InitTree();
}
void tbtnView_Click(object sender, EventArgs e)
{
ToolStripButton target = sender as ToolStripButton;
if (target.Checked) return;
foreach (ToolStripButton btn in arrToolView)
{
btn.Checked = false;
//btn.CheckState = CheckState.Unchecked;
}
target.Checked = true;
target.CheckState = CheckState.Checked;
}
How about this?
Assuming you have System.Windows.Forms referenced.
var cbtnToggler = new CheckBox();
cbtnToggler.Appearance = Appearance.Button;
cbtnToggler.TextAlign = ContentAlignment.MiddleCenter;
cbtnToggler.MinimumSize = new Size(75, 25); //To prevent shrinkage!
Hope this helps ;)
This is my simple codes I hope it can help you
private void button2_Click(object sender, EventArgs e)
{
if (button2.Text == "ON")
{
panel_light.BackColor = Color.Yellow; //symbolizes light turned on
button2.Text = "OFF";
}
else if (button2.Text == "OFF")
{
panel_light.BackColor = Color.Black; //symbolizes light turned off
button2.Text = "ON";
}
}
When my button's FlatStyle is set to system, it looks flat. And when it's set to popup, it only pops up when mouses over. Either is what I want. I want it to look sunken when checked and raised when unchecked and no change while mousing over (the button is really a checkbox but the checkbox's appearance property is set to button).
I end up setting the FlatStyle to flat and wrote a new Paint event handler.
private void checkbox_paint(object sender, PaintEventArgs e)
{
CheckBox myCheckbox = (CheckBox)sender;
Rectangle borderRectangle = myCheckbox.ClientRectangle;
if (myCheckbox.Checked)
{
ControlPaint.DrawBorder3D(e.Graphics, borderRectangle,
Border3DStyle.Sunken);
}
else
{
ControlPaint.DrawBorder3D(e.Graphics, borderRectangle,
Border3DStyle.Raised);
}
}
I give a similar answer to this question:
C# winforms button with solid border, like 3d
Sorry for double posting.
You can always code your own button with custom graphics and a PictureBox, though it won't necessarily match the Windows theme of your users.
I ended up overriding the OnPaint and OnBackgroundPaint events and manually drawing the button exactly like I need it. It worked pretty well.
use if command to check status and let operate as a toggle button
private void Protection_ON_OFF_Button_Click(object sender, EventArgs e)
{
if (FolderAddButton.Enabled == true)
{
FolderAddButton.Enabled = false;
}
else
{
FolderAddButton.Enabled = true;
}
}
You should look into Siticone I use it and I love it. It works exactly like a checkbox but is a toggle button. Its downside is a message box will come up every time you open Visual Studios so I just installed a tool that disables it. You can also look into Guana but I found that to have a few bugs :)
Changing a CheckBox appearance to Button will give you difficulty in adjustments. You cannot change its dimensions because its size depends on the size of your text or image.
You can try this: (initialize the count variable first to 1 | int count = 1)
private void settingsBtn_Click(object sender, EventArgs e)
{
count++;
if (count % 2 == 0)
{
settingsPanel.Show();
}
else
{
settingsPanel.Hide();
}
}
It's very simple but it works.
Warning: This will work well with buttons that are occasionally used (i.e. settings), the value of count in int/long may be overloaded when used more than it's capacity without closing the app's process. (Check data type ranges: http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx)
The Good News: If you're running an app that is not intended for use 24/7 all-year round, I think this is helpful. Important thing is that when the app's process ended and you run it again, the count will reset to 1.