C# LocationChanged event not firing - c#

I have a form that I use to overlay things that I don't want the user to mess with at a given time. When I use this overlay form to cover an entire form, everything works beautifully. However, when I use it to cover a panel, the LocationChanged event never fires! I tried changing the panel's properties to see if something was preventing it somehow. I tried using Dock = Fill, I have also tried matching the size of its parent control and using anchors... All to no avail.
Is there something I am missing that would prevent the LocationChanged event from firing?
Overlay form:
Panel PanelToCover = new Panel();
public Overlay(Panel paneltocover)
{
PanelToCover = paneltocover;
this.StartPosition = FormStartPosition.Manual;
this.AutoScaleMode = AutoScaleMode.None;
this.Location = paneltocover.PointToScreen(Point.Empty);
this.ClientSize = paneltocover.ClientSize;
paneltocover.LocationChanged += PanelCover_LocationChanged;
paneltocover.ClientSizeChanged += PanelCover_ClientSizeChanged;
this.Show(paneltocover);
paneltocover.Focus();
}
private void PanelCover_LocationChanged(object sender, EventArgs e)
{
this.Location = PanelToCover.PointToScreen(Point.Empty);
}
private void PanelCover_ClientSizeChanged(object sender, EventArgs e)
{
// This works without an issue
this.ClientSize = PanelToCover.ClientSize;
}
Edit:
I am silly. The panel's location will never change in respect to its owner. I was checking the PointToScreen value, watching it change, and wondering why the LocationChanged event never fired.

The location of the panel is relative to the form, so if you're moving the form the location_changed event won't be triggered on the panel. That's why the event is not triggered.

The panel's Location property represents the location of the panel on its containing control (the form). The panel is not moving with respect to the form, so LocationChanged never fires.

Related

Handle DragDrop outside of control - DragEnd event?

i'm are trying to mimic the behavior of web browsers in a WinForm application where you can drag and drop tabs in and out of the browser and create another instance of the it when you drop the tab somewhere with no existing tabs.
Currently the WinForm application only has one main TabControl and I was looking at the DoDragDrop() related events, but they seem to only work when you have two TabControls and move TabPages around those two.
Is there a way to make it work with only one TabControl? Meaning, If you Drop a TabPage out of the TabControl then it will create a new TabControl with the TabPage in it?
I can only think of using:
private void TabControl_DragLeave(object sender, EventArgs e)
{
Form newInstance = new Form();
TabControl newTabControl = new TabControl();
newInstance.Controls.Add(newTabControl);
newTabControl.TabPages.Add(sender as TabPage);
newInstance.Show();
}
but that is pretty crud and will create the new tab every time you leave the TabControl.
It seems you are looking for an event which raises at the end of drop, regardless of ending over your control or outside of the control.
You can rely on QueryContinueDrag and check if the action is Drop, then check the mouse position and for example if it's not inside your control, just create another window and add the selected tab into a tab control inside the new window.
private void tabControl1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
tabControl1.DoDragDrop(tabControl1.SelectedTab, DragDropEffects.All);
}
}
private void tabControl1_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TabPage)))
e.Effect = DragDropEffects.Move;
}
private void tabControl1_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
if (e.Action == DragAction.Drop)
{
var tabPage = tabControl1.SelectedTab;
if (!tabControl1.RectangleToScreen(tabControl1.Bounds).Contains(Cursor.Position))
{
var form = new Form();
form.Text = tabPage.Text;
var tabControl = new TabControl();
tabControl.TabPages.Add(tabPage);
tabControl.Dock = DockStyle.Fill;
form.Controls.Add(tabControl);
form.FormBorderStyle = FormBorderStyle.SizableToolWindow;
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(Cursor.Position.X - form.Width / 2,
Cursor.Position.Y - SystemInformation.CaptionHeight / 2);
form.Show();
e.Action = DragAction.Cancel;
//You can comment tabControl.TabPages.Add
//Then set e.Action = DragAction.Continue
//Then the DragDrop event will raise and add the tab there.
}
}
}
private void tabControl1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TabPage)))
{
var tabPage = (TabPage)e.Data.GetData(typeof(TabPage));
tabControl1.TabPages.Remove(tabPage);
tabControl1.TabPages.Add(tabPage);
}
}
For more advanced scenarios and to enhance the code:
When start dragging, you can start dragging just if the mouse dragged at least for a specific points, for example 16 points. It's easy to calculate. Having p1 as mouse down point and p2 as mouse move point, and d as drag threshold. start dragging just in case (p1.X-p2.X)*(p1.X-p2.X) + (p1.Y-p2.Y)*(p1.Y-p2.Y) > d*d.
You can use GiveFeedback event to disable default cursor of the mouse and instead show a more suitable cursor while dragging, easily by e.UseDefaultCursors = false; and setting Cursor.Current = Cursors.SizeAll; for example.
You can encapsulate the logic and put it in a derived TabControl. Then in DragEnter and DragLeave events set a static property for tracking drop target. In case the drop-target has value, it means you are dropping on a derived tab control, otherwise it means you are dropping outside. Then drag and drop will be easily enabled for all your custom tab controls.
You can close the tool form, after a drag and drop, in case the form doesn't contain any other tab.
When adding the tab, you can insert it before/after the selected tab or the tab under cursor in target.

