How to prevent contexmenustrip closing? - c#

I have a listbox with unnumbered items and a contexmenustrip. I wrote this code ( I know it seems too primitive, because of my inexpertness) It works fine but I have a little problem.
I want to make cms open at near your mouse position when you click on an item in listbox. and It will be opened at previous position when you click on blank. It is ok but cms is reopening by your each click. Is it posible to make it stay open when you click on blank not an item?
public Form1()
{
InitializeComponent();
}
int a, b, tx, ty;
int mx=0;
private void listBox1_MouseClick(object sender, MouseEventArgs e)
{
b = a;
a = listBox1.SelectedIndex;
if (listBox1.SelectedIndex != -1)
{
if (a!= b)
{
contextMenuStrip1.Show(MousePosition.X + 10, MousePosition.Y);
tx = MousePosition.X;
ty = MousePosition.Y;
mx =1;
}
else if (a==0 && b==0 && mx== 0)
{
tx = MousePosition.X;
ty = MousePosition.Y;
contextMenuStrip1.Show(tx + 10, ty);
mx = 1;
}
else
{
contextMenuStrip1.Show(tx + 10, ty);
}
}
}

Use AutoClose property of ContextMenuStrip to prevent it automatically closing.
ContextMenuStrip cms = new ContextMenuStrip();
cms.AutoClose = false;
Then call Close method to manually close it
cms.Close();
Or handle the Closing event of contextmenustrip and set e.Cancel = true based on your condition
void cms_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if(your condition)
{
e.Cancel = true;
}
}

Related

How to check if mouse is in ContextMenuStrip or in its items

