I want to add some buttons during run time to a existing panel in my form so that I can scroll them by my panel when the number of the buttons increases and they do not fit the form.
I use the this.panel1.Controls.Add(this.button50[number]); but it does not show the button on the panel
How can I show the control on the panel after adding it?
Here is my code:
static int number = 49;
static int size = 163;
public void initialize()
{
this.button50= new System.Windows.Forms.Button[50];
}
public void makeButton()
{
if (number > 0)
{
this.button50[number] = new System.Windows.Forms.Button();
this.button50[number].Font = new System.Drawing.Font("Nazanin"
,12F,System.Drawing.FontStyle.Bold,
System.Drawing.GraphicsUnit.Point, ((byte)(178)));
size = 41 + size;
this.button50[number].Location = new System.Drawing.Point(194, size);
this.button50[number].Name = "buttonPlus"+number;
this.button50[number].Size = new System.Drawing.Size(151, 34);
this.button50[number].TabIndex = 24;
this.button50[number].Text = "انتخاب دستی دروس";
this.button50[number].UseVisualStyleBackColor = true;
this.panel1.Controls.Add(this.button50[number]);
number--;
}
}
//// a part of InitializeComponent() function
//
// panel1
//
this.panel1.Controls.Add(this.button50[number]);
this.panel1.AutoScroll = true;
this.panel1.Controls.Add(this.button10);
this.panel1.Controls.Add(this.button3);
this.panel1.Controls.Add(this.button8);
this.panel1.Controls.Add(this.button9);
this.panel1.Controls.Add(this.button5);
this.panel1.Controls.Add(this.button7);
this.panel1.Controls.Add(this.button6);
this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.button4);
this.panel1.Controls.Add(this.button2);
this.panel1.Controls.Add(this.textBox1);
this.panel1.Controls.Add(this.label1);
this.panel1.Controls.Add(this.bindingNavigator1);
this.panel1.Controls.Add(this.button1);
this.panel1.Controls.Add(this.lable4);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(549, 306);
this.panel1.TabIndex = 0;
Related
I have a tabControl in a Winform application. The user is able to change settings that will impact each tab visually, and I need to get each tabs as images.
I'm trying to understand why/how some controls are updating even if not visible and some other don't.
Is there a way to force an existing UserControl to update/redraw even if not visible so that Control.DrawToBitmap(...) gets a valid image?
I created an example with a Chart and a FlowLayoutPanel to explain what I mean and to make sure I could reproduce the issue I have.
In the example below:
The image created from the FlowLayoutPanel is only correct if it was updated and visible before DrawToBitmap is called.
The image from the Chart is alway up to date even if updated when not visible.
Questions:
How does it work with one control and not the other?
How could I ensure the FlowLayoutPanel has the same behavior as the Chart?
(EDIT) I have tried a few things without success:
Suspend/Resume layout when updating
call Refresh / Update / Invalidate on the layout that do not update as expected
Here is a gif showing that the chart get updated even when not visible but not the FlowLayoutPanel:
Here is the code of this example:
using LiveChartsCore.SkiaSharpView;
using System.Collections.ObjectModel;
namespace WinFormsDrawToBitmapTest
{
public partial class Form1 : Form
{
int legendCount = 1;
ViewModel viewModel;
public Form1()
{
InitializeComponent();
viewModel = new ViewModel();
cartesianChart1.Series = viewModel.Series;
updateLegend(this.flowLayoutPanel1);
}
private async void button1_Click(object sender, EventArgs e)
{
Bitmap bitmap = await Task.Run(() => getImg3());
this.pictureBox1.Image = bitmap;
this.pictureBox1.Invoke((MethodInvoker)delegate
{ this.pictureBox1.Image = bitmap; });
}
private Bitmap getImg3()
{
Bitmap bitmap = new Bitmap(this.cartesianChart1.Width, this.cartesianChart1.Height + this.flowLayoutPanel1.Height);
Bitmap chart = new Bitmap(this.cartesianChart1.Width, this.cartesianChart1.Height);
Bitmap legend = new Bitmap(this.flowLayoutPanel1.Width, this.flowLayoutPanel1.Height);
this.cartesianChart1.Invoke((MethodInvoker)delegate
{
this.cartesianChart1.DrawToBitmap(chart, new Rectangle(new Point(0, 0), this.cartesianChart1.Size));
});
this.flowLayoutPanel1.Invoke((MethodInvoker)delegate
{
this.flowLayoutPanel1.DrawToBitmap(legend, new Rectangle(new Point(0, 0), this.flowLayoutPanel1.Size));
});
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawImage(legend, 0, 0);
g.DrawImage(chart, 0, legend.Height);
}
return bitmap;
}
private void button2_Click(object sender, EventArgs e)
{
Random r = new Random();
viewModel.Data.Add(r.Next(0, 10));
legendCount++;
updateLegend(this.flowLayoutPanel1);
}
private void updateLegend(FlowLayoutPanel flow)
{
flow.Controls.Clear();
Color[] colorList = new Color[]
{
Color.FromArgb(15, 1, 215),
Color.FromArgb(255, 0, 0),
Color.FromArgb(0, 176, 80),
Color.FromArgb(112, 48, 160)
};
for (int i = 0; i < legendCount; i++)
{
//flow.Controls.Add(new LegendLabel($"Label {i}", colorList[i % colorList.Length]));
Button btn = new Button();
btn.Name = $"Button {i}";
btn.TabIndex = 0;
btn.Text = $"Button {i}";
flow.Controls.Add(btn);
}
}
}
public partial class ViewModel
{
public ObservableCollection<double> Data { get; set; }
public List<LineSeries<double>> Series { get; set; }
public ViewModel()
{
Data = new ObservableCollection<double>();
Data.Add(1); Data.Add(2); Data.Add(5); Data.Add(4);
Series = new List<LineSeries<double>>();
Series.Add(new LineSeries<double> { Values = Data, Fill = null });
}
}
}
With the associated .Designer.cs in case it helps
namespace WinFormsDrawToBitmapTest
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel2 = new System.Windows.Forms.Panel();
this.button2 = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.cartesianChart1 = new LiveChartsCore.SkiaSharpView.WinForms.CartesianChart();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.panel2.SuspendLayout();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// panel2
//
this.panel2.Controls.Add(this.button2);
this.panel2.Controls.Add(this.button1);
this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(1042, 24);
this.panel2.TabIndex = 1;
//
// button2
//
this.button2.Location = new System.Drawing.Point(167, 0);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(86, 23);
this.button2.TabIndex = 1;
this.button2.Text = "Change Tab1";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button1
//
this.button1.Location = new System.Drawing.Point(0, 0);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(161, 23);
this.button1.TabIndex = 0;
this.button1.Text = "Get Tab1 as Image in Tab 2";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location = new System.Drawing.Point(0, 24);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(1042, 585);
this.tabControl1.TabIndex = 2;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.cartesianChart1);
this.tabPage1.Controls.Add(this.flowLayoutPanel1);
this.tabPage1.Location = new System.Drawing.Point(4, 24);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(1034, 557);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "tabPage1";
this.tabPage1.UseVisualStyleBackColor = true;
//
// cartesianChart1
//
this.cartesianChart1.Location = new System.Drawing.Point(8, 116);
this.cartesianChart1.Name = "cartesianChart1";
this.cartesianChart1.Size = new System.Drawing.Size(1018, 435);
this.cartesianChart1.TabIndex = 4;
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.Location = new System.Drawing.Point(8, 6);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(1018, 100);
this.flowLayoutPanel1.TabIndex = 3;
//
// tabPage2
//
this.tabPage2.Controls.Add(this.pictureBox1);
this.tabPage2.Location = new System.Drawing.Point(4, 24);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(1034, 557);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "tabPage2";
this.tabPage2.UseVisualStyleBackColor = true;
//
// pictureBox1
//
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(3, 3);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(1028, 551);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1042, 609);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.panel2);
this.Name = "Form1";
this.Text = "Form1";
this.panel2.ResumeLayout(false);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private Panel panel2;
private Button button1;
private TabControl tabControl1;
private TabPage tabPage1;
private TabPage tabPage2;
private PictureBox pictureBox1;
private FlowLayoutPanel flowLayoutPanel1;
private LiveChartsCore.SkiaSharpView.WinForms.CartesianChart cartesianChart1;
private Button button2;
}
}
Thank you for your help with this.
I am trying to set my panel so it will scroll horizontally. I have tried:
MainPanel.HorizontalScroll.Enabled = true;
MainPanel.HorizontalScroll.Visible = true;
MainPanel.VerticalScroll.Enabled = false;
MainPanel.VerticalScroll.Visible = false;
My MainPanel is a parent to 2 sub Panels that are Horizontaly larger than the Panel itself but the horizontal scroll bar still doesn't appear. How can I fix this?
This is the code in the .Designer.cs file of the Parent Form of my Panels:
this.panel0.Dock = System.Windows.Forms.DockStyle.Top;
this.panel0.Location = new System.Drawing.Point(0, 0);
this.panel0.Name = "panel0";
this.panel0.Size = new System.Drawing.Size(828, 28);
this.panel0.TabIndex = 2;
//
// list
//
this.list.Dock = System.Windows.Forms.DockStyle.Fill;
this.list.Location = new System.Drawing.Point(0, 28);
this.list.Name = "list";
this.list.Size = new System.Drawing.Size(828, 444);
this.list.TabIndex = 3;
//
// MainPanel
//
this.MainPanel.AutoScroll = true;
this.MainPanel.Controls.Add(this.list);
this.MainPanel.Controls.Add(this.panel0);
this.MainPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.MainPanel.Location = new System.Drawing.Point(152, 104);
this.MainPanel.Name = "MainPanel";
this.MainPanel.Size = new System.Drawing.Size(828, 472);
this.MainPanel.TabIndex = 7;
So I'm creating some panels with the following code
private void button1_Click(object sender, EventArgs e)
{
int xlocation = 5;
for (int i = 0; i < 10; i++)
{
Panel panel = new Panel();
{
panel.Name = string.Format("{0}", i);
panel.Text = string.Format(i.ToString());
panel.BackColor = Color.White;
panel.Location = new System.Drawing.Point(xlocation, 30);
panel.Width = flowLayoutPanel1.Width;
panel.Height = 50;
panel.MouseEnter += new System.EventHandler(this.panel_MouseEnter);
flowLayoutPanel1.Controls.Add(panel);
Label label = new Label();
label.Location = new System.Drawing.Point(15, 10);
label.AutoSize = true;
label.Font = new System.Drawing.Font("Calibri", 13F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label.ForeColor = System.Drawing.Color.FromArgb(64, 64, 64);
label.Text = string.Format("{0}", "GNU" + i);
panel.Controls.Add(label);
Label label10 = new Label();
label10.Location = new System.Drawing.Point(15, 35);
label10.AutoSize = true;
label10.Font = new System.Drawing.Font("Calibri", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label10.ForeColor = System.Drawing.Color.FromArgb(64, 64, 64);
label10.Text = string.Format("{0}", "hest");
panel.Controls.Add(label10);
}
xlocation = xlocation + 85;
}
}
The problem is when I resize my form, my flowLayoutPanel obviously gets bigger, but the panels inside doesn't.
I have tried using the
private void Form1_Resize(object sender, EventArgs e)
{
}
But it doesn't seem to work.
Any answer is much appreciated!
Thanks!
You can either use the Anchor property and set it to Right and Left, or can dock each panel to parent control. Something like this should work:
Panel panel = new Panel();
panel.Dock = DockStyle.Top; // Docks the panel to top, and fills to the width of Parent control
panel.Anchor = (AnchorStyles.Right | AnchorStyles.Left); // Set anchor to right and left
I found a solution. I just created a list with my panels like so
List<Panel> pnls = new List<Panel>();
And just did like so to make them follow the width of my flowlayoutpanel, so you can actually use a flowlayoutpanel ;-)
private void Kontrol_Resize(object sender, EventArgs e)
{
for (int i = 0; i < pnls.Count; i++)
{
pnls[i].Width = activityData.Width - 24;
pnls[i].Height = activityData.Height / 4;
}
}
I'm looking for the fastest way to refresh an image (and draw some shapes) on a Winform. I'm using a PictureBox now, but I'm open for suggestions.
The way I'm getting the max FPS possible I took from here: "My last post on render loops (hopefully)"
This is a game loop pattern, but it can also be used to other purpose, like to display live images acquired from a camera.
I'm drawing a red circle in different positions.
As you can see, the FPS drops a lot when a Bitmap is loaded at the PictureBox. Especially in the SizeMode Zoom (the one I want to use).
My PC values for FPS:
Form size (start size)
Bitmap ON: 140 (Zoom); 1000 (Normal); 135 (Stretch); 880 (Auto); 1000 (Center)
Bitmap OFF: 3400 !!
Form size (after Zoom 100% click)
Bitmap ON: 40 (Zoom); 150 (Normal); 65 (Stretch); 150 (Auto); 150 (Center)
Bitmap OFF: 540 !!
Edit 1:
Well, this results was for a 1024x1024 image. But I realizy that the form Height was not getting the right value, I found out that it is because the form size is limited by the Screen resolution. So I've edited the code to load a 800x600 Bitmap. Now the Zoom 100% button works. As you can see, at zoom 100% the FPS is 350, but if you increase the size of the PictureBox one more pixel, the FPS drops to 35, about 10x slower ¬¬ !
The big question is: How can I improve the FPS, specially in zoom mode?
PS: I know WinForm is not the best way to go, I also know WPF. But for now I'm looking the solution using WinForm. Ok? The reason is that I have a big scary project using it. I'm planing to move to WPF, but I'm still learning it. :)
Here is the full code, so you can test it by yourself.
Form1.cs:
//.NET 4.0 Client Profile
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
//You need to add System.Activities.Presentation.dll
using System.Activities.Presentation.Hosting;
namespace WindowsFormsApplication2
{
public enum DrawSource
{
None = 0,
PictureBox = 1,
Grapghics = 2,
}
public partial class Form1 : Form
{
private readonly Timer _updateFPSTimer;
private bool _isIdle;
private Point _location;
private double _updateCount;
private readonly Bitmap _backImage;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = this.ckbDoubleBufferForm.Checked;
this.pictureBox1.DoubleBuffered = this.ckbDoubleBufferPictureBox.Checked;
_backImage = new Bitmap(800, 600, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(_backImage);
int penWidth = 10;
Pen pen = new Pen(Brushes.Blue, penWidth);
g.DrawRectangle(pen, new Rectangle(new Point(penWidth, penWidth), new Size(_backImage.Size.Width - 2 * penWidth, _backImage.Size.Height - 2 * penWidth)));
this.cbxSizeMode.DataSource = Enum.GetValues(typeof(PictureBoxSizeMode));
this.cbxSizeMode.SelectedItem = PictureBoxSizeMode.Zoom;
this.cbxBitmapDrawSource.DataSource = Enum.GetValues(typeof(DrawSource));
this.cbxBitmapDrawSource.SelectedItem = DrawSource.PictureBox;
this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
Application.Idle += Application_Idle;
_updateFPSTimer = new Timer();
_updateFPSTimer.Tick += UpdateFPSTimer_Tick;
_updateFPSTimer.Interval = Convert.ToInt32(1000.0 / 5); //Period in s = 1 s / 5 Hz
_updateFPSTimer.Start();
}
private void Application_Idle(object sender, EventArgs e)
{
while (this.ckbRun.Checked && IsAppStillIdle())
this.pictureBox1.Refresh();
}
void UpdateFPSTimer_Tick(object sender, EventArgs e)
{
GetFPS();
}
private void GetFPS()
{
double fps = _updateCount / (Convert.ToDouble(_updateFPSTimer.Interval) / 1000.0);
_updateCount = 0;
lblFps.Text = fps.ToString("0.00");
}
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
DrawCircle(e.Graphics);
}
private void DrawCircle(Graphics g)
{
if (this.pictureBox1.Image == null && ((DrawSource)this.cbxBitmapDrawSource.SelectedItem == DrawSource.Grapghics))
g.DrawImage(_backImage, 0, 0, g.ClipBounds.Width, g.ClipBounds.Height);
var rect = new Rectangle(_location, new Size(30, 30));
g.DrawEllipse(Pens.Red, rect);
_location.X += 1;
_location.Y += 1;
if (_location.X > g.ClipBounds.Width)
_location.X = 0;
if (_location.Y > g.ClipBounds.Height)
_location.Y = 0;
_updateCount++;
}
/// <summary>
/// Gets if the app still idle.
/// http://blogs.msdn.com/b/tmiller/archive/2005/05/05/415008.aspx
/// </summary>
/// <returns></returns>
private bool IsAppStillIdle()
{
Message msg;
return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
}
#region Unmanaged Get PeekMessage
// http://blogs.msdn.com/b/tmiller/archive/2005/05/05/415008.aspx
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
#endregion
private void btnZoomReset_Click(object sender, EventArgs e)
{
if (_backImage != null)
{
//Any smarter way to do this?
//Note that the maximum Form size is limmited by designe by the Screen resolution.
//Rectangle screenRectangle = RectangleToScreen(this.ClientRectangle);
//int titleHeight = screenRectangle.Top - this.Top;
//Borders
Size border = new Size();
border.Width = this.Width - this.pictureBox1.Width;
border.Height = this.Height - this.pictureBox1.Height;
this.Width = border.Width + _backImage.Width;
this.Height = border.Height + _backImage.Height;
Console.WriteLine("PictureBox size: " + this.pictureBox1.Size.ToString());
}
}
private void SizeMode_SelectedIndexChanged(object sender, EventArgs e)
{
PictureBoxSizeMode mode;
Enum.TryParse<PictureBoxSizeMode>(cbxSizeMode.SelectedValue.ToString(), out mode);
this.pictureBox1.SizeMode = mode;
}
private void DoubleBufferForm_CheckedChanged(object sender, EventArgs e)
{
this.DoubleBuffered = this.ckbDoubleBufferForm.Checked;
}
private void DoubleBufferPictureBox_CheckedChanged(object sender, EventArgs e)
{
this.pictureBox1.DoubleBuffered = this.ckbDoubleBufferPictureBox.Checked;
}
private void BitmapDrawSource_SelectedIndexChanged(object sender, EventArgs e)
{
if ((DrawSource)this.cbxBitmapDrawSource.SelectedItem == DrawSource.PictureBox)
this.pictureBox1.Image = _backImage;
else
this.pictureBox1.Image = null;
}
}
}
Designer.CS:
namespace WindowsFormsApplication2
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.pictureBox1 = new WindowsFormsApplication2.PictureBoxDoubleBuffer();
this.label1 = new System.Windows.Forms.Label();
this.lblFps = new System.Windows.Forms.Label();
this.ckbRun = new System.Windows.Forms.CheckBox();
this.btnZoomReset = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.cbxSizeMode = new System.Windows.Forms.ComboBox();
this.gpbDoubleBuffer = new System.Windows.Forms.GroupBox();
this.ckbDoubleBufferPictureBox = new System.Windows.Forms.CheckBox();
this.ckbDoubleBufferForm = new System.Windows.Forms.CheckBox();
this.cbxBitmapDrawSource = new System.Windows.Forms.ComboBox();
this.label3 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.gpbDoubleBuffer.SuspendLayout();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox1.BackColor = System.Drawing.SystemColors.ControlDarkDark;
this.pictureBox1.DoubleBuffered = true;
this.pictureBox1.Location = new System.Drawing.Point(8, 84);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(347, 215);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.PictureBox1_Paint);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(134, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(30, 13);
this.label1.TabIndex = 3;
this.label1.Text = "FPS:";
//
// lblFps
//
this.lblFps.AutoSize = true;
this.lblFps.Location = new System.Drawing.Point(160, 13);
this.lblFps.Name = "lblFps";
this.lblFps.Size = new System.Drawing.Size(10, 13);
this.lblFps.TabIndex = 4;
this.lblFps.Text = "-";
//
// ckbRun
//
this.ckbRun.Appearance = System.Windows.Forms.Appearance.Button;
this.ckbRun.AutoSize = true;
this.ckbRun.Checked = true;
this.ckbRun.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbRun.Location = new System.Drawing.Point(8, 8);
this.ckbRun.Name = "ckbRun";
this.ckbRun.Size = new System.Drawing.Size(37, 23);
this.ckbRun.TabIndex = 5;
this.ckbRun.Text = "Run";
this.ckbRun.UseVisualStyleBackColor = true;
//
// btnZoomReset
//
this.btnZoomReset.Location = new System.Drawing.Point(51, 8);
this.btnZoomReset.Name = "btnZoomReset";
this.btnZoomReset.Size = new System.Drawing.Size(74, 23);
this.btnZoomReset.TabIndex = 7;
this.btnZoomReset.Text = "Zoom 100%";
this.btnZoomReset.UseVisualStyleBackColor = true;
this.btnZoomReset.Click += new System.EventHandler(this.btnZoomReset_Click);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(5, 37);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(57, 13);
this.label2.TabIndex = 8;
this.label2.Text = "SizeMode:";
//
// cbxSizeMode
//
this.cbxSizeMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbxSizeMode.FormattingEnabled = true;
this.cbxSizeMode.Location = new System.Drawing.Point(73, 34);
this.cbxSizeMode.Name = "cbxSizeMode";
this.cbxSizeMode.Size = new System.Drawing.Size(84, 21);
this.cbxSizeMode.TabIndex = 9;
this.cbxSizeMode.SelectedIndexChanged += new System.EventHandler(this.SizeMode_SelectedIndexChanged);
//
// gpbDoubleBuffer
//
this.gpbDoubleBuffer.Controls.Add(this.ckbDoubleBufferPictureBox);
this.gpbDoubleBuffer.Controls.Add(this.ckbDoubleBufferForm);
this.gpbDoubleBuffer.Location = new System.Drawing.Point(221, 8);
this.gpbDoubleBuffer.Name = "gpbDoubleBuffer";
this.gpbDoubleBuffer.Size = new System.Drawing.Size(99, 65);
this.gpbDoubleBuffer.TabIndex = 10;
this.gpbDoubleBuffer.TabStop = false;
this.gpbDoubleBuffer.Text = "Double Buffer";
//
// ckbDoubleBufferPictureBox
//
this.ckbDoubleBufferPictureBox.AutoSize = true;
this.ckbDoubleBufferPictureBox.Checked = true;
this.ckbDoubleBufferPictureBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbDoubleBufferPictureBox.Location = new System.Drawing.Point(9, 38);
this.ckbDoubleBufferPictureBox.Name = "ckbDoubleBufferPictureBox";
this.ckbDoubleBufferPictureBox.Size = new System.Drawing.Size(77, 17);
this.ckbDoubleBufferPictureBox.TabIndex = 8;
this.ckbDoubleBufferPictureBox.Text = "PictureBox";
this.ckbDoubleBufferPictureBox.UseVisualStyleBackColor = true;
this.ckbDoubleBufferPictureBox.CheckedChanged += new System.EventHandler(this.DoubleBufferPictureBox_CheckedChanged);
//
// ckbDoubleBufferForm
//
this.ckbDoubleBufferForm.AutoSize = true;
this.ckbDoubleBufferForm.Checked = true;
this.ckbDoubleBufferForm.CheckState = System.Windows.Forms.CheckState.Checked;
this.ckbDoubleBufferForm.Location = new System.Drawing.Point(9, 15);
this.ckbDoubleBufferForm.Name = "ckbDoubleBufferForm";
this.ckbDoubleBufferForm.Size = new System.Drawing.Size(49, 17);
this.ckbDoubleBufferForm.TabIndex = 7;
this.ckbDoubleBufferForm.Text = "Form";
this.ckbDoubleBufferForm.UseVisualStyleBackColor = true;
this.ckbDoubleBufferForm.CheckedChanged += new System.EventHandler(this.DoubleBufferForm_CheckedChanged);
//
// cbxBitmapDrawSource
//
this.cbxBitmapDrawSource.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbxBitmapDrawSource.FormattingEnabled = true;
this.cbxBitmapDrawSource.Items.AddRange(new object[] {
"PictureBox",
"Graphics"});
this.cbxBitmapDrawSource.Location = new System.Drawing.Point(73, 57);
this.cbxBitmapDrawSource.Name = "cbxBitmapDrawSource";
this.cbxBitmapDrawSource.Size = new System.Drawing.Size(84, 21);
this.cbxBitmapDrawSource.TabIndex = 12;
this.cbxBitmapDrawSource.SelectedIndexChanged += new System.EventHandler(this.BitmapDrawSource_SelectedIndexChanged);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(5, 60);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(68, 13);
this.label3.TabIndex = 11;
this.label3.Text = "Bitmap draw:";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(361, 304);
this.Controls.Add(this.cbxBitmapDrawSource);
this.Controls.Add(this.label3);
this.Controls.Add(this.gpbDoubleBuffer);
this.Controls.Add(this.cbxSizeMode);
this.Controls.Add(this.label2);
this.Controls.Add(this.btnZoomReset);
this.Controls.Add(this.ckbRun);
this.Controls.Add(this.lblFps);
this.Controls.Add(this.label1);
this.Controls.Add(this.pictureBox1);
this.DoubleBuffered = true;
this.Name = "Form1";
this.Text = "Max FPS tester";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.gpbDoubleBuffer.ResumeLayout(false);
this.gpbDoubleBuffer.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
PictureBoxDoubleBuffer pictureBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label lblFps;
private System.Windows.Forms.CheckBox ckbRun;
private System.Windows.Forms.Button btnZoomReset;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.ComboBox cbxSizeMode;
private System.Windows.Forms.GroupBox gpbDoubleBuffer;
private System.Windows.Forms.CheckBox ckbDoubleBufferPictureBox;
private System.Windows.Forms.CheckBox ckbDoubleBufferForm;
private System.Windows.Forms.ComboBox cbxBitmapDrawSource;
private System.Windows.Forms.Label label3;
}
}
PictureBoxDoubleBuffer.cs:
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public class PictureBoxDoubleBuffer : PictureBox
{
public bool DoubleBuffered
{
get { return base.DoubleBuffered; }
set { base.DoubleBuffered = value; }
}
public PictureBoxDoubleBuffer()
{
base.DoubleBuffered = true;
}
}
}
"The big question is: How can I improve the FPS, specially in zoom mode?"
In Zoom (and Stretch) mode the Image() is probably being resized for each Refresh()...a very expensive operation. You could roll your own "zoom" mode that creates a new image that is already zoomed and assign that instead, leaving the mode at "Normal".
Here's a quick example using a cheat zoom with another PictureBox (obviously you could do the zoom mathematically by computing aspect ratio, etc...but that hurts my brain in the morning):
private void cbxSizeMode_SelectedIndexChanged(object sender, EventArgs e)
{
PictureBoxSizeMode mode;
Enum.TryParse<PictureBoxSizeMode>(cbxSizeMode.SelectedValue.ToString(), out mode);
this.pictureBox1.SizeMode = mode;
if (this.pictureBox1.SizeMode == PictureBoxSizeMode.Zoom)
{
using (PictureBox pb = new PictureBox())
{
pb.Size = pictureBox1.Size;
pb.SizeMode = PictureBoxSizeMode.Zoom;
pb.Image = _backImage;
Bitmap bmp = new Bitmap(pb.Size.Width, pb.Size.Height);
pb.DrawToBitmap(bmp, pb.ClientRectangle);
this.pictureBox1.SizeMode = PictureBoxSizeMode.Normal;
this.pictureBox1.Image = bmp;
}
}
else
{
pictureBox1.Image = _backImage;
}
}
You'll need to call this method when the form first runs if Zoom is the default selection, otherwise it won't have custom zoom image.
Now your Zoom mode should zoom along! (sorry, couldn't resist doing that)
I have included 4 buttons inside a panel. The panel is docked to the main window.
When I resize the main window, it doesn't reposition the 4 buttons with respect to the newly modified window size. I am using VS 2010 Designer view to accomplish this.
Here is the entire code generated from designer.cs
private void InitializeComponent()
{
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
this.TreeDDC = new System.Windows.Forms.TreeView();
this.BtnPointCtrl = new System.Windows.Forms.Button();
this.BtnLogic = new System.Windows.Forms.Button();
this.BtnComm = new System.Windows.Forms.Button();
this.BtnSystem = new System.Windows.Forms.Button();
this.panel1 = new System.Windows.Forms.Panel();
this.statusStrip1.SuspendLayout();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel1});
this.statusStrip1.Location = new System.Drawing.Point(0, 445);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(639, 22);
this.statusStrip1.TabIndex = 0;
this.statusStrip1.Text = "statusBar";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(61, 17);
this.toolStripStatusLabel1.Text = "Status Bar";
//
// TreeDDC
//
this.TreeDDC.Dock = System.Windows.Forms.DockStyle.Left;
this.TreeDDC.Location = new System.Drawing.Point(0, 0);
this.TreeDDC.Name = "TreeDDC";
this.TreeDDC.Size = new System.Drawing.Size(97, 445);
this.TreeDDC.TabIndex = 1;
//
// BtnPointCtrl
//
this.BtnPointCtrl.Location = new System.Drawing.Point(28, 93);
this.BtnPointCtrl.Name = "BtnPointCtrl";
this.BtnPointCtrl.Size = new System.Drawing.Size(202, 86);
this.BtnPointCtrl.TabIndex = 2;
this.BtnPointCtrl.Text = "???";
this.BtnPointCtrl.UseVisualStyleBackColor = true;
//
// BtnLogic
//
this.BtnLogic.Location = new System.Drawing.Point(28, 282);
this.BtnLogic.Name = "BtnLogic";
this.BtnLogic.Size = new System.Drawing.Size(202, 86);
this.BtnLogic.TabIndex = 4;
this.BtnLogic.Text = "??";
this.BtnLogic.UseVisualStyleBackColor = true;
//
// BtnComm
//
this.BtnComm.Location = new System.Drawing.Point(307, 93);
this.BtnComm.Name = "BtnComm";
this.BtnComm.Size = new System.Drawing.Size(202, 86);
this.BtnComm.TabIndex = 3;
this.BtnComm.Text = "??";
this.BtnComm.UseVisualStyleBackColor = true;
//
// BtnSystem
//
this.BtnSystem.Location = new System.Drawing.Point(307, 282);
this.BtnSystem.Name = "BtnSystem";
this.BtnSystem.Size = new System.Drawing.Size(202, 86);
this.BtnSystem.TabIndex = 5;
this.BtnSystem.Text = "???";
this.BtnSystem.UseVisualStyleBackColor = true;
//
// panel1
//
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel1.Controls.Add(this.BtnSystem);
this.panel1.Controls.Add(this.BtnComm);
this.panel1.Controls.Add(this.BtnPointCtrl);
this.panel1.Controls.Add(this.BtnLogic);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(97, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(542, 445);
this.panel1.TabIndex = 6;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(639, 467);
this.Controls.Add(this.panel1);
this.Controls.Add(this.TreeDDC);
this.Controls.Add(this.statusStrip1);
this.Name = "MainForm";
this.Text = "MainForm";
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
But I believe the only code of interest will be the following:
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Controls.Add(this.BtnSystem);
this.panel1.Controls.Add(this.BtnComm);
this.panel1.Controls.Add(this.BtnPointCtrl);
this.panel1.Controls.Add(this.BtnLogic);
Any help will be greatly appreciated.
Use the Anchor property of the buttons...
Read it Working with Anchoring and Docking
The Panel does not itself repositioning the controls when it resizing, Use the Anchor (Top, Bottom, Left, Right) property that the controls reposition when parent Panel resizes...
Or Use TableLayOutPanel.
Docking the panel will only resize the panel iteelf, not reposition the controls within the panel. To have elements within a container change their position after resizing the container, look into the Anchor property. There is also TableLayoutPanel which can, as its name suggests, layout controls in a table format.
Please Dock a FlowLayoutPanel inside your panel and palce the buttons inside that FlowLayoutPanel. Set the Layout Direction property. Now when you resize the main window your buttons will also be resized.