从另一个类添加控件到窗体

时间:2010-11-19 11:58:15

标签: c# forms controls

我有一个程序,它在Form1中创建一个pictureBox,然后创建一个我称为InitialState的类的实例。 InitialState将源放到Image中以便显示它,经过一段时间后,我使用了Timer,它创建了下一个类MainMenuState。现在,在我创建的MainMenuState类中,我想创建另一个pictureBox并使其显示在该Form1上。后来,我想让它里面的图片改变一点,然后(可能)破坏那个pictureBox。之后,程序进入下一个状态(在另一个类中),并且我希望该类将图片框添加到原始表单中,依此类推。

基本上,我想动态地将控件添加到主Form1,但不是在所述表单中,而是从我稍后创建的类中添加。我一直在互联网上寻找一种方法来做到这一点,似乎我必须使用委托才能调用Form1类的Controls.Add方法。我试过了,代码编译了,但是pictureBox仍然没有显示出来。

这是我的代码:

Form1类:

 public const string RESOURCE_PATH = "C:/Users/Noel/Documents/Visual Studio 2010/Projects/A/Resources/Animations/";

public Form1()
        {
            InitializeComponent(); //here, the first pictureBox shows

            iInitializeComponent();
            zacetnaAnimacija.Dock = DockStyle.Fill; //zacetnaAnimacija is the first pictureBox that appears
            zacetnaAnimacija.Anchor = AnchorStyles.Top | AnchorStyles.Left;
            zacetnaAnimacija.SizeMode = PictureBoxSizeMode.StretchImage;
            InitialState intialState = new InitialState(this, zacetnaAnimacija); //entering InitialState
        }

InitialState类:

class InitialState : State
    {

        System.Timers.Timer initialTimer;
        PictureBox pictureBox1;
        Form1 form;

        public InitialState (Form1 form, PictureBox pictureBox1) {
            this.form = form;
            GifImage zacetnaSlika = new GifImage(Form1.RESOURCE_PATH + "Presenting.gif"); //this is just a .gif picture I'm displaying

            Image trenutnaSlika = zacetnaSlika.GetFrame(0); //a method that plays the .gif
            pictureBox1.Image = trenutnaSlika; //makes the first .gif display
            this.pictureBox1 = pictureBox1;            

            initialTimer = new System.Timers.Timer(2500);
            initialTimer.Enabled = true;
            initialTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        }

        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            initialTimer.Enabled = false;
            MainMenuState menuState = new MainMenuState(form, pictureBox1); //enters main menu state with the Form1 argument passed on

        }

MainMenuState类:

class MainMenuState : State
    {
        Form1 form;

        public MainMenuState (Form1 form, PictureBox pictureBox1) {
            this.form = form;
            GifImage zacetnaSlika = new GifImage(Form1.RESOURCE_PATH + "animated.gif");

            Image trenutnaSlika = zacetnaSlika.GetFrame(0);
            pictureBox1.Image = trenutnaSlika; //this simply makes another .gif appear in the picture box instead of the first one

            PictureBox a = new PictureBox(); //HERE'S my problem, when I want to add ANOTHER pictureBox to that form.
            a.BackgroundImage = trenutnaSlika;
            a.Location = new System.Drawing.Point(0, 0);
            a.Name = "zacetnaAnimacija";
            a.Size = new System.Drawing.Size(150, 150);
            a.TabIndex = 1;
            a.TabStop = false;

            AddControl(a); //calling the delegate
        }


        public delegate void AddControls(PictureBox a);
        public void AddControl(PictureBox a)
        {
            if (form.InvokeRequired)
            {
                AddControls del = new AddControls(AddControl);
                form.Invoke(del, new object[] { a });
            }
            else
            {
                form.Controls.Add(a);
            }
        }

正如我所说,代码编译,但是当创建MainMenuState时,它不会在Form1上创建PictureBox。问题是,如果我不在MainMenuState中使用委托,只是尝试做类似form.Controls.Add(a)的事情,那么我得到一个“跨线程操作无效”异常,它不会甚至编译。这就是我使用代表的原因,但即使是现在,它也无效。

有人可以帮帮我吗?

3 个答案:

答案 0 :(得分:1)

天啊,我刚刚找到了原因X_x

事实是,由于第一个pictureBox覆盖了整个表单,而第二个是由代表创建的,显示在后面它!我只需要把它带到前面!

谢谢你们,尽管如此,如果没有你,我可能不会那么做。

编辑:不过,请问如何将控件带到前面? a.BringToFront()函数似乎不起作用。

答案 1 :(得分:1)

        initialTimer = new System.Timers.Timer(2500);

这是你遇到麻烦的部分原因。 Elapsed事件在线程池线程上运行,强制您进行BeginInvoke歌曲和舞蹈。使用System.Windows.Forms.Timer,它的Tick事件在UI线程上运行。

你也会遇到内存管理问题,这些类需要实现IDisposable。

答案 2 :(得分:0)

而不是

form.Invoke(del, new object[]{a});

尝试:

form.Invoke(new ThreadStart(delegate
   {
      form.Controls.Add(a);
   }
));