Creating a tooltip from a system-tray only app - c#

So I'm trying to create a tooltip at some point on the screen.
ToolTip tip = new ToolTip();
tip.Show("foobar", **IWin32Window window**, new Point(100, 100))
The problem is I don't know what to insert as the window parameter in the above. My app runs entirely out of the system tray, and has no other GUI elements. It's called notifyIcon1. That is created through Form1. Neither of these values work when plugged in to tip.Show().
How can I generate a tooltip anywhere on my screen using only the system tray?
Thanks.

The IWin32Window interface is a simple interface that only provides a IntPtr property named Handle. Feasibly something like this should work:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace SO_ToolTip
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
WindowWrapper windowWrapper = new WindowWrapper(GetDesktopWindow());
ToolTip toolTip = new ToolTip();
toolTip.Show("Blah blah... Blah blah... Blah blah...", windowWrapper, 1, 1, 10000);
}
}
public class WindowWrapper : IWin32Window
{
public WindowWrapper(IntPtr handle)
{
Handle = handle;
}
public IntPtr Handle { get; protected set; }
}
}
But it doesn't. It complains about a NullReferenceException and I haven't debugged further. This does work:
...
private void button1_Click(object sender, EventArgs e)
{
ToolTip toolTip = new ToolTip();
toolTip.Show("Blah blah... Blah blah... Blah blah...", this, 1, 1, 10000);
}
...
Although the position is relative to the current form. Maybe that will get you going in the right direction.
Edit: Even this doesn't work so I'm not sure if it's an issue with WindowWrapper (how?) or what:
...
private void button1_Click(object sender, EventArgs e)
{
WindowWrapper windowWrapper = new WindowWrapper(this.Handle);
ToolTip toolTip = new ToolTip();
toolTip.Show("Blah blah... Blah blah... Blah blah...", windowWrapper, 1, 1, 10000);
}
...
Here you go, use a transparent, maximized form that you BringToFront() before showing the ToolTip
Form1 Code:
using System;
using System.Windows.Forms;
namespace SO_ToolTip
{
public partial class Form1 : Form
{
Random _Random = new Random();
ToolTip _ToolTip = new ToolTip();
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
BringToFront();
_ToolTip.Show("Blah blah... Blah blah... Blah blah...", this, _Random.Next(0, Width), _Random.Next(0, Height), 10000);
}
}
}
Form1 Designer Code: So you can see the forms properties:
namespace SO_ToolTip
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 264);
this.ControlBox = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.Opacity = 0;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Timer timer1;
}
}