I´m using ContextMenuStrip in my Form app as my drop down menu. Exactly, when I click on button, ContextMenuStrip shows right under it. Everithing is OK, but I really want to auto-close ContextMenuStrip after mouse leave its area. Ok, so I´m try to use MouseLeave event. Once again, everything is OK, but when I add dropdown items to some ToolStripItem in ContextMenuStrip, the mouseLeave event donť recognize this new area as a part of ContextMenuStrip. This is my newest attempt, but it is not finished. Any idea, how to resolve this problem?
private void ContextMenuStrip_MouseLeave(object sender, EventArgs e)
{
ContextMenuStrip cms = (sender is ContextMenuStrip) ? sender as ContextMenuStrip : null;
if (cms != null)
{
//List<Rectangle> cmsFullArea = new List<Rectangle>();
//cmsFullArea.Add(new Rectangle(cms.Bounds.Location, cms.Bounds.Size));
bool itemIsPressed = false;
for (int i = 0; i < cms.Items.Count; i++)
{
if (cms.Items[i].Pressed) { itemIsPressed = true; break; }
}
if (!itemIsPressed) { cms.Close(); }
}
}
This works fine, when I leave CMS to dropDown items, but it is not working, when I leave them too after. I need to close whole CMS, when I leave any of his areas.
Add a region variable which will be ContextMenuStrip plus the DropDownMenus.
private Region rgn = new Region();
Initialize region:
public Form1() {
InitializeComponent();
rgn.MakeEmpty();
}
When ContextMenuStrip opens update region:
private void contextMenuStrip1_Opened( object sender, EventArgs e ) {
rgn.Union( contextMenuStrip1.Bounds );
}
In leave event check if mouse is inside this region:
private void contextMenuStrip1_MouseLeave( object sender, EventArgs e ) {
Point pnt = Cursor.Position;
if( rgn.IsVisible( pnt ) == false ) {
rgn.MakeEmpty();
contextMenuStrip1.Close();
}
}
When you create a new ToolStripDropDownMenu adding items to eg toolStripMenuItem0, add these event handlers:
//toolStripMenuItem0 is an item of your ContextMenuStrip
toolStripMenuItem0.DropDown.MouseLeave += DropDown_MouseLeave;
toolStripMenuItem0.DropDown.Opened += DropDown_Opened;
toolStripMenuItem0.DropDown.Closed += DropDown_Closed;
private void DropDown_Closed( object sender, ToolStripDropDownClosedEventArgs e ) {
ToolStripDropDownMenu tsddm = (ToolStripDropDownMenu)sender;
rgn.Exclude( tsddm.Bounds ); //remove rect from region
}
private void DropDown_Opened( object sender, EventArgs e ) {
ToolStripDropDownMenu tsddm = (ToolStripDropDownMenu)sender;
rgn.Union( tsddm.Bounds ); //add rect to region
}
private void DropDown_MouseLeave( object sender, EventArgs e ) {
Point pnt = Cursor.Position;
if( rgn.IsVisible( pnt ) == false ) {
rgn.MakeEmpty();
contextMenuStrip1.Close();
}
}
Do the same for every DropDownMenu you create.
As I promise in comments, I want to post another solution for this problem.
Firstly there is MouseLeave method for event handle. This method is common to ContextMenuStrip (CMS) and ToolStripDropDownMenu (TSDDM).
private void ContextMenuStrip_MouseLeave(object sender, EventArgs e)
{
ContextMenuStrip cms = (sender is ContextMenuStrip) ? sender as ContextMenuStrip : null;
//Recognize CMS or TSDDM, in this case we dont need anything else
if (cms != null)
{
//Check, if mouse position is on any of CMS DropDownMenus.
//If false, close CMS. If true, we dont want to close it - CMS is actively in use
if (!IsMouseOnDropDown(cms.Items)) { cms.Close(); }
}
else
{
ToolStripDropDownMenu ddm = (sender is ToolStripDropDownMenu) ? sender as ToolStripDropDownMenu : null;
if (ddm != null)
{
//As above, check mouse position against items DropDownMenus
if (IsMouseOnDropDown(ddm.Items)) { return; }
//Declare our CMS
cms = GetPrimaryOwner(ddm);
//Get TSDDM owner
//var is important here, because we dont know if it is CMS or another TSDDM!!!
//Also TSDDM and CMS have the same properties for our purpose, so var is OK
var owner = ddm.OwnerItem.Owner;
Point pnt = Cursor.Position;
//If owner doesn't contains mouse position, close whole CMS
if (!owner.Bounds.Contains(pnt))
{
cms.Close();
}
else
{
//If does, we need to check if mouse position is exactly on parent item,
//because its prevent to TSDDM unnecessary close/open
//(explanation: Mouse leave TSDDM -> TSDDM close;
//Mouse is on parent item -> TSDDM open)
for (int i = 0; i < owner.Items.Count; i++)
{
//Define own rectangle, because item has its own bounds against the owner
//so we need to add up their X and Y to get the real one
int x = owner.Bounds.X + (owner.Items[i] as ToolStripMenuItem).Bounds.X;
int y = owner.Bounds.Y + (owner.Items[i] as ToolStripMenuItem).Bounds.Y;
Rectangle rect = new Rectangle(new Point(x, y), (pupik.Items[i] as ToolStripMenuItem).Bounds.Size);
//If its our DropDownMenu and mouse position is in there,
//we dont want to close ddm
if ((owner.Items[i] as ToolStripMenuItem).DropDown == ddm
&& rect.Contains(pnt))
{
return;
}
}
ddm.Close();
}
}
}
}
Above you can see IsMouseOnDropDown and GetPrimaryOwner methods, so there is the code:
private static bool IsMouseOnDropDown(ToolStripItemCollection itemCollection)
{
Point pnt = Cursor.Position;
//All what we do is check, if some of DropDownMenus from input collection is active (Visible)
//and if mouse position is in it
for (int i = 0; i < itemCollection.Count; i++)
{
if ((itemCollection[i] as ToolStripMenuItem).DropDown.Visible
&& (itemCollection[i] as ToolStripMenuItem).DropDown.Bounds.Contains(pnt))
{
return true;
}
}
return false;
}
private static ContextMenuStrip GetPrimaryOwner(ToolStripDropDownMenu dropDownMenu)
{
//All what we do is take owner by owner until we find our CMS,
//which is the last one -> primary owner
object cmsItems = dropDownMenu;
while (!(cmsItems is ContextMenuStrip))
{
cmsItems = (cmsItems as ToolStripDropDownMenu).OwnerItem.Owner;
}
return cmsItems as ContextMenuStrip;
}
The last thing what we need to do, is handle the mouseLeave event for every DropDownMenu an ContextmenuStrip
this.ContextMenuStrip1.MouseLeave += new System.EventHandler(ContextMenuStrip_MouseLeave);
this.StripMenuItem1.DropDown.MouseLeave += new System.EventHandler(ContextMenuStrip_MouseLeave);
With this example everything works fine to me, so if you find an error, please let me know.
It is just an example, so I dont write Try/Catch there..

Two Reordering ListBoxes on Same page, prevent user from dragging and dropping between

