Relocate form created inside a previous form - c#

I have two form classes (IHM and HelpPanel). In my first loaded form (IHM) I call the function bHclass_Click to create and load a HelpPanel. The PopulatePCBclasses() function basically creates all the controls that will be displayed.
My issue is that this HelpPanel is always displayed at the exact same location no matter what value is input in it's Location property.
I tried also by setting the Top and Left attributes but result was the same.
Do I miss an instruction?
private void bHclass_Click(object sender, EventArgs e)
{
HelpPanel hp = new HelpPanel();
hp.PopulatePCBclasses();
hp.Location = new Point(10, 500);
hp.Show();
}

Try setting the start position as manual before changing the location:
private void bHclass_Click(object sender, EventArgs e)
{
HelpPanel hp = new HelpPanel();
hp.PopulatePCBclasses();
hp.StartPosition = FormStartPosition.Manual;
hp.Location = new Point(10, 500);
hp.Show();
}

Related

Apply parent mouse events to child elements

I am making little Windows Forms Application.
I have PictureBox (parent) and Label (child) in it.
The Parent's Mouse Events are working perfectly, but Mouse events generated by child elements are not reflected on the Parent. The Cursor also changes back to its default (arrow).
Is it possible to pass events generated by child Controls, e.g., the MouseEnter event, to the Parent Control?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Card.MouseEnter += new EventHandler(Card_MouseEnter);
Card.MouseLeave += new EventHandler(Card_MouseLeave);
Card.MouseDown += new MouseEventHandler(this.Card_MouseDown);
Card.MouseUp += new MouseEventHandler(this.Card_MouseUp);
}
void Card_MouseLeave(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_bg));
this.Rename("Running!");
}
void Card_MouseEnter(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_hover_bg));
}
private void Card_MouseDown(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_click_bg));
}
private void Card_MouseUp(object sender, EventArgs e)
{
this.Card.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.card_hover_bg));
this.Rename("Please Wait...");
}
private void CardName_MouseDown(object sender, MouseEventArgs e)
{
}
void Rename(string args)
{
this.CardName.Text = args;
}
private void CardName_Click(object sender, EventArgs e)
{
}
}
         