Joining late to the party:
In case you prefer/need to have WPF window:
private class ToolTipWPFWindow : Window
{
private readonly TextBlock m_txtToDisplay = new TextBlock();
private readonly DispatcherTimer m_timer = new DispatcherTimer();
public ToolTipWindow(string p_strStringToDisplay, int p_intXOnScreen = 0, int p_intYOnScreen = 0, double p_dblDurationInMilliSeconds = 1500)
{
if (p_intXOnScreen == 0 && p_intYOnScreen == 0)
{
p_intXOnScreen = System.Windows.Forms.Cursor.Position.X;
p_intYOnScreen = System.Windows.Forms.Cursor.Position.Y;
}
m_txtToDisplay.Text = p_strStringToDisplay;
m_txtToDisplay.Margin = new Thickness(3);
Background = new SolidColorBrush(Colors.LightGoldenrodYellow);
ShowInTaskbar = false;
ResizeMode = System.Windows.ResizeMode.NoResize;
Topmost = true;
// Location on screen - As Set
WindowStartupLocation = WindowStartupLocation.Manual;
Left = p_intXOnScreen;
Top = p_intYOnScreen;
WindowStyle = WindowStyle.None;
SizeToContent = SizeToContent.WidthAndHeight;
Content = m_txtToDisplay;
m_timer.Interval = TimeSpan.FromMilliseconds(p_dblDurationInMilliSeconds);
m_timer.Tick += timer_Tick;
m_timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
if (m_timer != null)
{
m_timer.Stop();
m_timer.Tick -= timer_Tick;
}
Close();
}
Usage:
// Display the ToolTip Window to the right of the Cursor
int intX = Cursor.Position.X + 20;
int intY = Cursor.Position.Y;
ToolTipWindow wpfWindow = new ToolTipWindow("Text To Display", intX, intY, 800);
wpfWindow.Show();
Result:
I didn't implement the Mouse leave event, since I've used short display duration.

Related

C# Lock Cursor inside of Window like Blender does it [duplicate]

Can someone give me a sample code to confine the cursor on to a Form. I found this (ClipCursor API, that says it can be done using it). I have a C# Windows form application and using VS 2008.
My code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_CursorChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
MoveCursor ();
}
private void Form1_Resize(object sender, EventArgs e)
{
MoveCursor();
}
private void Form1_LocationChanged(object sender, EventArgs e)
{
MoveCursor();
}
private void MoveCursor()
{
Cursor.Clip = Bounds;
this.Capture = true;
}
}
}
Form1.Designer.cs
namespace WindowsFormsApplication1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.AutoCompleteCustomSource.AddRange(new string[] {
"all",
"allah",
"allo"});
this.textBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.textBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
this.textBox1.Location = new System.Drawing.Point(30, 70);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(227, 20);
this.textBox1.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 264);
this.Controls.Add(this.textBox1);
this.Cursor = System.Windows.Forms.Cursors.No;
this.Name = "Form1";
this.Text = "Form1";
this.CursorChanged += new System.EventHandler(this.Form1_CursorChanged);
this.Load += new System.EventHandler(this.Form1_Load);
this.Resize += new System.EventHandler(this.Form1_Resize);
this.LocationChanged += new System.EventHandler(this.Form1_LocationChanged);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox textBox1;
}
}
There's an option that doesn't require you to p/invoke: Cursor.Clip
Edit: new code. Complete form code in single file.
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Activate(object sender, EventArgs e) {
MoveCursor ();
}
private void Form1_Resize(object sender, EventArgs e) {
MoveCursor();
}
private void Form1_LocationChanged(object sender, EventArgs e) {
MoveCursor();
}
private void MoveCursor()
{
this.Capture = true;
System.Windows.Forms.Cursor.Clip = Bounds;
}
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
this.textBox1.AutoCompleteCustomSource.AddRange(new string[] {"all", "allak", "allo"});
this.textBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.textBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
this.textBox1.Location = new System.Drawing.Point(30, 70);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(227, 20);
this.textBox1.TabIndex = 0;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 264);
this.Controls.Add(this.textBox1);
this.Cursor = System.Windows.Forms.Cursors.No;
this.Name = "Form1";
this.Text = "Form1";
this.Activated += new System.EventHandler(this.Form1_Activate);
this.Resize += new System.EventHandler(this.Form1_Resize);
this.LocationChanged += new System.EventHandler(this.Form1_LocationChanged);
this.ResumeLayout(false);
this.PerformLayout();
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.TextBox textBox1 = null;
}
}
Unless this is a particularly locked-down computer like a kiosk, users will probably hate it. Think about if they are needing to alt+tab to a different app to copy something to the clipboard to fill out your form... Just be careful.

Windows forms button parameters

