在表单上显示Usercontrol

时间:2014-04-20 09:54:48

标签: c# user-controls

我正在尝试向我的表单显示一个usercontrol。 usercontrol是一个带有鸟的gif-image的图片框。

我正在尝试这样做:

//main form
class Form1
{
    //play button
    private void gameButton1_Click(object sender, EventArgs e)
    {
        startPanel.Visible = false;
        Game g = new Game(this.gamePanel1);
        g.Start();
    }
}

class Game
{
    //is set to true after starting game

    public Game(gamePanel Display)
    {
        this.Display = Display;
    }

    bool Running = false;

    public gamePanel Display;

    public void Start()
    {

        Thread create_BirdsThread = new Thread(new ThreadStart(create_Birds));
        create_BirdsThread.Start();
        Running = true;

    }

    private void create_Birds()
    {
        while (Running)
        {

            //Display is a variable from class 'GamePanel'
            Display.CreateBirds();
            Display.Refresh();

            //this is just to test that one bird works
            Running = false;
        }
    }
}


class gamePanel : UserControl
{
    public void CreateBirds()
    {
        yBird y = new yBird();
            y.BackColor = System.Drawing.Color.Transparent;
            y.Location = new System.Drawing.Point(32, 56);
            y.Size = new System.Drawing.Size(96, 65);
            y.TabIndex = 1;

            if (this.InvokeRequired)
            {
                this.BeginInvoke((MethodInvoker)delegate()
                {
                    this.Controls.Add(y);
                });
            }
            else
            {
                this.Controls.Add(y);
            }
            y.Visible = true;
            y.BringToFront();
    }
}

但它不会在我的屏幕上显示一只鸟。 如何解决这个问题?

谢谢!

*编辑:

我从我的主表单和Game.Start()方法添加了代码

2 个答案:

答案 0 :(得分:2)

当然,这段代码无法正常工作。为了使Control.Begin / Invoke()起作用,.NET首先需要知道代码需要运行的特定线程。它从Handle属性中得出。这告诉它哪个特定线程拥有该窗口,底层的winapi调用是GetWindowThreadProcessId()

但这是你代码中的鸡与蛋问题。在代码调用Controls.Add()方法之前,不会创建本机窗口。哪个必须在程序的UI线程上运行,该线程拥有Form对象。 Windows不允许子窗口由其他线程拥有。

所以它只是不知道要调用的线程。如果你强制创建句柄,那么由于所有权规则,你的程序会以不同的方式死掉。

请注意更大的问题:您正在创建一个线程来运行需要几纳秒的代码。这些属性分配非常便宜。 真正的工作正在创建窗口,需要很多微秒。您希望(并且需要)在UI线程上运行。因此,根本没有使用线程的好处,UI线程也不会花费几纳秒来设置属性。

因此完全删除线程以获得成功。如果你做的其他事情很慢,比如加载图像,那么 就可以在工作线程上轻松完成。

答案 1 :(得分:0)

我已经修好了。

我刚刚改变了这个

if (this.InvokeRequired)
            {
                this.BeginInvoke((MethodInvoker)delegate()
                {
                    this.Controls.Add(y);
                });
            }

到这个

if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(this.yellow));

            }