I have a treeview but when I click on a node it displays a blue background.
Do you have a solution to remove this blue background ? I am using winform c#
Thanks
To eliminate the blue background color of a node that is selected by mouse click, set the DrawMode property of the tree view to OwnerDrawText and handle the node label drawing as shown:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
treeView.DrawNode += customDrawNode;
treeView.AfterSelect += setTitleBarText;
}
If the node is selected, custom draw the label. Non-selected nodes draw default.
private void customDrawNode(object? sender, DrawTreeNodeEventArgs e)
{
if(sender is TreeView treeView)
{
if ((e.Node != null) && e.State.HasFlag(TreeNodeStates.Selected))
{
using (var brush = new SolidBrush(treeView.BackColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
using (var brush = new SolidBrush(treeView.ForeColor))
{
e.Graphics.DrawString(e.Node.Text, treeView.Font, brush, e.Bounds);
}
return;
}
}
e.DrawDefault = true;
}
Verify selected node by setting main form text.
private void setTitleBarText(object? sender, TreeViewEventArgs e)
{
Text =
treeView.SelectedNode == null ?
"Main Form" :
$"Main Form: {treeView.SelectedNode.Text}";
}
}
Related
I want to show tooltip on ListBox, so in load form I have:
lstTech.DrawMode = DrawMode.OwnerDrawFixed;
var techListQuery = $"exec getTaskAssignableEmployeeList";
var techList = db.GetTableBySQL(techListQuery);
lstTech.DataSource = techList.ToList();
lstTech.DisplayMember = "Abbreviation";
lstTech.ValueMember = "EmpGuid";
Then in DrawItem method I have:
private void lstTech_DrawItem(object sender, DrawItemEventArgs e)
{
ListBox senderListBox = (ListBox)sender;
if (e.Index < 0)
{
return;
}
var item = ((DataRowView)senderListBox.Items[e.Index]);
var abbr = senderListBox.GetItemText(item["Abbreviation"]);
var name = senderListBox.GetItemText(item["Name"]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(abbr, e.Font, br, e.Bounds);
}
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected )
{
ttTechs.Show(name, senderListBox, e.Bounds.Right, senderListBox.PointToClient(Cursor.Position).Y);
}
e.DrawFocusRectangle();
}
Then I want to disappear Tooltip on mouse leave like:
private void lstTech_MouseLeave(object sender, EventArgs e)
{
ListBox senderListBox = (ListBox)sender;
ttTechs.Hide(senderListBox);
}
So now Tooltip works, it appear when I clic on some item of list, problem is I don't want it on clic, I want it in Hover event. So I try:
private void lstTech_MouseHover(object sender, EventArgs e)
{
ListBox senderListBox = (ListBox)sender;
ttTechs.Show(senderListBox);
}
But it returns me an error:
No overload for method 'Show' takes 1 arguments
What am I doing wrong? what I need to display tooltip on hover event and remove from click event? Regards
Update
As answer below I change code to:
//Set tooltip as Global variable
ToolTip toolTip = new ToolTip();
//Create new method to assign Draw
private void SetToolTipText()
{
var content = string.Empty;
foreach (DataRowView list in lstTech.SelectedItems)
{
var techName = list[1].ToString();
content += techName + Environment.NewLine;
}
toolTip.SetToolTip(lstTech, content);
}
//Draw method
private void lstTech_DrawItem(object sender, DrawItemEventArgs e)
{
SetToolTipText();
}
Problem is list items are invisible, if I click in listbox Tooltip appears correctly but list is not displayed. If I remove lstTech.DrawMode = DrawMode.OwnerDrawVariable; from load_form listbox items appears again but tooltip stop working. What is going on there?
There's a ToolTip control in WinForms which you can make use of.
Let's say your list box contains a bunch of names, and I want to only display the first 3 letters of each name on the tool tip. So I would write a function to go through each item in the list box and filter the names and create a string, then set it to the tool tip.
private void SetToolTipText()
{
var content = string.Empty;
foreach (var item in listBox1.Items)
{
var first3 = item.ToString().Substring(0, 3);
content += first3 + Environment.NewLine;
}
toolTip.SetToolTip(listBox1, content);
}
Note that the toolTip is a global variable in my Form.
public partial class MainForm : Form
{
ToolTip toolTip = new ToolTip();
public MainForm()
{
InitializeComponent();
}
Next I would call that function in my DrawItem() event like so:
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
SetToolTipText();
}
In your program, instead of taking the first 3 characters of the string, do whatever the filtering you do.
I have a tableLayoutPanel with 16 cells. 15 of the cells have controls. I want to be able to move the controls from one cell to another at runtime.
I have used
private void button15_Click(object sender, EventArgs e)
{
tableLayoutPanel1.Controls.Remove(button15);
tableLayoutPanel1.Controls.Add(button15, 3, 3);
}
This works well but i want to know if there is any better way to do this???
In Winforms, you can only move a control inside its parent (of course there are some exceptions to some controls which in fact don't have any Parent). So the idea here is if you want to move a control of your TableLayoutPanel, you have to set its Parent to your Form of another container when mouse is held down, when moving, the position of the control is in the new parent, after mouse is released, we have to set the Parent of the control to the TableLayoutPanel back, of course we have to find the drop-down cell position and use SetCellPosition method to position the control on the TableLayoutPanel, here is the demo code for you (works great), I use 2 Buttons in this demo, you can replace them with any control you want:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
//This will prevent flicker
typeof(TableLayoutPanel).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(tableLayoutPanel1, true, null);
}
Point downPoint;
bool moved;
//This is used to store the CellBounds together with the Cell position
//so that we can find the Cell position later (after releasing mouse).
Dictionary<TableLayoutPanelCellPosition, Rectangle> dict = new Dictionary<TableLayoutPanelCellPosition, Rectangle>();
//MouseDown event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseDown(object sender, MouseEventArgs e) {
Control button = sender as Control;
button.Parent = this;
button.BringToFront();
downPoint = e.Location;
}
//MouseMove event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseMove(object sender, MouseEventArgs e) {
Control button = sender as Control;
if (e.Button == MouseButtons.Left) {
button.Left += e.X - downPoint.X;
button.Top += e.Y - downPoint.Y;
moved = true;
tableLayoutPanel1.Invalidate();
}
}
//MouseUp event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseUp(object sender, MouseEventArgs e) {
Control button = sender as Control;
if (moved) {
SetControl(button, e.Location);
button.Parent = tableLayoutPanel1;
moved = false;
}
}
//This is used to set the control on the tableLayoutPanel after releasing mouse
private void SetControl(Control c, Point position) {
Point localPoint = tableLayoutPanel1.PointToClient(c.PointToScreen(position));
var keyValue = dict.FirstOrDefault(e => e.Value.Contains(localPoint));
if (!keyValue.Equals(default(KeyValuePair<TableLayoutPanelCellPosition, Rectangle>))) {
tableLayoutPanel1.SetCellPosition(c, keyValue.Key);
}
}
//CellPaint event handler for your tableLayoutPanel1
private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e) {
dict[new TableLayoutPanelCellPosition(e.Column, e.Row)] = e.CellBounds;
if (moved) {
if (e.CellBounds.Contains(tableLayoutPanel1.PointToClient(MousePosition))) {
e.Graphics.FillRectangle(Brushes.Yellow, e.CellBounds);
}
}
}
}
Remove Lock & set dock to none and move!
I have a textBlock to which I've added some text e.g. as follows:
textBlock1.Inlines.Add(new Run("One "));
textBlock1.Inlines.Add(new Run("Two "));
textBlock1.Inlines.Add(new Run("Three "));
How can I add a click event that changes the color of the text of the inline that has been clicked?
e.g. if "One" is clicked I'd like it to have a red font; then if "Two" is clicked, I'd like "One" to be black again, and "Two" to be red, so that the color of the last word clicked is red.
I'm fairly new to programming with c# and wpf.
Thanks for your help
Something like this should do the trick
public MainWindow()
{
InitializeComponent();
textBlock1.Inlines.Add(new Run("One "));
textBlock1.Inlines.Add(new Run("Two "));
textBlock1.Inlines.Add(new Run("Three "));
}
private SolidColorBrush _blackBrush = new SolidColorBrush(Colors.Black);
private SolidColorBrush _redBrush = new SolidColorBrush(Colors.Red);
private Run _selectedRun;
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
var run = e.OriginalSource as Run;
if (run != null)
{
if (_selectedRun != null)
{
_selectedRun.Foreground = _blackBrush;
if (_selectedRun == run)
{
return;
}
}
run.Foreground = _redBrush;
_selectedRun = run;
}
}
But you will have to handle click with "MouseDown" or "MouseUp" as Textblock does not have Click event
To color one at a certain index this is a quick example.
private void ColorInlineAtIndex(InlineCollection inlines, int index, Brush brush)
{
if (index <= inlines.Count - 1)
{
inlines.ElementAt(index).Foreground = brush;
}
}
Usage:
ColorInlineAtIndex(textBlock1.Inlines, 2, new SolidColorBrush(Colors.Blue));
Find position:
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
var run = e.OriginalSource as Run;
if (run != null)
{
int position = (sender as TextBlock).Inlines.ToList().IndexOf(run);
}
}
I was wondering how could I do this. I know I can use the button component but it has the little gray stuff around it when I give it a image. With image button how could I show another image for the hover effect
You want to create a button with no border but displays different images when the user hovers over it with the mouse? Here's how you can do it:
Add an ImageList control to your form at add two images, one for the button's normal appearance and one for when the mouse is hovering over.
Add your button and set the following properties:
FlatStyle = Flat
FlatAppearance.BorderColor (and maybe MouseOverBackColor & MouseDownBackColor) to your form's background color
ImageList = the ImageList you added to the form
ImageIndex to the index value of your normal image
Code the MouseHover and MouseLeave events for the button like this:
// ImageList index value for the hover image.
private void button1_MouseHover(object sender, EventArgs e) => button1.ImageIndex = 1;
// ImageList index value for the normal image.
private void button1_MouseLeave(object sender, EventArgs e) => button1.ImageIndex = 0;
I believe that will give you the visual effect you're looking for.
Small summary (Border, MouseDownBackColor, MouseOverBackColor)
FlatApperance
BorderColor = Black or what ever you want
BorderSize = can be set to 0
MouseDownBackColor = Transparent
MouseOverBackColor = Transparent
Text = none
For MouseDown:
// ImageList index value for the mouse down image.
private void button1_MouseDown(object sender, MouseEventArgs e) => button1.ImageIndex = 2;
You can assign the BackgroundImage property for the button. You can also use the OnMouseEnter and OnMouseExit events to change the background as per your request.
See BackgroundImage OnMouseEnter OnMouseLeave
I also needed an image button, but I wanted one like the ToolstripMenuButton.
With the correct borders and colors on hover.
So I made a custom control to do just that:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace LastenBoekInfrastructure.Controls.Controls
{
[DefaultEvent("Click")]
public class ImageButton : UserControl
{
public string ToolTipText
{
get { return _bButton.ToolTipText; }
set { _bButton.ToolTipText = value; }
}
public bool CheckOnClick
{
get { return _bButton.CheckOnClick; }
set { _bButton.CheckOnClick = value; }
}
public bool DoubleClickEnabled
{
get { return _bButton.DoubleClickEnabled; }
set { _bButton.DoubleClickEnabled = value; }
}
public System.Drawing.Image Image
{
get { return _bButton.Image; }
set { _bButton.Image = value; }
}
public new event EventHandler Click;
public new event EventHandler DoubleClick;
private ToolStrip _tsMain;
private ToolStripButton _bButton;
public ImageButton()
{
InitializeComponent();
}
private void InitializeComponent()
{
var resources = new ComponentResourceManager(typeof(ImageButton));
_tsMain = new ToolStrip();
_bButton = new ToolStripButton();
_tsMain.SuspendLayout();
SuspendLayout();
//
// tsMain
//
_tsMain.BackColor = System.Drawing.Color.Transparent;
_tsMain.CanOverflow = false;
_tsMain.Dock = DockStyle.Fill;
_tsMain.GripMargin = new Padding(0);
_tsMain.GripStyle = ToolStripGripStyle.Hidden;
_tsMain.Items.AddRange(new ToolStripItem[] {
_bButton});
_tsMain.Location = new System.Drawing.Point(0, 0);
_tsMain.Name = "_tsMain";
_tsMain.Size = new System.Drawing.Size(25, 25);
_tsMain.TabIndex = 0;
_tsMain.Renderer = new ImageButtonToolStripSystemRenderer();
//
// bButton
//
_bButton.DisplayStyle = ToolStripItemDisplayStyle.Image;
_bButton.Image = ((System.Drawing.Image)(resources.GetObject("_bButton.Image")));
_bButton.ImageTransparentColor = System.Drawing.Color.Magenta;
_bButton.Name = "_bButton";
_bButton.Size = new System.Drawing.Size(23, 22);
_bButton.Click += bButton_Click;
_bButton.DoubleClick += bButton_DoubleClick;
//
// ImageButton
//
Controls.Add(_tsMain);
Name = "ImageButton";
Size = new System.Drawing.Size(25, 25);
_tsMain.ResumeLayout(false);
_tsMain.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
void bButton_Click(object sender, EventArgs e)
{
if (Click != null)
{
Click(this, e);
}
}
void bButton_DoubleClick(object sender, EventArgs e)
{
if(DoubleClick != null)
{
DoubleClick(this, e);
}
}
public class ImageButtonToolStripSystemRenderer : ToolStripSystemRenderer
{
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
//base.OnRenderToolStripBorder(e);
}
}
}
}
I want to add a label to my form , and I want it without any color- I want just it's text to be visible, I don't find this option in the label's properties, can anyone help me please?
Do you want to make the label (except for the text) transparent? Windows Forms (I assume WinForms - is this true) doesn't really support transparency. The easiest way, sometimes, is Label's Backcolor to Transparent.
label1.BackColor = System.Drawing.Color.Transparent;
You will run into problems though, as WinForms really doesn't properly support transparency. Otherwise, see here:
http://www.doogal.co.uk/transparent.php
http://www.codeproject.com/KB/dotnet/transparent_controls_net.aspx
http://www.daniweb.com/code/snippet216425.html
Setting the parent of a usercontrol prevents it from being transparent
Good luck!
If you picture box in the background then use this:
label1.Parent = pictureBox1;
label1.BackColor = Color.Transparent;
Put this code below InitializeComponent(); or in Form_Load Method.
Ref: https://www.c-sharpcorner.com/blogs/how-to-make-a-transparent-label-over-a-picturebox1
You are right. but here is the simplest way for making the back color of the label transparent
In the properties window of that label select Web.. In Web select Transparent
:)
this.label1.BackColor = System.Drawing.Color.Transparent;
Let's view 2 possible cases.
Background is a color.
Double-Click the form background in VS constructor. Then, write this code:
/*
This code will set all your object's background color to the same as the form.
This should be written in the body of <FormName>_Load(object, EventArgs).
*/
Control[] objs = new Control[] { /* your object list, e. g { myLabel, myPicture } */ };
foreach (Control control in objs) {
control.BackColor = Color.Transparent;
// OR
control.BackColor = this.BackColor;
}
Background is a PictureBox.
This is also easy. We just need to make all objects as children of your PictureBox and set it's color to transparent. Code:
/*
This code will set all your object's background to transparent and show the PBox.
This should be written in the body of <FormName>_Load(object, EventArgs)'s foreach loop.
Put everything before it the same as in 1st code fragment.
*/
control.Parent = back;
control.BackColor = Color.Transparent;
Let's see the pictures.
Color
Before
After
PictureBox
Before
After (here foreground were changed, don't mind this)
Generally, labels and textboxes that appear in front of an image is best organized in a panel. When rendering, if labels need to be transparent to an image within the panel, you can switch to image as parent of labels in Form initiation like this:
var oldParent = panel1;
var newParent = pictureBox1;
foreach (var label in oldParent.Controls.OfType<Label>())
{
label.Location = newParent.PointToClient(label.Parent.PointToScreen(label.Location));
label.Parent = newParent;
label.BackColor = Color.Transparent;
}
This uses Graphics.CopyFromScreen so the control needs to be added when it's visable on screen.
public partial class TransparentLabelControl : Label
{
public TransparentLabelControl()
{
this.AutoSize = true;
this.Visible = false;
this.ImageAlign = ContentAlignment.TopLeft;
this.Visible = true;
this.Resize += TransparentLabelControl_Resize;
this.LocationChanged += TransparentLabelControl_LocationChanged;
this.TextChanged += TransparentLabelControl_TextChanged;
this.ParentChanged += TransparentLabelControl_ParentChanged;
}
#region Events
private void TransparentLabelControl_ParentChanged(object sender, EventArgs e)
{
SetTransparent();
if (this.Parent != null)
{
this.Parent.ControlAdded += Parent_ControlAdded;
this.Parent.ControlRemoved += Parent_ControlRemoved;
}
}
private void Parent_ControlRemoved(object sender, ControlEventArgs e)
{
SetTransparent();
}
private void Parent_ControlAdded(object sender, ControlEventArgs e)
{
if (this.Bounds.IntersectsWith(e.Control.Bounds))
{
SetTransparent();
}
}
private void TransparentLabelControl_TextChanged(object sender, EventArgs e)
{
SetTransparent();
}
private void TransparentLabelControl_LocationChanged(object sender, EventArgs e)
{
SetTransparent();
}
private void TransparentLabelControl_Resize(object sender, EventArgs e)
{
SetTransparent();
}
#endregion
public void SetTransparent()
{
if (this.Parent!= null)
{
this.Visible = false;
this.Image = this.takeComponentScreenShot(this.Parent);
this.Visible = true;
}
}
private Bitmap takeComponentScreenShot(Control control)
{
Rectangle rect = control.RectangleToScreen(this.Bounds);
if (rect.Width == 0 || rect.Height == 0)
{
return null;
}
Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
return bmp;
}
}
An easy way to have a label with a picture behind it is to use the Image Property of the label itself. This will print the text over the top of the picture, and enable you to align the image (top/bottom/left/right/centre) as required.picture