Background Info:
For school, I need to make a crossword puzzle project in Windows Forms using OOP and the project needs to have a list build in it.
Problem:
For the functions in Form1.cs, I need to pass parameters (Object sender, Eventargs e) coming from the classes for the Form. The Project is OOP based.
Question:
error: There is no argument given that corresponds to the required formal parameter 'sender'
The errors are coming from:
menuOptions.aboutToolStripMenuItem_Click();
menuOptions.openPuzzleToolStripMenuItem_Click();
menuOptions.exitToolStripMenuItem_Click();
boardCells.Board_CellPainting();
boardCells.Board_CellValueChanged();
boardCells.formatCell();
My question is what do I need to do to solve the error?
Form1.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.IO;
namespace CrossWordPuzzle
{
public partial class Form1 : Form
{
//Object instances from classes
Clues clue_window = new Clues();
Cell boardCells = new Cell();
Menu menuOptions = new Menu();
Board board = new Board();
public Form1()
{
InitializeComponent();
//Board functions
board.buildWordList();
board.InitializeBoard();
//Menu functions
menuOptions.aboutToolStripMenuItem_Click();
menuOptions.openPuzzleToolStripMenuItem_Click();
menuOptions.exitToolStripMenuItem_Click();
menuOptions.InitializeComponent();
//Cell functions
boardCells.Board_CellPainting();
boardCells.Board_CellValueChanged();
boardCells.formatCell();
boardCells.InitializeComponent();
}
//Function loads form with window properties
public void Form1_Load(object sender, EventArgs e)
{
board.InitializeBoard();
clue_window.SetDesktopLocation(this.Location.X + this.Width + 1, this.Location.Y);
clue_window.StartPosition = FormStartPosition.Manual;
clue_window.Show();
clue_window.clueTable.AutoResizeColumns();
}
//Function location form window
public void Form1_LocationChanged(object sender, EventArgs e)
{
clue_window.SetDesktopLocation(this.Location.X + this.Width + 1, this.Location.Y);
}
}
}
(menuOptions) Menu Class
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace CrossWordPuzzle
{
class Menu : Form
{
//Object instances from classes
public DataGridView datagridview = new DataGridView();
public Form1 form = new Form1();
public string puzzle_file = Application.StartupPath + "\\Puzzles\\Puzzle1.pzl";
Clues clue_window = new Clues();
public List<id_cells> idc = new List<id_cells>();
Board board = new Board();
//Opens puzzle selector
public void openPuzzleToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Puzzle Files|*.pzl";
if (ofd.ShowDialog().Equals(DialogResult.OK))
{
puzzle_file = ofd.FileName;
datagridview.Rows.Clear();
clue_window.clueTable.Rows.Clear();
idc.Clear();
board.buildWordList();
board.InitializeBoard();
}
}
//Exit application function
public void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
//About menu function
public void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("CrossWordPuzzle made in C# Windows Forms", "CrossWordPuzzle");
return;
}
//Initialize Menu component
public void InitializeComponent()
{
this.SuspendLayout();
//
// Menu
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "Menu";
this.Load += new System.EventHandler(this.Menu_Load);
this.ResumeLayout(false);
}
//Load Menu
private void Menu_Load(object sender, EventArgs e)
{
}
}
}
(boardCells) Cell class
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace CrossWordPuzzle
{
class Cell : Form
{
//Object instances from classes
public DataGridView datagridview = new DataGridView();
public List<id_cells> idc = new List<id_cells>();
public Form1 form = new Form1();
//Cell painting
public void Board_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
//Every time a cell gets drawn on the board, it comes with a rectangle that has the number of the word.
String number = "";
if (idc.Any(c => (number = c.number) != "" && c.X == e.ColumnIndex && c.Y == e.RowIndex))
{
Rectangle r = new Rectangle(e.CellBounds.X, e.CellBounds.Y, e.CellBounds.Width, e.CellBounds.Height);
e.Graphics.FillRectangle(Brushes.White, r);
Font f = new Font(e.CellStyle.Font.FontFamily, 7);
e.Graphics.DrawString(number, f, Brushes.Black, r);
e.PaintContent(e.ClipBounds);
e.Handled = true;
}
}
//Function for BoardCell design
public void Board_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
//make letter uppercase
try
{
form.Board[e.ColumnIndex, e.RowIndex].Value = form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().ToUpper();
}
catch (Exception)
{
}
//Only 1 letter per cell
try
{
if (form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().Length > 1)
{
form.Board[e.ColumnIndex, e.RowIndex].Value = form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().Substring(0, 1);
}
}
catch (Exception)
{
}
//Change color if correct
try
{
if (form.Board[e.ColumnIndex, e.RowIndex].Value.ToString().ToUpper().Equals(form.Board[e.ColumnIndex, e.RowIndex].Tag.ToString().ToUpper()))
{
form.Board[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.DarkGreen;
}
else
{
form.Board[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.Red;
}
}
catch (Exception)
{
}
}
//Function for formatting Cell design on Board
public void formatCell(int row, int col, String letter)
{
DataGridViewCell c = form.Board[col, row];
c.Style.BackColor = Color.White;
c.ReadOnly = false;
c.Style.SelectionBackColor = Color.Cyan;
c.Tag = letter;
}
//Initialize Cell component
public void InitializeComponent()
{
this.SuspendLayout();
//
// Cell
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "Cell";
this.Load += new System.EventHandler(this.Cell_Load);
this.ResumeLayout(false);
}
//Load Cell
private void Cell_Load(object sender, EventArgs e)
{
}
}
//Class for Cell id's
public class id_cells
{
public int X;
public int Y;
public String direction;
public String number;
public String word;
public String clue;
public id_cells(int x, int y, String d, String n, String w, String c)
{
this.X = x;
this.Y = y;
this.direction = d;
this.number = n;
this.word = w;
this.clue = c;
}
} //end of class
}
You are trying to call menuOptions.aboutToolStripMenuItem_Click(); but the function requires 2 parameters (object sender, EventArgs e);
You need to supply those parameters.
This is done automatically by the framework when you wire up events:
this.Load += new System.EventHandler(this.Cell_Load);
private void Cell_Load(object sender, EventArgs e)
{
}
When the Load event is triggered by the framework when a form is loaded, it will automatically pass in the sender and event args.
If you are trying to call those functions manually (i.e. in YOUR code), then you must supply those parameters.
You can fake it by using:
CellLoad(this, EventArgs.Empty);
What is confusing is why you have decided to call these functions during initialisation.
menuOptions.aboutToolStripMenuItem_Click();
menuOptions.openPuzzleToolStripMenuItem_Click();
menuOptions.exitToolStripMenuItem_Click();
Why do you want to press the exit button during startup?