(Winform) Cannot click the linklabel after adding it as MouseHover event fired

I have a PictureBox. I want to add automatically a LinkLabel at a specific location when the mouse hover to it. Everything's fine but I can't click on the LinkLabel as it can't stop flickering. This is my code:
private void ptbType1_MouseHover(object sender, EventArgs e)
{
PictureBox ptb = sender as PictureBox;
LinkLabel lkl = new LinkLabel();
lkl.Text = "Change Image...";
lkl.Font = new Font(lkl.Font.FontFamily, 10, FontStyle.Regular);
lkl.BackColor = SystemColors.Window;
lkl.AutoSize = false; lkl.TextAlign = ContentAlignment.MiddleCenter;
lkl.Size = new Size(120, 30); lkl.BorderStyle = BorderStyle.FixedSingle;
lkl.Location = new Point(ptb.Size.Width - 120, 5);
ptb.Controls.Add(lkl);
}
**UPDATE 10/18/2016: The idea using Tooltip to avoid LOTS OF linklabel by gzaxx suggests me to implement another way: A linklabel now has already been on the picture box, its Visible property was set False. When mouse hovers the picturebox, the label appears as Visible -> true, vice versa when mouse leaves. All remain the same: flickering makes it cannot be clicked. The MouseHover Event on the picture box, certainly, is the cause.
Any ideas? thanks for any help!
Your code have some issues. First you create A LOT of labels, each time mouse is moved by millimeter, new label is created. Second you do not attach event to link label so clicking on it does nothing. My advice would be to use Tooltip to show message when hovering over PictureBox with information "Click to change image..." and handle click event.
// should be called only once
private void AttachClickEvent(PictureBox ptb)
{
ptb.MouseClick += (s, o) =>
{
// open change dialog here
}
}
It's a straightforward solution.
Thanks for all your support, I've solved the problem. The key is
When the mouse cursor enter the linklabel, it coincidentally fire the MouseLeave_Event of the picturebox => linklabel disappears
As label vanished, the mouse cursor then enter the picturebox, so MouseHover_Event of the picturebox work => linklabel appears
---> eternal loop -> blinking
I 've dealt with it by this code to check whether the mouse cursor is in linklabel bound area, the linklabel stands still and only disappears when cursor actually get out of the picturebox:
private void ptbType1_MouseLeave(object sender, EventArgs e)
{
PictureBox ptb = sender as PictureBox;
LinkLabel lkl = ptb.Controls[0] as LinkLabel;
if (!lkl.Bounds.Contains(ptb.PointToClient(Cursor.Position)))
{
lkl.Visible = false;
}
}
Done! My 1st question on the site and i myself answer it, brilliant :))

How to determine which form was brought to front by clicking it?

I have an application with a Panel containing children Form objects. When I click one of the children Form it brings to front. I would like to know which one is in front now...
I've looked in event list but cant find proper event form my purpose :(
These methods doesn't work:
protected void OpenedFileForm_Enter(object sender, EventArgs e)
{
MessageBox.Show("enter");
}
protected void OpenedFileForm_Click(object sender, EventArgs e)
{
MessageBox.Show("click");
}
protected void OpenedFileForm_Activated(object sender, EventArgs e)
{
MessageBox.Show("activated");
}
protected void OpenedFileForm_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("mouse click");
}
protected void OpenedFileForm_Shown(object sender, EventArgs e)
{
MessageBox.Show("shown");
}
OpenFileDialog openFile1 = new OpenFileDialog();
openFile1.DefaultExt = "*.txt";
openFile1.Filter = "TXT Files|*.txt|RTF Files|*.rtf";
if (openFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
openFile1.FileName.Length > 0)
{
switch (Path.GetExtension(openFile1.FileName))
{
case ".txt":
txtForm childTXT = new txtForm();
this.childForms.Add(childTXT);
childTXT.Parent = this.mainPanel;
childTXT.richTextBox1.LoadFile(openFile1.FileName, RichTextBoxStreamType.PlainText);
childTXT.Show();
break;
}
}
Have you tried the Form.Activated Event?
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.activated(v=vs.80).aspx
Edit:
If you are in an MDI application, you might need to use MdiChildActivate instead.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.mdichildactivate.aspx
This code can only work when you set the Form.TopLevel property to false. Which makes it turn into a child control, almost indistinguishable from a UserControl.
This has many side-effects, for one there is no notion of "front" anymore. The Z-order of child controls is determined by their position in their parent's Controls collection. And it affects the events it fires, Activated and Deactivated will never fire. Furthermore, the Form class was designed to be a container control, it doesn't like taking the focus itself. Its child controls get the focus, the Form class doesn't have any use for focus. Which is why the Enter, Click and MouseClick events don't fire, they are events that require focus.
Long story short, what you are trying to do doesn't make a wholeheckofalot of sense. If it is strictly the Z-order you want to fix then write an event handler for the MouseDown event:
void OpenedFileForm_MouseDown(object sender, MouseEventArgs e) {
var frm = (Form)sender;
frm.BringToFront();
}
You could add frm.Select() to get the Enter event to fire, but only do that if the form doesn't contain any focusable controls itself. Do note that there is evidence that you don't assign the events correctly in your code. The Shown event does fire. It is also important that you set the FormBorderStyle to None, the title bar cannot indicate activation status anymore.
Ok, I got this! Thx for help everyone. You gave me a hint to think about equity of my strange MDI idea where Panel is parent for other Forms. I Removed SplitContainer containing Panel and just did standard MDI application, where Forms are MDIChildren of main Form.
childTXT.MdiParent = this;

