Basically, I am trying to create a glControl window on Widows Forms at realtime. I'm doing this because I will be using multiple windows, and more likely readjusting their position, and I don't want to be doing this manually.
I don't understand why my code doesn't work. Here it is:
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);
}
}
}
I'm just seeing the windows form. The glControl window doesn't show. However, when I add the glControl to the form manually, and add this code:
//____________________________________________
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 window shows up on the form.
The code in my program is no different to the code in the designer, so I am completely puzzled.
This is the designer code:
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);
I tried something by creating another glControl, but this time, not in the Load event handler of the Form.
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);
}
... and it worked. I don't know why that is. It also caused the manually created glControl window to change to black - in it's original location, or white - if moved. However, at least I got results. I'll continue to play with it and see what I can figure out. I have a feeling it may be buffer related. The other option I have is to create the windows manually, and adjust their position and size by code, since that also works. I still would welcome any input on why the code does not work in the Form's Load Event Handler, if anyone knows. Thanks
EDIT I'm making progress. I just have one final step. So now I am using an array of glControls to create my windows, but I didn't want to create multiple event handlers to manage each window, so I am trying to get results with just one Load event and one Paint event. However, I am having trouble with setting the color on all the windows. I'm not sure if this method is possible. I'd really appreciate any help on this. Here is my test code:
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);
}
}
}
Only one window gets a color. All the other turn black. I appreciate any feedback.
EDIT
Got it! MakeCurrent to the rescue.
void OpenTK.GLControl.MakeCurrent ( )
Makes the underlying this GLControl current in the calling thread. All OpenGL commands issued are hereafter interpreted by this GLControl.
Here is an update of the code:
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;
}