Passing a Boolean from one window to another

I'm having two issues which I'm pretty sure are separate in WPF. First off boolean xs isn't getting passed into the Main Window which I've checked by testing where it is true and where it isn't. Also Cross 1 and Cross 2 do not draw if I add them to the Stack Panel in a button click event. Sorry about it being two pretty basic questions but I can't find anything that works. Also I tried to spare you guys as much reading as possible so if you need anything else to make it work for whatever reason don't hesitate to ask for it.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
Rectangle Rectangle = new Rectangle();
Rectangle.MouseLeftButtonDown += Rectangle8_MouseLeftButtonDown;
Rectangle Cross1 = new Rectangle();
Rectangle Cross2 = new Rectangle();
myStackPanel.Children.Add(Rectangle8);
bool xs = Menu.Xs;
bool os = Menu.Os;
bool RectangleClicked = false;
void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
RectangleClicked = true;
}
void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
RectangleClicked = true;
}
if (RectangleClicked == true)
{
myStackPanel.Children.Add(Cross2);
myStackPanel.Children.Add(Cross1);
}
if (xs == true)
{
MessageBox.Show("Xs is true");
}
}
}
Window Two Code
public partial class Menu : Window
{
public Menu()
{
InitializeComponent();
}
public static bool Xs { get; private set; }
public static bool Os { get; private set; }
public void Button_Click(object sender, RoutedEventArgs e)
{
Xs = true;
Os = false;
this.Close();
}
public void Button_Click_1(object sender, RoutedEventArgs e)
{
Xs = false;
Os = true;
MessageBox.Show("Xs is false");
this.Close();
}
}
}
The first issue with the Menu not returning the values:
You need an event to signal to main window that menu has closed and should retrieve the new values from menu.
In Menu, we add a delegate and event to signal that data has changed and the menu is closing:
public partial class Menu : Window
{
public delegate void DataChangeHandler(object sender, EventArgs e);
// an instance of the delegate
public DataChangeHandler DataChanged;
public Menu()
{
InitializeComponent();
}
public static bool Xs { get; private set; }
public static bool Os { get; private set; }
public void Button_Click(object sender, RoutedEventArgs e)
{
Xs = true;
Os = false;
DataChanged?.Invoke(this, new EventArgs());
this.Close();
}
public void Button_Click_1(object sender, RoutedEventArgs e)
{
Xs = false;
Os = true;
MessageBox.Show("Xs is false");
DataChanged?.Invoke(this, new EventArgs());//when menu closes announce change event if a handler is wired up to listen.
this.Close();
}
}
In MainWindow, we have two properties for x and o's being set from menu. These are outside the constructor.
public partial class MainWindow : Window
{
bool xs;
bool os;
public MainWindow()
{
//snip
Button Start = new Button();
Start.Height = 50;
Start.Width = 200;
Start.Margin = new Thickness(500, -100, 0, 0);
Start.Content = "Start";
myStackPanel.Children.Add(Start);
Start.Click += Start_Click;
xs = Menu.Xs;
os = Menu.Os;
}
private void Start_Click(object sender, RoutedEventArgs e)
{
Menu win2 = new Menu();
win2.DataChanged += MenuClosed; //handler
win2.Show();
}
public void MenuClosed(object sender, EventArgs e) //fires after closing menu
{
xs = Menu.Xs; //get new values from Menu for x and o
os = Menu.Os;
}
The second issue:Cross 1 and Cross 2 do not draw if I add them to the Stack Panel.
You need create new crosses and add them to the desired rectangle. First remove the handler to the rectangle clicked outside the constructor in Mainwindow.
void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
RectangleClicked = true;
HandleMove(); //draw a new cross either X or O to 'this' square
}
For each rectangle you add, add a handler to draw the right cross inside the clicked rectangle. The cross drawing handler would then check if x's or o's are set and draw the right cross and add the cross to the rectangle.