I have a WPF c# application that has a window with two Reordering Listboxes right next to each other. I used the examples in this link to make the listbox user control. Unfortunately this allows the user to drag from one box and drop in the other. How can I make sure that this doesn't happen?
Here is my code:
public void setItems(List<string> values){
_items = new ObservableCollection<Item>();
foreach (string s in values)
{
_items.Add(new Item(s));
}
listBox.DisplayMemberPath = "Name";
listBox.ItemsSource = _items;
listBox.PreviewMouseMove += ListBox_PreviewMouseMove;
var style = new Style(typeof(ListBoxItem));
style.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true));
style.Setters.Add(
new EventSetter(
ListBoxItem.PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(ListBoxItem_PreviewMouseLeftButtonDown)));
style.Setters.Add(
new EventSetter(
ListBoxItem.DropEvent,
new DragEventHandler(ListBoxItem_Drop)));
listBox.ItemContainerStyle = style;
}
private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point point = e.GetPosition(null);
Vector diff = _dragStartPoint - point;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
var lb = sender as ListBox;
var lbi = FindVisualParent<ListBoxItem>(((DependencyObject)e.OriginalSource));
if (lbi != null)
{
DragDrop.DoDragDrop(lbi, lbi.DataContext, DragDropEffects.Move);
}
}
}
private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_dragStartPoint = e.GetPosition(null);
}
private void ListBoxItem_Drop(object sender, DragEventArgs e)
{
if (sender is ListBoxItem)
{
var source = e.Data.GetData(typeof(Item)) as Item;
var target = ((ListBoxItem)(sender)).DataContext as Item;
int sourceIndex = listBox.Items.IndexOf(source);
int targetIndex = listBox.Items.IndexOf(target);
Debug.WriteLine("Target: " + targetIndex.ToString());
Move(source, sourceIndex, targetIndex);
}
}
private void Move(Item source, int sourceIndex, int targetIndex)
{
if (sourceIndex < targetIndex)
{
_items.Insert(targetIndex + 1, source);
_items.RemoveAt(sourceIndex);
}
else
{
int removeIndex = sourceIndex + 1;
if (_items.Count + 1 > removeIndex)
{
_items.Insert(targetIndex, source);
_items.RemoveAt(removeIndex);
}
}
}
}
I figured it out in case anyone else has a similar issue...
I changed the Move function to the following:
private void Move(Item source, int sourceIndex, int targetIndex)
{
IList<Item> prevItems = _items;
try
{
_items.RemoveAt(sourceIndex);
_items.Insert(targetIndex, source);
}
catch(ArgumentOutOfRangeException)
{
//User doesn't need to be notified about this. It just means that they dragged out of the box they were ordering.
//The application does not need to be stopped when this happens.
_items = prevItems;
Debug.WriteLine("User tried to drag between boxes.. Order of boxes were not changed. ");
}
}
I realized that if I remove the item first then I won't have to worry about changing the target or remove index based on the position of the sourceIndex in relation to the targetIndex. Instead I can wrap it in a try catch and look for an ArgumentOutOfRangeException, which will happen if the user tries to drag and drop between. If that happens I reset the box to the previous items.
As far as I can tell this solution works fine... There may have been a simpler way to go about this.

c# Change the status of a button after closing a form?