This is what I have This is what I want to achieve
The first animation represents what I have now, the second is what I need to achieve :)
When I'm making pictureBox1.Controls.Add(label1) label1 is
disappearing and I tried bring to front and change color but couldn't
do it. Please if you will have any idea show me in provided code by me
to be understandable for me. Thank you all again and again :)
You'd use code like this, maybe in the Load() event of the Form:
private void Form1_Load(object sender, EventArgs e)
{
Point pt = CardName.Parent.PointToScreen(CardName.Location);
Card.Controls.Add(CardName);
CardName.Location = Card.PointToClient(pt);
}
This keeps the label in the same position as it was, but makes the picturebox the parent.
Not sure where you're going wrong. Here's an example showing it in action. Both the PictureBox (Card) and Label (CardName) are inside a Panel (panel1). Clicking on button2 toggles the visibility of the Card. Clicking on button1 makes Card the Parent of CardName. You can see that at first, only the Card toggles visibility, but after clicking on button1 and setting the Parent, both toggle visibility together since CardName is a Child of Card (it also changes its BackColor to match that of its new Parent):
Code:
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Point pt = CardName.Parent.PointToScreen(CardName.Location);
Card.Controls.Add(CardName);
CardName.Location = Card.PointToClient(pt);
}
private void button2_Click(object sender, EventArgs e)
{
Card.Visible = !Card.Visible;
}
}
When I move mouse over label, panel thinks mouse left it and rises
MouseLeave event
Here is how you can tell if the cursor has actually left the BOUNDS of the Panel, as opposed to simply enter a child control within the Panel:
private void panel1_MouseEnter(object sender, EventArgs e)
{
panel1.BackColor = Color.Red;
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
Point pt = panel1.PointToClient(Cursor.Position);
if (!panel1.ClientRectangle.Contains(pt))
{
// we only get in here when the cursor leaves the BOUNDS of panel1
panel1.BackColor = Control.DefaultBackColor;
}
}
First of all, you should build a UserControl as a container for all your objects: it'd make everything simpler (the one I'm using here is actually a UserControl, modified to comply with your current setup).
When a Control other than the PictureBox is interacted with, you can decide whether you want to trigger a similar action on the main Control or perform a different action based on what event has been generated.
▶ When the Mouse Pointer enters you assembled Control, you want to change the default Cursor: then, when one of the Labels raises the Enter event, call the method of the main Control that handles this. An event handler is a method, you can call it.
▶ When a Label is clicked, you don't want to trigger the related action of the main Control: in this case, there's nothing to do, just handle this event and perform the required action.
▶ The Label should be child of the main Control. You're using a PictureBox, which is not a ContainerControl. You can add child controls to it anyway. You need to do this in code, since - as mentioned - the PictureBox is not designed to host Controls, thus you cannot drop one inside it: the Control you drop will be parented with the Container that hosts the PictureBox (your Form, here).
When you set the parent in code, you need to remember that the Location of the child control is relative to the old Parent, so you have to re-define it's position.
E.g: PictureBox.Bounds = (100, 100, 100, 200) / Label.Bounds = (100, 250, 100, 50)
When the PictureBox becomes Parent of your Label, the Label.Location is still (100, 250): so, now, it will be hidden, since it's outside the visible bounds of its new Parent. You have to reposition it in relation to the new host: its new Location should be (0, 150), to keep the previous relative position.
PictureBox.Control.Add(Label);
//[...]
Label.Location = new Point(Label.Left - PictureBox.Left, Label.Top - PictureBox.Top);
=> Label.Location = (100 - 100, 250 - 100) => (0, 150)
Or, centered horizontally:
Label.Location = new Point((PictureBox.Width - Label.Width) / 2, Label.Top - PictureBox.Top);
=> Label.Location = ((100 - 100) / 2, 250 - 100) => (0, 150) // <- Since both have the same Width
Or, using positions relative to the Screen:
var p = Label.PointToScreen(Point.Empty); // Relative to the ClientRectangle (Top/Left = (0, 0))
PictureBox.Controls.Add(Label);
Label.Location = PictureBox.PointToClient(p);
In any case, call BringToFront() after, to ensure that the new child Control is brought on top and anchor the Control, so it will keep its position and its Width will be bound to the Parent Width:
Label.BringToFront();
Label.Anchor = AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right;
Now, assuming you want to change the Cursor to Cursors.Hand when the Mouse enters your combined Control and reset to default when it leaves it:
▶ You want the Cursor to change shape in any case.
▶ You want to generate different actions when the PictureBox is clicked and when one of the Labels is clicked.
▶ Both Labels can have distinct actions when clicked.
→ In the visual sample, the Label above the PictureBox is named lblTitle, the Label inside the PictureBox, at the bottom, is named lblFooter.
→ The PictureBox is named ImageView.
Setup the handlers:
NOTE: With a UserControl, the events handling, e.g., in relation to MouseEnter, changes in:
// The Parent's MouseEnter calls OnMouseEnter
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Hand;
}
// Child Controls just call the same method
private void Labels_MouseEnter(object sender, EventArgs e) => OnMouseEnter(e);
public Form1()
{
InitializeComponent();
Point p = lblFooter.PointToScreen(Point.Empty);
ImageView.Controls.Add(lblFooter);
lblFooter.Location = ImageView.PointToClient(p);
ImageView_MouseEnter += ImageView_MouseEnter;
ImageView_MouseLeave += ImageView_MouseLeave;
// Not added in the code here, do whatever is needed with this handler
ImageView_Click += ImageView_Click;
lblFooter.MouseEnter += Labels_MouseEnter;
lblFooter.MouseLeave += Labels_MouseLeave;
lblFooter.MouseClick += lblFooter_MouseClick;
lblTitle.MouseEnter += Labels_MouseEnter;
lblTitle.MouseLeave += Labels_MouseLeave;
lblTitle.MouseDown += lblTitle_MouseDown;
lblTitle.MouseUp += lblTitle_MouseUp;
}
private void ImageView_MouseEnter(object sender, EventArgs e) => this.Cursor = Cursors.Hand;
private void ImageView_MouseLeave(object sender, EventArgs e) => this.Cursor = Cursors.Default;
private void Labels_MouseEnter(object sender, EventArgs e)
{
ImageView_MouseEnter(ImageView, e);
// [...]
// Do stuff related to the Labels Enter event
}
private void Labels_MouseLeave(object sender, EventArgs e) {
ImageView_MouseLeave(ImageView, e);
}
private void lblTitle_MouseDown(object sender, MouseEventArgs e) {
// Perform actions when the Mouse button is held down lblTitle
}
private void lblTitle_MouseUp(object sender, MouseEventArgs e) {
// Perform actions when the Mouse button is released
}
private void lblFooter_MouseClick(object sender, MouseEventArgs e) {
// Perform actions on a Mouse Click event on lblFooter
}