how to exclude control from a WinForm.Opacity in C#

I have a form that i set it's Opacity as 50% like this:
this.Opacity = 0.5D; <--this==Form
My problem is that everything that on the form is with an Opacity of 50%
I have two buttons on the form and I want them without Opacity.
I know that this.Opacity included all Controls and for some reason the graphics too
My question is, How to Exclude the Opacity of the controls?
Example Image:
Thanks!
Since Control doesn't have Opacity property and plus that, most of the controls doesn't support transparent colors, then a working solution can be this:
Create a Form called MainForm and place all the controls you're going to be excluded.
1.1 Set both of BackColor and TransparencyKey properties of MainForm to the same color, e.g Color.Red
Create another form named TransparentForm and place all controls that must become transparent. Set ShowInTaskbar property to False.
In the MainForm Load event show the TransparentForm and send it to back.
private void MainForm_Load(object sender, EventArgs e)
{
TransparentForm form = new TransparentForm();
form.Opacity = 0.5D;
form.Show();
form.SendToBack();
}
The position of controls in both form must be such that, when combined, it shows the proper user interface.
Crate a C# project and add 3 forms named
MAIN
BACKGOUND
Child
and add the following code for "MAIN" form load event;
private void MAIN_Load(object sender, EventArgs e)
{
Child frm1 = new Child();
BACKGOUND frm2 = new BACKGOUND();
frm2 .WindowState = System.Windows.Forms.FormWindowState.Maximized;
frm2.Opacity = 0.5;
frm2.Show();
frm1.ShowDialog();
frm2.Close();
}

C# - How to trigger opacity event when form loses focus?

Purpose is to have the opacity event trigger when the form loses focus. The form has a setting for STAY ON TOP. The visual effect would be to click on a possibly overlapping window, and yet the form when not focused on would stay on top, but in the corner slightly transparent, keeping it within easy access, but providing visibility to the stuff underneath.
I 've googled and googled, and can't figure out how to get this event to properly fire when form loses focus, and then when form gains focus back to restore opacity to 100% or the level determined elsewhere.
Tips?
// under designer.cs
//
// CollectionToolForm
//
//other code....
this.LostFocus += new System.EventHandler(goTransparent);
//method
private void goTransparent(object sender, EventArgs e)
{
if (transparentCheck.Checked == true)
{
this.Opacity = 0.50;
}
else
{
this.Opacity = 1;
}
}
It sounds as if you are looking for the Activated and Deactivate events.
Update
In response to the comment about LostFocus event, it could be of interest to clarify how it works. The LostFocus event of the Form is inherited from Control. It is raised when a controls loses focus; either because the form as such is being deactivated (focus moves to another application for instance), or because focus moves to another control within the same form.
If you hook up an event handler for the LostFocus event of a form that contains only at least one control that can receive focus, you will find that the LostFocus event of the form is raised immediately after the form is displayed. This is because focus moves from the form (which is a Control) to the first focusable control on the form.
So, the form being active and the form being focused are two separate behaviours.
You tried doing it with mouse enter/leave events?
public Form1()
{
this.MouseEnter += new System.EventHandler(this.Form1_MouseEnter);
this.MouseLeave += new System.EventHandler(this.Form1_MouseLeave);
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
this.Opacity = 0.5;
}
private void Form1_MouseEnter(object sender, EventArgs e)
{
this.Opacity = 1;
}

Categories

Resources