views:

227

answers:

1

The code below demonstrates a very simple problem; I am hoping that I am just missing a setting that someone might be able to reveal.

Goal

(1) Launch main winform (MainForm).
(2) Press button to display secondary winform (ShadowForm) that is semi-transparent and should exactly overlay MainForm.

What Actually Happens

Scenario 1: Launch main winform then press button: ShadowForm displays with correct size but incorrect location, lower and to the right (as if it was cascaded). Press button to close ShadowForm again. Press button once more to reopen ShadowForm and now it is in the correct position, covering MainForm.

Scenario 2: Launch main winform, move it around, then press button: ShadowForm displays with correct size but incorrect location (where the MainForm was before moving it). Press button to close; press again to reopen and now ShadowForm is in the correct position.

using System;
using System.Windows.Forms;

namespace LocationTest
{
    static class Program
    {
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }

    public class MainForm : Form
    {
        ShadowForm shadowForm = new ShadowForm();
        Button button1 = new Button();
        System.ComponentModel.IContainer components = null;

        public MainForm()
        {
            this.SuspendLayout();
            this.button1.Location = new System.Drawing.Point(102, 44);
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.Text = "button1";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.button1);
            this.ResumeLayout(false);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (shadowForm.Visible) { shadowForm.Hide(); }
            else
            {
                shadowForm.Size = Size; // this always works
                shadowForm.Location = Location; // this fails first time, but works second time!
                shadowForm.Show();
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null)) { components.Dispose(); }
            base.Dispose(disposing);
        }
    }

    public class ShadowForm : Form
    {
        private System.ComponentModel.IContainer components = null;

        public ShadowForm()
        {
            this.SuspendLayout();
            this.BackColor = System.Drawing.Color.Black;
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Opacity = 0.5;
            this.Click += new System.EventHandler(this.ShadowForm_Click);
            this.ResumeLayout(false);
        }

        private void ShadowForm_Click(object sender, EventArgs e)
        {
            Hide();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null)) { components.Dispose(); }
            base.Dispose(disposing);
        }
    }
}
+3  A: 

You should set the StartPosition to manual before setting your location the first time.

shadowForm.StartPosition = FormStartPosition.Manual;
shadowForm.Size = Size; // this always works
shadowForm.Location = Location; // this fails first time, but works second time!
shadowForm.Show();

or as Joel suggested:

shadowForm.StartPosition = FormStartPosition.CenterParent;  // Location shouldn't need to be set
shadowForm.Size = Size; // this always works
shadowForm.Show();
heavyd
Or, while you're at it, just set StartPosition to "CenterParent" and forget about location completely.
Joel Coehoorn
Yes... even better
heavyd
Thanks for an exceedingly quick (and correct!) response. I was not aware of that particular property. You not only solved this issue but you solved another item on my 'todo' list involving a sub-window not opening on the same monitor as the current window. Double kudos to you!
msorens