How to fix black/negative background on livecharts chart in winforms

When adding a usercontrol at runtime (with a button click for example) that has a chart on, it causes the background of the chart to go black/negative.
When I add the usercontrol during the forms load it does not have this issue.
private void Form1_Load(object sender, EventArgs e)
{
//this one loads fine
testingControl tc = new testingControl();
this.Controls.Add(tc);
tc.Location = new Point(470, 53);
//......
}
private void Button1_Click(object sender, EventArgs e)
{
testingControl tc = new testingControl();
this.Controls.Add(tc);
//tc.Visible = false;
//tc.Visible = true;
tc.Location = new Point(0, 53);
}
I found out after some google searches, that hiding it and then setting it visible again kind of fixes it, but that seems a bit janky.
Does anyone know what I can do to fix this?
P.S. the data that is in the chart I got from the 'livecharts' website, but the problem happens no matter if there is data or not.
The problem also happens on all charts.
Got similar problem & made few changes to get it fixed ,
Just change the chart visibility false
Change
Then , Make it visible on form load .
private void Form1_Load(object sender, EventArgs e)
{
pieChart1.Visible = true;
....
}
Hope this will help you !.

NullReferenceException dynamically created controls, object seems to exist

In Win Forms I have these three test methods. First to create a button, second to create a tab control with two tabs and third to move created button to first tab.
private void button1_Click(object sender, EventArgs e)
{
Button przycisk = new Button();
przycisk.Location = new Point(24, 250);
przycisk.Name = "nowy";
przycisk.Text = "utworzony";
przycisk.Width = 131;
przycisk.Height = 23;
Controls.Add(przycisk);
}
private void button2_Click(object sender, EventArgs e)
{
TabControl zakladki = new TabControl();
zakladki.Location = new Point(208, 160);
zakladki.Name = "zakl";
zakladki.Height = 150;
zakladki.Width = 208;
zakladki.TabPages.Add("zakladka1", "pierwsza");
zakladki.TabPages.Add("zakladka2", "druga");
Controls.Add(zakladki);
}
private void button3_Click(object sender, EventArgs e)
{
TabControl zakladki = (TabControl)Controls.Find("zakl", false).FirstOrDefault();
int numerZakladki = 1;
foreach (TabPage zakladka in zakladki.TabPages)
{
Control kt = Controls["nowy"];
kt.Location = new Point(10, 10); // System.NullReferenceException
zakladka.Controls.Add(kt);
numerZakladki++;
}
}
I'm having a hard time to understand the behavior upon trying to change the referenced button location. The code above throws System.NullReferenceException, but when I do
if (kt != null)
{
kt.Location = new Point(10, 10);
}
it works as expected. Can anyone explain it to me ?
The new TabControl contains two Tabs.
If you move the button to the first Tab, the control at the Main form is null.
Code without Loop:
private void button3_Click(object sender, EventArgs e)
{
TabControl zakladki = (TabControl)Controls.Find("zakl", false).FirstOrDefault();
Control kt = Controls["nowy"];
kt.Location = new Point(10, 10);
zakladki.TabPages[0].Controls.Add(kt);
}
Your nowy controls are added to the root control (Form I guess), but you are trying to find them in the tab pages under zakl. You have to either add the controls to the tab page, or find them in the root control, just like you did with zakl.
You move the "nowy" button from the Form.Controls to the first TabPage's Controls collection. This removes the control from the first collection, so the code throws the exception on the next iteration. A Control can have only a singleParent.
Either create the Button for each tab separately (instead of moving it), or add the Button to the first tab only (without the foreach loop).