Changing the color of the elements of a UserControl

i have a problem whit an userControl.
When I try to hover it to change the color of all the components , the function "ChangeColor" isn't fire correctly.
If I hover on the label or picturebox of the usercontrol, it is evoked the event mouseLeave
This is my userControl
public partial class infoUser : UserControl
{
public infoUser()
{
InitializeComponent();
}
public void SetNome(string nome)
{
labelUserLogged.Text = nome;
}
public void ChangeColor(System.Drawing.Color color)
{
labelUserLogged.BackColor = color;
pictureBoxUser.BackColor = color;
}
private void infoUser_MouseHover(object sender, EventArgs e)
{
ChangeColor(Color.CadetBlue);
}
private void infoUser_MouseLeave(object sender, EventArgs e)
{
ChangeColor(Color.WhiteSmoke);
}
}
Code of designer
private void InitializeComponent()
{
this.labelUserLogged = new System.Windows.Forms.Label();
this.pictureBoxUser = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxUser)).BeginInit();
this.SuspendLayout();
//
// labelUserLogged
//
this.labelUserLogged.BackColor = System.Drawing.SystemColors.Control;
this.labelUserLogged.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.labelUserLogged.Cursor = System.Windows.Forms.Cursors.Hand;
this.labelUserLogged.Location = new System.Drawing.Point(0, 0);
this.labelUserLogged.Name = "labelUserLogged";
this.labelUserLogged.Size = new System.Drawing.Size(167, 27);
this.labelUserLogged.TabIndex = 3;
this.labelUserLogged.Text = "Non loggato";
this.labelUserLogged.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// pictureBoxUser
//
this.pictureBoxUser.BackColor = System.Drawing.Color.Transparent;
this.pictureBoxUser.Cursor = System.Windows.Forms.Cursors.Hand;
this.pictureBoxUser.Image = global::Castor.Gestionale.Properties.Resources.user_icon;
this.pictureBoxUser.Location = new System.Drawing.Point(5, 6);
this.pictureBoxUser.Name = "pictureBoxUser";
this.pictureBoxUser.Size = new System.Drawing.Size(18, 15);
this.pictureBoxUser.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBoxUser.TabIndex = 4;
this.pictureBoxUser.TabStop = false;
//
// infoUser
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.pictureBoxUser);
this.Controls.Add(this.labelUserLogged);
this.Name = "infoUser";
this.Size = new System.Drawing.Size(171, 30);
this.MouseLeave += new System.EventHandler(this.infoUser_MouseLeave);
this.MouseHover += new System.EventHandler(this.infoUser_MouseHover);
((System.ComponentModel.ISupportInitialize)(this.pictureBoxUser)).EndInit();
this.ResumeLayout(false);
}
Child controls of your UserControl are receive the mouse-input when cursor is within it's bounds. So, when your mouse "enter" into the label/picturebox it "leave" the UserControl and etc.
To make the specific child control "transparent" for mouse events you can use the following trick:
const int WM_NCHITTEST = 0x84, HTTRANSPARENT = (-1);
class HitTestTransparentPictureBox : PictureBox {
protected override void WndProc(ref Message m) {
if(m.Msg == WM_NCHITTEST) {
m.Result = new IntPtr(HTTRANSPARENT);
return;
}
base.WndProc(ref m);
}
}
class HitTestTransparentLabel : Label {
protected override void WndProc(ref Message m) {
if(m.Msg == WM_NCHITTEST) {
m.Result = new IntPtr(HTTRANSPARENT);
return;
}
base.WndProc(ref m);
}
}
Then you can replace the specific controls in your UserControl with their "mouse-transparent" analogs:
this.labelUserLogged = new HitTestTransparentLabel();
this.pictureBoxUser = new HitTestTransparentPictureBox();
After that you can use the following approach to create hover-effect on UserControl:
public infoUser() {
InitializeComponent();
MouseEnter += infoUser_MouseEnter;
MouseLeave += infoUser_MouseLeave;
}
void infoUser_MouseLeave(object sender, EventArgs e) {
Hover = false;
}
void infoUser_MouseEnter(object sender, EventArgs e) {
Hover = true;
}
bool hoverCore;
protected bool Hover {
get { return hoverCore; }
set {
if(hoverCore == value) return;
hoverCore = value;
OnHoverChanged();
}
}
void OnHoverChanged() {
ChangeColor(Hover ? Color.CadetBlue : Color.WhiteSmoke);
}

