实时创建glControl窗口

时间:2017-12-21 19:25:33

标签: c# winforms opengl opentk

基本上,我试图在Widows Forms上实时创建一个glControl窗口。我这样做是因为我将使用多个窗口,而且更有可能重新调整其位置,我不想手动执行此操作。

我不明白为什么我的代码不起作用。这是:

using System;
using System.Drawing;
using System.Windows.Forms;

using System.Diagnostics;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform;

namespace Draw3Dv01wf
{
    public partial class Form1 : Form
    {
        GLControl renderCanvas1;
        int winX, winY, winW, winH;

        public Form1()
        {
            // required method for designer support
            InitializeComponent();
        }


        // load event handler
        private void Form1_Load(object sender, EventArgs e)
        {
            // create and setup gl.control windows
            this.renderCanvas1 = new GLControl();
            //this.SuspendLayout();

            winX = this.Location.X; winY = this.Location.Y;
            winW = this.Width; winH = this.Height;

            this.renderCanvas1.BackColor = System.Drawing.Color.CadetBlue;
            this.renderCanvas1.Location = 
                new System.Drawing.Point(winX + 50, winY + 50);
            this.renderCanvas1.Name = "renderCanvas1";
            this.renderCanvas1.Size = new System.Drawing.Size(winW/3, winH/2);
            this.renderCanvas1.TabIndex = 1;
            this.renderCanvas1.VSync = false;
            this.renderCanvas1.Load += 
                new System.EventHandler(this.renderCanvas_Load);
            this.renderCanvas1.Paint += 
                new System.Windows.Forms.PaintEventHandler(
                    this.renderCanvas_Paint);
            //renderCanvas1.Paint += renderCanvas_Paint;
            //this.ResumeLayout(false);
        }

        private void renderCanvas_Paint(object sender, PaintEventArgs e)
        {
            GL.Viewport(winX + 20, winY + 25, Width, Height);

            // Clear the render canvas with the current color
            GL.Clear(
                ClearBufferMask.ColorBufferBit | 
                ClearBufferMask.DepthBufferBit);

            GL.Flush();
            renderCanvas1.SwapBuffers();
        }

        private void renderCanvas_Load(object sender, EventArgs e)
        {
            // Specify the color for clearing
            GL.ClearColor(Color.SkyBlue);
        }
    }
}

我刚看到窗户就形成了。 glControl窗口不显示。 但是,当我手动将glControl添加到表单时,添加以下代码:

    //____________________________________________

    private void glControl1_Load(object sender, EventArgs e)
    {
        // Specify the color for clearing
        GL.ClearColor(Color.SkyBlue);

        this.Paint += new PaintEventHandler(glControl1_Paint);
    }

    private void glControl1_Paint(object sender, PaintEventArgs e)
    {
        GL.Viewport(this.Location.X, this.Location.Y, Width, Height);

        // Clear the render canvas with the current color
        GL.Clear(
            ClearBufferMask.ColorBufferBit |
            ClearBufferMask.DepthBufferBit);

        GL.Flush();
        glControl1.SwapBuffers();
    }

    //________________________________________________________

...此窗口显示在表单上。

我的程序中的代码与设计器中的代码没有什么不同,所以我完全不解。

这是设计师代码:

    this.glControl1 = new OpenTK.GLControl();
    this.SuspendLayout();
    // 
    // glControl1
    // 
    this.glControl1.BackColor = System.Drawing.Color.Black;
    this.glControl1.Location = new System.Drawing.Point(385, 12);
    this.glControl1.Name = "glControl1";
    this.glControl1.Size = new System.Drawing.Size(476, 284);
    this.glControl1.TabIndex = 0;
    this.glControl1.VSync = false;
    this.glControl1.Load += new System.EventHandler(this.glControl1_Load);
    // 
    // Form1
    // 
    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.BackColor = System.Drawing.SystemColors.Desktop;
    this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
    this.ClientSize = new System.Drawing.Size(1264, 681);
    this.Controls.Add(this.glControl1);
    this.HelpButton = true;
    this.MaximumSize = new System.Drawing.Size(3840, 2160);
    this.MinimumSize = new System.Drawing.Size(640, 480);
    this.Name = "Form1";
    this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
    this.Text = "Draw3D";
    this.ResumeLayout(false);

1 个答案:

答案 0 :(得分:1)

我通过创建另一个glControl尝试了一些东西,但这一次,不是在Form的Load事件处理程序中。

public Form1()
{
    // required method for designer support
    InitializeComponent();
    initSetup();
}

private void initSetup()
{
    winX = this.Location.X; winY = this.Location.Y;
    winW = this.Width; winH = this.Height;

    this.renderCanvas2 = new GLControl();
    this.renderCanvas2.BackColor = System.Drawing.Color.DeepSkyBlue;
    this.renderCanvas2.Location =
        new System.Drawing.Point(winX + 150, winY + 150);
    this.renderCanvas2.Name = "renderCanvas2";
    this.renderCanvas2.Size = 
        new System.Drawing.Size(winW / 2, winH / 2);
    this.renderCanvas2.TabIndex = 1;
    this.renderCanvas2.VSync = false;
    this.renderCanvas2.Load +=
        new System.EventHandler(this.renderCanvas2_Load);
    this.renderCanvas2.Paint +=
        new System.Windows.Forms.PaintEventHandler(
            this.renderCanvas2_Paint);

    this.Controls.Add(this.renderCanvas2);
}