Saving Location for next form

Alright so I'm doing something with next buttons that open new forms, annoying thing is that new forms pop up somewhere I don't want to on the desktop.
I'm trying to get the new form to spawn on the location of the old form with the code below, unfortunately for whatever reason it's not working at all, they still pop up the same way as before. And yes I have registered the events.
Form1:
System.Drawing.Point LocationPoint = new System.Drawing.Point(200,200);
private void Installer_template_LocationChanged(object sender, EventArgs e)
{
// Save the window location to the installer arts
LocationPoint = this.Location;
}
private void NextButton_Click(object sender, EventArgs e)
{
var NextForm = new Form2(LocationPoint);
NextForm.Show();
this.Hide();
}
Form2
public Form2(System.Drawing.Point LocationPoint)
{
InitializeComponent();
this.Location = LocationPoint;
}
The code is something along those lines
Have you tried setting the StartPosition of the new forms, i.e.
this.StartPosition = FormStartPosition.Manual;
or
this.StartPosition = FormStartPosition.CenterParent;
Alrighty I fixed it, it was a bunch of problems.
Wrong property, gotta use DesktopLocation instead of Location property
Second I had some issues with static member that couldn't be modified or whatever the error is, I just used the settings file to save my location instead
Having that done, it still didn't work because you can't just do this.DesktopLocation = something, you have to use this.SetDesktopLocation(X, Y)
Still didn't work, because it got overwritten by other code when loading the form so you had to use the Shown even of the form and run it in there..

DrawToBitmap on Panel is blank

So I've written a class that has a stores some test results info and then a control that displays that info to the user. I want to put a print function on this class to draw the control at a full page size and print it. However it always comes out blank. The code see the panel as a control because it could be some other type of value. I figure there must be something simple I'm missing.
void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
System.Drawing.Size oldSize = printData.Size;
printData.Size = new System.Drawing.Size(e.MarginBounds.Width, e.MarginBounds.Height);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(printData.Size.Width, printData.Size.Height);
InvertZOrderOfControls(printData.Controls);
printData.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, printData.Size.Width, printData.Size.Height));
InvertZOrderOfControls(printData.Controls);
e.Graphics.DrawImage(bitmap, e.MarginBounds.Location);
bitmap.Save(#"C:\Users\jdudley\Documents\File.bmp");
printData.Size = oldSize;
}
Following this advice of this thread inverted the Z-Order of the controls but it didn't change anything.
The save call was added for debugging. It looks like it's actually rendering the background color of the panel without any of the controls.
Edit: This is in the context of printing but I have not issue with printing what so ever. My error is in creating the bitmap. The save line I added proves this because it creates a blank bitmap file.
Change your entire event to this
void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(printData.Width, printData.Height);
printData.DrawToBitmap(bitmap, new System.Drawing.Rectangle(new Point(0, 0), printData.Size));
e.Graphics.DrawImage(bitmap, e.MarginBounds.Location);
}
Edit
This is my whole Project. I created a panel named printData and I added two buttons, I attached an event to button1.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
PrintDocument printDocument = new PrintDocument();
public Form1()
{
InitializeComponent();
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
}
void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(printData.Width, printData.Height);
printData.DrawToBitmap(bitmap, new System.Drawing.Rectangle(new Point(0, 0), printData.Size));
e.Graphics.DrawImage(bitmap, e.MarginBounds.Location);
}
private void button1_Click(object sender, EventArgs e)
{
pd.Print();
}
}
}
You have to try this and see if it works, or else I wont be able to sleep tonight!!

Categories