this is my problem: I have a main form where I have a panel that contains some buttons, when the user clicks a button a form is opened.( I have some buttons and clicking these buttons the user can open different forms )If the user click again the same button he can close the form.
this is what I do:
in the main form I have a method that is invoked when one of these buttons is clicked by the user, the method checks the text associated to the button in order to decide which is the button clicked. Once I have discovered which is the button that has been clicked it launches the form associated with the button.
this is the code
private void tlStBtn_Click(object sender, EventArgs e)
{
//// loop through all items in the ToolStrip
//foreach (Object item in toolStripMain.Items)
//{
// // if this item is a ToolStripButton object, check it
// if (item is ToolStripButton)
// {
// // cast the item to a ToolStripButton object and check it if the sender of the event is the currently looked at button in the loop
// ToolStripButton button = (ToolStripButton)item;
// button.Checked = (button == sender);
// }
//}
foreach (ToolStripItem item in this.VerticalToolBox.Items)
{
if ((item != sender) &&
(item is ToolStripButton))
{
((ToolStripButton)item).Checked = false;
}
}
if (sender_old != sender)
{
sender_old = sender;
if ((sender as ToolStripButton).Text == "Protection")
{
if (!Application.OpenForms.OfType<frm_Protection>().Any())
{
frm_Protection Newf = new frm_Protection(ref CurrentProject);
Newf.Show();
}
}
else
{
if (Application.OpenForms.OfType<frm_Protection>().Any())
{
Application.OpenForms.OfType<frm_Protection>().First().Close();
Properties.Settings.Default.Save();
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
if ((sender as ToolStripButton).Text == "Info")
{
if (!Application.OpenForms.OfType<Frm_ObjectInfo>().Any())
{
Frm_ObjectInfo Newform = new Frm_ObjectInfo();
Newform.Show();
}
}
else
{
if (Application.OpenForms.OfType<Frm_ObjectInfo>().Any())
{
Application.OpenForms.OfType<Frm_ObjectInfo>().First().Close();
Properties.Settings.Default.Save();
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
if ((sender as ToolStripButton).Text == "Layers")
{
if (!Application.OpenForms.OfType<Frm_LayersManage>().Any())
{
Frm_LayersManage Newform = new Frm_LayersManage();
Newform.Show();
Application.OpenForms.OfType<Frm_LayersManage>().First().UpdateLayers(null, CurrentProject.layers);
}
}
else
{
if (Application.OpenForms.OfType<Frm_LayersManage>().Any())
{
Application.OpenForms.OfType<Frm_LayersManage>().First().Close();
Properties.Settings.Default.Save();
UpdateScreen = true;
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
if (Properties.Settings.Default.Grip2Enabled && (sender as ToolStripButton).Text == "Insert Grip")
{
gbx_SelectGrip.Visible = true;
}
else
{
gbx_SelectGrip.Visible = false;
}
//SelectedPoints.Clear();
//MousePointList.Clear();
//myIDs.Clear();
//IdxPointsEnt.Clear();
//RatiosLines.Clear();
//CadSource.cuts_tmp.Clear();
//IDAddedCutList.Clear();
//ZoomPort.SetValue(0, 0);
//ZoomPort.SetValue(0, 1);
//ZoomPort.SetValue(0, 2);
//ZoomPort.SetValue(0, 3);
//// Reset index of scrap selected by moving gripper
//idxScrap = -1;
//pnl_OpenTK.Refresh();
//// Se ho evidenziato uno SCRAP , annullo l'evidenziazione.
//if (IdsScrapDisablePath[0] != -1)
//{
// int identifiedScrap = CadSource.IdToIdx_Scrap(IdsScrapDisablePath[0]);
// if (CadSource.scraps[identifiedScrap].GripExists())
// {
// CadSource.scraps[identifiedScrap].Enabled = ScrapAbilitation.Enabled; // Disable clicked scrap
// }
// else
// {
// CadSource.scraps[identifiedScrap].Enabled = ScrapAbilitation.WithoutGrip; // Disable clicked scrap
// }
//}
//numScrap = 0;
//IdsScrapDisablePath = new List<int>() { -1, -1 };
}
else
{
(sender as ToolStripButton).Checked = false;
(sender as ToolStripButton).BackColor = Color.Transparent;
sender_old = new object() { };
if (Application.OpenForms.OfType<frm_Protection>().Any())
{
Application.OpenForms.OfType<frm_Protection>().First().Close();
Properties.Settings.Default.Save();
}
if (Application.OpenForms.OfType<Frm_ObjectInfo>().Any())
{
Application.OpenForms.OfType<Frm_ObjectInfo>().First().Close();
Properties.Settings.Default.Save();
}
if (Application.OpenForms.OfType<Frm_LayersManage>().Any())
{
Application.OpenForms.OfType<Frm_LayersManage>().First().Close();
Properties.Settings.Default.Save();
}
gbx_SelectGrip.Visible = false;
GC.Collect();
GC.WaitForPendingFinalizers();
}
SelectedPoints.Clear();
MousePointList.Clear();
myIDs.Clear();
IdxPointsEnt.Clear();
RatiosLines.Clear();
CurrentProject.cuts_tmp.Clear();
IDAddedCutList.Clear();
ZoomPort.SetValue(0, 0);
ZoomPort.SetValue(0, 1);
ZoomPort.SetValue(0, 2);
ZoomPort.SetValue(0, 3);
// Reset index of scrap selected by moving gripper
idxScrap = -1;
pnl_OpenTK.Refresh();
// Se ho evidenziato uno SCRAP , annullo l'evidenziazione.
if (IdsScrapDisablePath[0] != -1)
{
int identifiedScrap = CurrentProject.IdToIdx_Scrap(IdsScrapDisablePath[0]);
if (CurrentProject.scraps[identifiedScrap].GripExists())
{
CurrentProject.scraps[identifiedScrap].Enabled = ScrapAbilitation.Enabled; // Disable clicked scrap
}
else
{
CurrentProject.scraps[identifiedScrap].Enabled = ScrapAbilitation.WithoutGrip; // Disable clicked scrap
}
}
numScrap = 0;
IdsScrapDisablePath = new List<int>() { -1, -1 };
}
the forms that are opned clicking the buttons are forms where I have set the controlbox at false because I don't want that the user is able to close the forms without clicking again the button that has clicked to open it, but I have found a problem because if the user closes the form in this way (see the picture below) the status of the button remains checked but the form has been closed manually
To solve this problem I have thought to add this method associated to the event closing of my forms this is the code
private void frm_Protection_FormClosed(object sender, FormClosedEventArgs e)
{
////// if user closes manually the window without using the button I have to change the state of the button
Frm_Main f = new Frm_Main();
f = Application.OpenForms.OfType<Frm_Main>().Last();
f.tlsBut_Protection.Checked = false;
}
with this code if I close manually the form the status of the button it becomes false again in the main form
but I have discovered that It causes some problems to my program , one of this problem is that after closing the form if I click again the button it seems that the method associated to the clicking event is not called and the form is not opened I have to click it twice before it works again.
do you know why what do I do in the wrong way???
thanks for your help
To prevent a Form from closing, you can subscribe to the FormClosing event, which fires before the Form closes, and intercept (and cancel) the user's action.
private void frm_Protection_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
e.Cancel = true;
}
Unfortunately, clicking the "X" (in the Taskbar preview or in the program itself) and calling this.Close() are both treated as "UserClosing" close reasons, so we need to modify it slightly.
Add a property to frm_Protection, and use that to determine whether the Form can be closed:
public bool CanClose { private get; set; }
private void frm_Protection_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = !CanClose;
}
And then only set the property to true when you want to allow the Form to be closed:
var frmP = Application.OpenForms.OfType<frm_Protection>().FirstOrDefault();
if (frmP != null)
{
frmP.CanClose = true;
frmP.Close();
}

Prevent printing blank pages

I just need to reset "border" after print previewing. I preview the page I wantted to print correctly but when I do printing it gives blank pages because "border" wasnt reset. Where should I put "border=0"?("border" is no. rows in a datagridview)
private void button5_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
PrintPreviewDialog ppd = new PrintPreviewDialog();
ppd.Document = pd;
ppd.ShowDialog();
}
private void pd_PrintPage(object sender, PrintPageEventArgs e)
{
prntt(sender, e);
}
public void prntt(object sender, PrintPageEventArgs e)
{
for (; border < ViewA.RowCount; border++)
{
if (ustsin + yuk > e.MarginBounds.Bottom - 400f)
{
e.HasMorePages = true;
return;
}
texts = ViewA.Rows[border].Cells["Persons"].Value.ToString();
...
graphics.DrawString(texts, font, Brushes.Black, new RectangleF(e.MarginBounds.Left, ustsin, 115f, 90f));
...
float hoho = (float)e.Graphics.MeasureString(texts, font, 115, StringFormat.GenericTypographic).Height;
...
var mesele = new float[] { hoho, koko, moko };
float kapa = mesele.OrderByDescending(s => s).First();
ustsin += kapa + yuk;
}
e.HasMorePages = false;
}
if I can close when we press the print button in print preview, can I reset in its closing event?
edit: I did this, it seems to work but when I send it to xps, it shows 2 pages in the screen. like this http://i.imgur.com/a9KnkA0.png . How can I make this show 1 page?
private void printDocument1_EndPrint(object sender, PrintEventArgs e)
{
border = 0;
}
initially set it to 0 and reset it after ppd.ShowDialog();
ppd.ShowDialog();
border = 0;
UPDATE
Looks like PrintPreviewDialog doesn't support much as you (and many others expect), it's up to the user (not to programmer). You can try this a little hacky stuff:
//code in your button5_Click
ToolStripButton onePageButton = ((ToolStrip)ppd.Controls[1]).Items[3] as ToolStripButton;
BeginInvoke((Action)(() => onePageButton.PerformClick()));
ppd.ShowDialog();
UPDATE
To intercept the Clicking on the Print button, you have to add a little much more code. You have to detect the click before the Click is fired on the item (print button), show the message box asking for confirmation and re-click the item if user agrees. Here is the code for you:
//Use this class to add message interceptor into your ToolStrip message loop
public class NativeToolStrip : NativeWindow {
ToolStrip ts;
bool letClicked;
protected override void OnHandleChange() {
base.OnHandleChange();
Control c = Control.FromHandle(Handle);
ts = c as ToolStrip;
}
protected override void WndProc(ref Message m) {
if (m.Msg == 0x202&&!letClicked) {//WM_LBUTTONUP = 0x202
int x = m.LParam.ToInt32() & 0x00ff;
int y = m.LParam.ToInt32() >> 16;
ToolStripItem item = ts.GetItemAt(new Point(x, y));
//check if the first item (the Print Button) is clicked
if (item != null && ts.Items.IndexOf(item) == 0) {
if (MessageBox.Show("Do you want to print?", "Print confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
return;//discard message
else {
letClicked = true;
item.PerformClick();
}
}
}
base.WndProc(ref m);
if (letClicked) letClicked = false;
}
}
//This code should be done somewhere like in your form constructor
//BUT your PrintPreviewDialog should also be declared once in the form scope
//You can also place this in your button5_Click BUT it's not recommended
ToolStrip ts = (ToolStrip)ppd.Controls[1];
new NativeToolStrip().AssignHandle(ts.Handle);

Fading in and fading out for a form

i have a requirement in which my form is transparent,if my mouse enters into it the form
should became visible,if my mouse leaves out of the form it becomes transparent, i have three different controls placed in my form , each controls mouse leave and mouse enter is the same that of the form . if my mouse enters into the form and enters into a control
form_mouseleaveevent and control_mouseenterd gets fired so iam not able to achieve it,how to overcome this.
below is the piece of code for this:
private void TransToOpac()
{
if (!isTransparent)
return;
if (TtoOON == false )
{
TtoOON = true;
for (i = this.Opacity; i <= 1; i = i + 0.02)
{
this.Opacity = i;
Thread.Sleep(50);
}
isTransparent = false;
TtoOON = false;
}
}
private void OpacToTrans()
{
if (isTransparent)
return;
if (OtoTON == false )
{
OtoTON = true;
for (i = this.Opacity; i >= 0.5; i = i - 0.02)
{
this.Opacity = i;
Thread.Sleep(50);
}
isTransparent = true;
OtoTON = false;
}
}
private void OnMouseEntered(object sender, EventArgs e)
{
TransToOpac();
}
private void OnMouseLeft(object sender, EventArgs e)
{
OpacToTrans();
}
You can't get this done with MouseEnter/Leave events. The smaller problem is that the form's Leave event may never fire if a control is close to the edge. The bigger problem is that it will fire when the cursor moves into the non-client area (border, caption), you don't want to fade the form when the user tries to close or resize the window.
The crude but effective solution is to use a timer to check where the mouse is located:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Opacity = 0.99; // Avoid flicker
mFadeTimer.Interval = 15;
mFadeTimer.Tick += new EventHandler(mFadeTimer_Tick);
mMouseTimer.Interval = 200;
mMouseTimer.Tick += new EventHandler(mMouseTimer_Tick);
mMouseTimer.Enabled = true;
}
void mMouseTimer_Tick(object sender, EventArgs e) {
if (this.Bounds.Contains(Control.MousePosition)) {
if (mFade <= 0) { mFade = 1; mFadeTimer.Enabled = true; }
}
else {
if (mFade >= 0) { mFade = -1; mFadeTimer.Enabled = true; }
}
}
void mFadeTimer_Tick(object sender, EventArgs e) {
double opaq = this.Opacity + mFade * 0.05;
if (opaq >= 0.99) { opaq = 0.99; mFadeTimer.Enabled = false; }
if (opaq <= 0.15) { opaq = 0.15; mFadeTimer.Enabled = false; }
this.Opacity = opaq;
}
private Timer mFadeTimer = new Timer();
private Timer mMouseTimer = new Timer();
private int mFade = 0;
}
You could also check in Form_MouseLeave whether the mouse pointer is still within the form's bounds and in that case not fade out.
EDIT
There are several ways to find out whether the mouse is still within form's bounds. Easiest would be to use the Mouse.GetPosition method to find the current mouse position. The result is the location of the mouse pointer in screen coordinates. You can then check, whether the form's bounding rectangle contains the location.

Categories