......它奏效了。我不知道为什么会这样。它还导致手动创建的glControl窗口变为黑色 - 在其原始位置,或白色 - 如果移动。 但是,至少我得到了结果。我会继续玩它,看看我能弄清楚什么。我感觉它可能与缓冲有关。 我的另一个选择是手动创建窗口,并通过代码调整它们的位置和大小,因为这也有效。 如果有人知道,我仍然欢迎任何有关代码在Form的加载事件处理程序中不起作用的输入。感谢

修改 我正在取得进步。我只有最后一步。 所以现在我使用一组glControl来创建我的窗口,但是我并不想创建多个事件处理程序来管理每个窗口,所以我试图只用一个Load事件和一个Paint事件来获得结果。 但是,我在所有窗口上设置颜色时遇到问题。我不确定这种方法是否可行。我真的很感激这方面的任何帮助。 这是我的测试代码:

using...

namespace Draw3Dv01wf
{
    public partial class Form1 : Form
    {
        GLControl[] renderCanvas = new GLControl[10];
        private int 
            winX, winY, winW, winH, winDist, winNum, 
            aCol, rCol, gCol, bCol;
        Random randNum = new Random();
        //byte[] num = new byte[255];
        byte r, g, b, a;
        Color4 winCol;
        private bool winCreated;
        private bool eHandlerIs;

        TextBox tb = new TextBox();

        public Form1()
        {
            // required method for designer support
            InitializeComponent();
            initSetup();
        }

        private void initSetup()
        {
            winX = this.Location.X; winY = this.Location.Y;
            winW = this.Width; winH = this.Height;
            rCol = 255; gCol = 255; bCol = 255; aCol = 255;

            // debugging text
            tb.Location = new Point(5, 5);
            tb.Size = new Size(200, 15);
            tb.Name = "textBox1";
            tb.TabIndex = 0;
            tb.BackColor = Color.Black;
            tb.ForeColor = Color.White;
            tb.Text = winNum.ToString();
            this.Controls.Add(this.tb);

            // create windows
            for (int w=0; w<8; w++)
            {
                // window distance 
                winDist += 32;
                // make sure window with index 0 is created
                if (winCreated) { winNum += 1; }

                // create windows 
                this.renderCanvas[w] = new GLControl();
                //this.SuspendLayout();
                this.renderCanvas[w].BackColor = 
                    System.Drawing.Color.DeepSkyBlue;
                this.renderCanvas[w].Location =
                    new System.Drawing.Point(winX + winDist, winY + winDist);
                this.renderCanvas[w].Name = "renderCanvas" + w;
                this.renderCanvas[w].Size =
                    new System.Drawing.Size(winW / 2, winH / 2);
                this.renderCanvas[w].TabIndex = 1;
                this.renderCanvas[w].VSync = false;
                // create event handler 
                this.renderCanvas[w].Load +=
                    new System.EventHandler(this.renderCanvas_Load);
                if (!eHandlerIs)
                {
                    this.renderCanvas[w].Paint +=
                        new System.Windows.Forms.PaintEventHandler(
                            this.renderCanvas_Paint);
                    //eHandlerIs = true;
                }
                //this.ResumeLayout(false);

                // add specified control to the control collection 
                this.Controls.Add(this.renderCanvas[w]);
                winCreated = true; // first window created
            }
        }

        private void renderCanvas_Paint(object sender, PaintEventArgs e)
        {
            tb.Text = r.ToString();
            if (winNum < 7)
            {
                //GL.Viewport(
                //    renderCanvas[winNum].Location.X,
                //    renderCanvas[winNum].Location.Y, Width, Height);

                //// Clear the render canvas with the current color
                //GL.Clear(
                //    ClearBufferMask.ColorBufferBit |
                //    ClearBufferMask.DepthBufferBit);

                //GL.Flush();
                //renderCanvas[winNum].SwapBuffers();
            }
            else if (winNum >= 7)
            {
                for (int w = 0; w < 8; w++)
                {
                    GL.Viewport(
                    renderCanvas[w].Location.X,
                    renderCanvas[w].Location.Y, Width, Height);

                    // Clear the render canvas with the current color
                    GL.Clear(
                        ClearBufferMask.ColorBufferBit |
                        ClearBufferMask.DepthBufferBit);

                    GL.Flush();
                    renderCanvas[w].SwapBuffers();
                }
            }
        }