How to make a checkbox button flash?

I have a checkbox shown as button. I want to make it flash when it is checked. From what Ive found, i think the simplest way is to use a timer to rotate the background color of the button.
Where I am stuck is finding the back color of the checked button. Can someone tell me what the back color is changed to by default (via designer) when the button is checked? Without that I cannot get the timer to begin the oscillation.
What I have is a Mute Button. When the mute is active i want the button to flash until it is pressed again to turn the mute off.
In case I'm wrong and the back color actually does not change, what changes about the button to make it appear pressed?
code:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
instructorTimer.Enabled = true;
}
private void instructorTimer_Tick(object sender, EventArgs e)
{
// interval is 2000
if (checkBox1.BackColor == System.Drawing.SystemColors.Control)
checkBox1.BackColor = System.Drawing.SystemColors.ControlDark;
else
checkBox1.BackColor = System.Drawing.SystemColors.Control;
}
Maybe SystemColors.Control is what you are looking for.
Make sure you have the tick event hooked up. It looks suspect:
private void Form1_Load(object sender, EventArgs e) {
timer1.Tick += instructorTimer_Tick;
}
I would also change the color immediately, for instant feedback:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkBox1.BackColor = SystemColors.ControlDark;
timer1.Enabled = true;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkBox1.BackColor = Color.Green;
Application.DoEvents();
TimeSpan ts = new TimeSpan();
do
{
}
while (ts.Milliseconds == 2000);
checkBox1.BackColor = SystemColors.Control;
}
If you're willing to use a UserControl instead of trying to repurpose Button - the following should work great and you can extend it if something doesn't work like you like:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace FlashyButton
{
public partial class FlashyButton : UserControl
{
private CheckState _Checked = CheckState.Unchecked;
[Browsable(true)]
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
lblText.Text = value;
Invalidate();
}
}
public FlashyButton()
{
this.CausesValidation = true;
InitializeComponent();
lblText.MouseClick += (sender, e) => { OnMouseClick(null); };
}
public void SetFont(Font WhichFont)
{
this.Font = WhichFont;
}
public CheckState GetCheckedState()
{
return this._Checked;
}
public void SetCheckedState(CheckState NewCheckState)
{
this._Checked = NewCheckState;
}
protected override void OnMouseClick(MouseEventArgs e)
{
this._Checked = (this._Checked == CheckState.Checked) ? CheckState.Unchecked : CheckState.Checked;
this.BorderStyle = (this._Checked == CheckState.Checked) ? System.Windows.Forms.BorderStyle.Fixed3D : System.Windows.Forms.BorderStyle.FixedSingle;
tmrRedraw.Enabled = (this._Checked == CheckState.Checked);
if (this._Checked == CheckState.Unchecked)
{
this.BackColor = SystemColors.Control;
}
this.Invalidate(); //Force redraw
base.OnMouseClick(e);
}
private float Percent = 100;
private void tmrRedraw_Tick(object sender, EventArgs e)
{
Percent -= 2;
if (Percent < -100) Percent = 100;
this.BackColor = Color.FromArgb(
255,
Lerp(255, SystemColors.Control.R, (int)Math.Abs(Percent)),
Lerp(0, SystemColors.Control.G, (int)Math.Abs(Percent)),
Lerp(0, SystemColors.Control.B, (int)Math.Abs(Percent))
);
}
private int Lerp(int Start, int End, int Percent)
{
return ((int) ((float)(End - Start) * ((float)Percent / 100f)) + Start);
}
}
}
And here is the .Designer code as well (just replace what you already have when you make a new control by this name)
namespace FlashyButton
{
partial class FlashyButton
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.lblText = new System.Windows.Forms.Label();
this.tmrRedraw = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// lblText
//
this.lblText.AutoSize = true;
this.lblText.Location = new System.Drawing.Point(4, 4);
this.lblText.Name = "lblText";
this.lblText.Size = new System.Drawing.Size(55, 17);
this.lblText.TabIndex = 0;
this.lblText.Text = "Sample";
//
// tmrRedraw
//
this.tmrRedraw.Interval = 10;
this.tmrRedraw.Tick += new System.EventHandler(this.tmrRedraw_Tick);
//
// FlashyButton
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.lblText);
this.Name = "FlashyButton";
this.Size = new System.Drawing.Size(148, 148);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblText;
private System.Windows.Forms.Timer tmrRedraw;
}
}
This worked for me when I had a CheckBox with Appearance = Button and FlatStyle = Flat and wanted it flashing when checked:
private void timer_Flashing_Tick(object sender, EventArgs e)
{
if (checkBox_Refresh.Checked)
{
if (checkBox_Refresh.FlatAppearance.CheckedBackColor == Color.Red)
{
checkBox_Refresh.FlatAppearance.CheckedBackColor = Color.Transparent;
}
else
{
checkBox_Refresh.FlatAppearance.CheckedBackColor = Color.Red;
}
}
}

Categories