        private void renderCanvas_Load(object sender, EventArgs e)
        {
            // randomize color (min & max int)
            rCol = randNum.Next(100, 255);
            gCol = randNum.Next(100, 255);
            bCol = randNum.Next(100, 255);
            aCol = 255;
            // convert int to (32) byte
            r = (byte)(rCol >> 32);
            g = (byte)(gCol >> 32);
            b = (byte)(bCol >> 32);
            a = (byte)(aCol >> 32);
            // window final color
            winCol = new Color4(r, g, b, a);

            // Specify the color for clearing
            GL.ClearColor(winCol);
        }
    }
}

......结果如下: enter image description here

只有一个窗口有颜色。所有其他都变黑了。我感谢任何反馈。

修改 知道了! MakeCurrent救援。 void OpenTK.GLControl.MakeCurrent()
在调用线程中使基础此GLControl当前。发布的所有OpenGL命令此后由此GLControl解释。 以下是代码的更新:

GLControl[] renderCanvas = new GLControl[10];
private int 
    winX, winY, winW, winH, winDist, winNum, win,
    aCol, rCol, gCol, bCol;
Random randNum = new Random();
//byte[] num = new byte[255];
byte r, g, b, a;
Color4 winCol;
private bool winCreated;
private bool eHandlerIs;

TextBox tb = new TextBox();

public Form1()
{
    // required method for designer support
    InitializeComponent();
    initSetup();
}

private void initSetup()
{
    winX = this.Location.X; winY = this.Location.Y;
    winW = this.Width; winH = this.Height;
    rCol = 255; gCol = 255; bCol = 255; aCol = 255;

    // debugging text
    tb.Location = new Point(5, 5);
    tb.Size = new Size(200, 15);
    tb.Name = "textBox1";
    tb.TabIndex = 0;
    tb.BackColor = Color.Black;
    tb.ForeColor = Color.White;
    tb.Text = winNum.ToString();
    this.Controls.Add(this.tb);

    // create windows
    for (int w=0; w<8; w++)
    {
        // window distance 
        winDist += 32;
        // make sure window with index 0 is created
        if (winCreated) { winNum += 1; }

        // create windows 
        this.renderCanvas[w] = new GLControl();
        //this.SuspendLayout();
        this.renderCanvas[w].BackColor = 
            System.Drawing.Color.DeepSkyBlue;
        this.renderCanvas[w].Location =
            new System.Drawing.Point(winX + winDist, winY + winDist);
        this.renderCanvas[w].Name = "renderCanvas" + w;
        this.renderCanvas[w].Size =
            new System.Drawing.Size(winW / 2, winH / 2);
        this.renderCanvas[w].TabIndex = 1;
        this.renderCanvas[w].VSync = false;
        // create event handler 
        this.renderCanvas[w].Load +=
            new System.EventHandler(this.renderCanvas_Load);
        if (!eHandlerIs)
        {
            this.renderCanvas[w].Paint +=
                new System.Windows.Forms.PaintEventHandler(
                    this.renderCanvas_Paint);
            //eHandlerIs = true;
        }
        //this.ResumeLayout(false);

        // add specified control to the control collection 
        this.Controls.Add(this.renderCanvas[w]);
        winCreated = true; // first window created
    }
}

private void renderCanvas_Paint(object sender, PaintEventArgs e)
{
    tb.Text = r.ToString();
    if (winNum < 7)
    {

    }
    else if (winNum >= 7)
    {
        for (int w = 0; w < 8; w++)
        {
            for (int n = 0; n < 8; n++)
            {
                if (w != n)
                {
                    if (renderCanvas[n].Created &&
                        renderCanvas[n].Context.IsCurrent)
                    { renderCanvas[n].Context.MakeCurrent(null); }
                }
            }

            if (renderCanvas[w].Context.IsCurrent == false)
            { renderCanvas[w].MakeCurrent(); }

            GL.Viewport(
            renderCanvas[w].Location.X,
            renderCanvas[w].Location.Y, Width, Height);

            // Clear the render canvas with the current color
            GL.Clear(
                ClearBufferMask.ColorBufferBit |
                ClearBufferMask.DepthBufferBit);

            GL.Flush();
            renderCanvas[w].SwapBuffers();
        }
    }
}

private void renderCanvas_Load(object sender, EventArgs e)
{
    // randomize color (min & max int)
    rCol = randNum.Next(100, 255);
    gCol = randNum.Next(100, 255);
    bCol = randNum.Next(100, 255);
    aCol = 255;
    // convert int to (32) byte
    r = (byte)(rCol >> 32);
    g = (byte)(gCol >> 32);
    b = (byte)(bCol >> 32);
    a = (byte)(aCol >> 32);
    // window final color
    winCol = new Color4(r, g, b, a);

    for (int n = 0; n < 8; n++)
    {
        if (win != n)
        {
            if (renderCanvas[n].Created && 
                renderCanvas[n].Context.IsCurrent)
            { renderCanvas[n].Context.MakeCurrent(null); }
        }
    }

    if (renderCanvas[win].Context.IsCurrent == false)
    { renderCanvas[win].MakeCurrent(); }

    // Specify the color for clearing
    GL.ClearColor(winCol);
    win += 1;
}

......结果: enter image description here