How to print the content of a panel with RadPrintPreview? - c#

i want print the content of panel with RadPrintPreview of telerik , but when i declare RadPrintDocument i cant associat this later with panel !
this is my code :
private void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap bmp = new Bitmap(radPanel2.Width, radPanel2.Height, radPanel2.CreateGraphics());
radPanel2.DrawToBitmap(bmp, new Rectangle(0, 0, radPanel2.Width, radPanel2.Height));
RectangleF bounds = e.PageSettings.PrintableArea;
e.Graphics.DrawImage(bmp, bounds.Left, bounds.Top, radPanel2.Width, radPanel2.Height);
}
private void btn_Imression_Click(object sender, EventArgs e)
{
System.Drawing.Printing.PrintDocument doc = new System.Drawing.Printing.PrintDocument();
doc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(doc_PrintPage);
RadPrintPreviewDialog PrintSettings = new RadPrintPreviewDialog();
PrintSettings.Document = doc;
PageSettings pgsetting = new PageSettings();
if (PrintSettings.ShowDialog() == DialogResult.OK)
doc.Print();
}
and thank's for help :)

In order to print Telerik UI for WinForms control, you should use the embedded in the framework functionality, namely RadPrintDocument, which allows you to print any object implementing the IPrintable interface. Here is how this can be done for RadPanel:
RadPanel panel = new RadPanel();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
InitializeComponent();
panel.Dock = DockStyle.Fill;
panel.BackColor = Color.Red;
panel.Parent = this;
RadButton b = new RadButton();
b.Text = "button1";
panel.Controls.Add(b);
RadButton b2 = new RadButton();
b2.Text = "button1";
b2.Location = new Point(400, 400);
panel.Controls.Add(b2);
}
private class PanelPrinter : IPrintable
{
private RadPanel panel;
public PanelPrinter(RadPanel panel)
{
this.panel = panel;
}
public int BeginPrint(RadPrintDocument sender, PrintEventArgs args)
{
return 1;
}
public bool EndPrint(RadPrintDocument sender, PrintEventArgs args)
{
return false;
}
public Form GetSettingsDialog(RadPrintDocument document)
{
return null;
}
public bool PrintPage(int pageNumber, RadPrintDocument sender, PrintPageEventArgs args)
{
float scale = Math.Min((float)args.MarginBounds.Width / panel.Size.Width, (float)args.MarginBounds.Height / panel.Size.Height);
Bitmap panelBmp = new Bitmap(this.panel.Width, this.panel.Height);
this.panel.DrawToBitmap(panelBmp, this.panel.Bounds);
Matrix saveMatrix = args.Graphics.Transform;
args.Graphics.ScaleTransform(scale, scale);
args.Graphics.DrawImage(panelBmp, args.MarginBounds.Location);
args.Graphics.Transform = saveMatrix;
return false;
}
}
private void radButton1_Click(object sender, EventArgs e)
{
RadPrintDocument document = new RadPrintDocument();
document.AssociatedObject = new PanelPrinter(this.panel);
RadPrintPreviewDialog dialog = new RadPrintPreviewDialog(document);
dialog.ShowDialog();
}

Related

Printing out Panel in C#

Again, I am asking a question about a USB Printer. This time however, the issue is more on the programming end of the spectrum.
I have a windows forms application in which I generate a receipt, which is then supposed to be sent to the printer. The Following things work: Generating the receipt, Sending the data to the printer.
The data however is only an empty strip of paper. I have the feeling that the Software is ignoring the Panel contents and just sends the empty panel to the printer.
The Sourcecode is as follows:
namespace MakeyMakey
{
public partial class Form1 : Form
{
public void Gridsettings()
{
GVReceipt.ScrollBars = ScrollBars.None;
GVReceipt.RowHeadersVisible = false;
GVReceipt.ColumnCount = 3;
GVReceipt.Columns[2].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
GVReceipt.CellBorderStyle = DataGridViewCellBorderStyle.None;
}
public Form1()
{
InitializeComponent();
pCompanyImage.SizeMode = PictureBoxSizeMode.StretchImage;
Bitmap Logo = new Bitmap(Bitmap.FromFile(#"C:/Users/manue/source/repos/MakeyMakey/MakeyMakey/logo.png"));
pCompanyImage.Image = MakeBW(Logo);
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode("Hier kann so gut wie alles stehen", QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
Bitmap qrCodeImage = qrCode.GetGraphic(20);
pQRCode.Image = qrCodeImage;
panel1.Height = GVProduct.Height + 220;
GVReceipt.Columns.Add("Name", "Name");
GVReceipt.Columns.Add("QTY", "QTY");
GVReceipt.Columns.Add("Price", "Price");
GVReceipt.Columns[0].Width = 50;
GVReceipt.Columns[1].Width = 15;
GVReceipt.Columns[2].Width = 50;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label4_Click(object sender, EventArgs e)
{
}
private void textBox4_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
string[] row = new string[] {txtName.Text, txtQty.Text, txtPrice.Text };
GVReceipt.Rows.Add(row);
GVProduct.Rows.Add(row);
Gridsettings();
Calc();
txtName.Clear();
txtQty.Clear();
txtPrice.Clear();
txtName.Focus();
}
private void GVResize()
{
//MessageBox.Show(GVReceipt.Height.ToString());
GVReceipt.Height = GVReceipt.ColumnHeadersHeight + GVReceipt.RowCount * GVReceipt.Rows[0].Height;
//MessageBox.Show(GVReceipt.Height.ToString());
panel1.Height += GVReceipt.Rows[0].Height;
//MessageBox.Show(panel1.Height.ToString());
GVReceipt.ClearSelection();
Refresh();
}
private void GVReceipt_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
}
private void GVReceipt_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
{
panel1.Height = 389;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
public Bitmap MakeBW(Bitmap Map)
{
Bitmap newbmp = new Bitmap(Map.Width, Map.Height); // New image
for (int row = 0; row < Map.Width; row++) // Indicates row number
{
for (int column = 0; column < Map.Height; column++) // Indicate column number
{
var colorValue = Map.GetPixel(row, column); // Get the color pixel
var averageValue = ((int)colorValue.R + (int)colorValue.B + (int)colorValue.G) / 3; // get the average for black and white
newbmp.SetPixel(row, column, Color.FromArgb(averageValue, averageValue, averageValue)); // Set the value to new pixel
}
}
return newbmp;
}
public void Calc()
{
decimal total = 0;
for(int i = 0; i < GVReceipt.RowCount-1; i++)
{
total += Convert.ToDecimal(GVReceipt.Rows[i].Cells[2].Value) * Convert.ToDecimal(GVReceipt.Rows[i].Cells[1].Value);
}
//Console.WriteLine("HELLO");
//MessageBox.Show(total.ToString());
lbltotal.Text = total.ToString() + "€";
Refresh();
GVResize();
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Print(panel1);
}
Bitmap MemoryImage;
PrintDocument printdoc1 = new PrintDocument();
PrintPreviewDialog previewdlg = new PrintPreviewDialog();
public void GetPrintArea(Panel pnl)
{
MemoryImage = new Bitmap(pnl.Width, pnl.Height);
Rectangle rect = new Rectangle(0, 0, pnl.Width, pnl.Height);
pnl.DrawToBitmap(MemoryImage, new Rectangle(0, 0, pnl.Width, pnl.Height));
}
public void printdoc1_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawImage(MemoryImage, 0, 0);
}
public void Print(Panel pnl)
{
GetPrintArea(pnl);
printdoc1.PrinterSettings.PrinterName = "Generico";
printdoc1.DefaultPageSettings.PaperSize = new PaperSize("Custom", panel1.Width, panel1.Height);
previewdlg.Document = printdoc1;
previewdlg.ShowDialog();
printdoc1.Print();
}
private void btnPrinter_Click(object sender, EventArgs e)
{
printDocument1.Print();
GVProduct.Rows.Clear();
GVReceipt.Rows.Clear();
Calc();
}
private void GVReceipt_RowsAdded_1(object sender, DataGridViewRowsAddedEventArgs e)
{
//GVResize();
}
}
I have also included two images, one shows what the receipt looks like, the other what the print preview generated.
I'd highy appreciate any help on that topic.

C#, How do i save picture using savefiledialog for paint-like program

I've tried many methods including bitmap converting and etc.
Here's my code. Would love it someone will explain to me how to save it and why. Thanks!
public partial class Form1 : Form
{
Graphics G;
Pen myPen = new Pen(Color.Black);
Point sp = new Point(0, 0);
Point ep = new Point(0, 0);
int ctrl = 0;
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
if(e.Button == MouseButtons.Left)
{
ctrl = 1;
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
ctrl = 0;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(ctrl == 1)
{
ep = e.Location;
G = panel1.CreateGraphics();
G.DrawLine(myPen, sp, ep);
}
sp = ep;
}
private void button1_Click(object sender, EventArgs e)
{
colorDialog1.ShowDialog();
myPen.Color = colorDialog1.Color;
colourBtn.BackColor = colorDialog1.Color;
}
private void clrBtn_Click(object sender, EventArgs e)
{
G.Clear(colorDialog2.Color);
}
private void button1_Click_1(object sender, EventArgs e)
{
colorDialog2.ShowDialog();
panel1.BackColor = colorDialog2.Color;
panel1Colourbtn.BackColor = colorDialog2.Color;
}
private void button1_Click_2(object sender, EventArgs e)
{
SaveFileDialog dlgSave = new SaveFileDialog();
dlgSave.Title = "Save Image";
dlgSave.Filter = "Bitmap Images (*.bmp)|*.bmp|All Files (*.*)|*.*";
if (dlgSave.ShowDialog(this) == DialogResult.OK)
{
using (Bitmap bmp = new Bitmap(panel1.Width, panel1.Height))
{
// how do i save my drawing using savefiledialog?
}
}
}
After you edited your question I suggest to do the following:
create a Bitmap member in your Form with the same dimensions as the panel
create the Graphics G from that bitmap
in your panel1_MouseMove draw on that Graphics (effectivly drawing into the bitmp`
in your panel1_Paint draw that bitmap on the panel and
in your button1_Click_2 save that bitmap:
Code example:
public partial class Form1 : Form
{
Bitmap bmp;
Graphics G;
Pen myPen = new Pen(Color.Black);
Point sp = new Point(0, 0);
Point ep = new Point(0, 0);
int ctrl = 0;
public Form1()
{
InitializeComponent();
// create bitmap
bmp = new Bitmap(panel1.Width, panel1.Height);
// create Graphics
G = Graphics.FromImage(bmp);
G.Clear(Color.Black);
// redraw panel
panel1.Invalidate();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
// draw bitmap on panel
if (bmp != null)
e.Grahics.DrawImage(bmp, Point.Empty);
}
// shortened for clarity
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(ctrl == 1)
{
ep = e.Location;
// draw onto graphics -> bmp
G.DrawLine(myPen, sp, ep);
}
sp = ep;
// redraw panel
panel1.Invalidate();
}
private void button1_Click_2(object sender, EventArgs e)
{
SaveFileDialog dlgSave = new SaveFileDialog();
dlgSave.Title = "Save Image";
dlgSave.Filter = "Bitmap Images (*.bmp)|*.bmp|All Files (*.*)|*.*";
if (dlgSave.ShowDialog(this) == DialogResult.OK)
{
bmp.Save(dlgSave.FileName);
}
}
}
Try this:
panel1.DrawToBitmap(bmp, new Rectangle(0, 0, panel1.Width, panel1.Height));
bmp.Save(dlgSave.FileName);

C# Drawing Lines with TextBox

I have an application where I can add a textBox on the screen and move it.
When I add more than two textBox, I double-click on top of two textbox and a line connects both.
My question is: How to make the line move along with the textBox?
code below:
public partial class principal : Form
{
int posMouseFormX, posMouseFormY;
int posMouseTXT_X, posMouseTXT_Y;
int posActTXT_X, posActTXT_Y;
bool txtPressionado = false;
int qntClick;
Pen myPen = new Pen(System.Drawing.Color.DarkGreen, 1);
Graphics Tela;
List<TextBox> listaNós = new List<TextBox>();
List<Point> origem = new List<Point>();
List<Point> destino = new List<Point>();
Point ponto1, ponto2;
ContextMenuStrip menu;
public principal()
{
InitializeComponent();
menu = new ContextMenuStrip();
menu.Items.Add("Remover");
menu.ItemClicked += new ToolStripItemClickedEventHandler(contextMenuStrip1_ItemClicked);
}
//TextBox event when the mouse moves over the TXT
private void txtMover_MouseMove(object sender, MouseEventArgs e)
{
TextBox textBox = sender as TextBox;
posMouseFormX = textBox.Location.X + e.Location.X;
posMouseFormY = textBox.Location.Y + e.Location.Y;
if (txtPressionado == true) moverTxt(textBox);
}
//Retrieve the X and Y coordinates where clicked within the component.
private void txtMover_MouseDown(object sender, MouseEventArgs e)
{
posMouseTXT_X = e.Location.X;
posMouseTXT_Y = e.Location.Y;
txtPressionado = true;
}
private void txtMover_MouseUp(object sender, MouseEventArgs e)
{
txtPressionado = false;
}
private void moverTxt(TextBox a)
{
a.Location = new System.Drawing.Point(posMouseFormX - posMouseTXT_X, posMouseFormY - posMouseTXT_Y);
posActTXT_X = a.Location.X;
posActTXT_Y = a.Location.Y;
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
}
//insert new TextBox
private void sb_Inserir_No_Click(object sender, EventArgs e)
{
TextBox noFilho = new TextBox();
noFilho = new System.Windows.Forms.TextBox();
noFilho.Location = new System.Drawing.Point(379, 284);
noFilho.Size = new System.Drawing.Size(100, 30);
noFilho.TabIndex = 20;
noFilho.Text = "";
noFilho.BackColor = Color.White;
posActTXT_X = noFilho.Location.X;
posActTXT_Y = noFilho.Location.Y;
this.Controls.Add(noFilho);
noFilho.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
noFilho.DoubleClick += new System.EventHandler(this.textBox1_Click);
noFilho.MouseUp += new System.Windows.Forms.MouseEventHandler(txtMover_MouseUp);
noFilho.MouseDown += new System.Windows.Forms.MouseEventHandler(txtMover_MouseDown);
noFilho.MouseMove += new System.Windows.Forms.MouseEventHandler(txtMover_MouseMove);
noFilho.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
noFilho.ContextMenuStrip = menu;
}
//event to resize the txt on the screen as the content.
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox textBox1 = sender as TextBox;
Size size = TextRenderer.MeasureText(textBox1.Text, textBox1.Font);
textBox1.Width = size.Width + 10;
textBox1.Height = size.Height;
}
//Event to control the connection between two give us when double click on the textbox
private void textBox1_Click(object sender, EventArgs e)
{
TextBox textBox1 = sender as TextBox;
int meio = textBox1.Size.Width / 2;
Tela = CreateGraphics();
qntClick = qntClick + 1;
if (this.qntClick == 1)
{
origem.Add(ponto1);
ponto1 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
}
if (this.qntClick == 2)
{
qntClick = 0;
destino.Add(ponto2);
ponto2 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
DesenhaSeta(Tela, ponto1, ponto2);
}
}
//draw arrow between two TXT
void DesenhaSeta(Graphics Tela, Point x, Point y)
{
myPen.StartCap = LineCap.Triangle;
myPen.EndCap = LineCap.ArrowAnchor;
Tela.DrawLine(myPen, x, y);
}
private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
//recuperando o controle associado com o contextmenu
Control sourceControl = menu.SourceControl;
DialogResult result = MessageBox.Show("Tem Certeza que deseja remover o nó selecionado?", "Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if(result == DialogResult.Yes)
{
sourceControl.Dispose();
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Determine whether the key entered is the F1 key. Display help if it is.
if (e.KeyCode == Keys.Space)
{
TextBox textBox1 = sender as TextBox;
novoNó tela = new novoNó(textBox1.Text);
tela.Show();
}
}
}
Each control, TextBox included has a Move, event. Put an Invalidate() call there!
The lines should be drawn in the Paint event of the container that holds the TextBoxes, probably the Form; if it is the Form indeed call this.Invalidate().
Please move the line drawing code out of the DoubleClick event into the Paint event or else the lines will not persist, say minimize/maximize events or other situation, when the system has to redraw the application!
You probably will need to create a data structure to maintain information about which TextBox-pairs need to be connected, maybe a List<Tuple> or a List<someStructure>. This would get filled/modified in the DoubleClick event, then call this.Invalidate() and in the Form.Paint you have a foreach loop over the list of TextBox-pairs..
If you are drawing on the Form do make sure to turn DoubleBuffered on!
Update: To compare the reults here is a minimal example the expects two TextBoxes on a Form:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
this.DoubleBuffered = true;
pairs.Add(new Tuple<Control, Control>(textBox1, textBox2));
}
List<Tuple<Control, Control>> pairs = new List<Tuple<Control, Control>>();
Point mDown = Point.Empty;
private void Form2_Paint(object sender, PaintEventArgs e)
{
foreach (Tuple<Control, Control> cc in pairs)
drawConnection(e.Graphics, cc.Item1, cc.Item2);
}
void drawConnection(Graphics G, Control c1, Control c2)
{
using (Pen pen = new Pen(Color.DeepSkyBlue, 3f) )
{
Point p1 = new Point(c1.Left + c1.Width / 2, c1.Top + c1.Height / 4);
Point p2 = new Point(c2.Left + c2.Width / 2, c2.Top + c2.Height / 4);
G.DrawLine(pen, p1, p2);
}
}
void DragBox_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
void DragBox_MouseMove(object sender, MouseEventArgs e)
{
TextBox tb = sender as TextBox;
if (e.Button == MouseButtons.Left)
{
tb.Location = new Point(e.X + tb.Left - mDown.X, e.Y + tb.Top - mDown.Y);
}
}
void DragBox_MouseUp(object sender, MouseEventArgs e)
{
mDown = Point.Empty;
}
private void DragBox_Move(object sender, EventArgs e)
{
this.Invalidate();
}
}

save picture to bmp

i have this code:
Dictionary<int, Class1> MyDict = new Dictionary<int, Class1>();
i get mouse position
private void panel1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{ Mycl.X1 = e.X;
Mycl.X2 = e.Y;}
private void panel1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
Mycl.X3 = e.X;
Mycl.X4 = e.Y;
MyDict.Add(MyDict.Count + 1, Mycl);
panel1.Invalidate();
Mycl = new Class1();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
if (panel1.BackgroundImage == null)
{
panel1.BackgroundImage = new Bitmap(this.Width, this.Height);
}
Pen MyPen = new Pen(Color.Black);
Graphics G = Graphics.FromImage(panel1.BackgroundImage);
foreach (KeyValuePair<int, Class1> kvp in MyDict)
{
Point pl1 = new Point(MyDict[kvp.Key].X1, MyDict[kvp.Key].X2);
Point pl2 = new Point(MyDict[kvp.Key].X3, MyDict[kvp.Key].X4);
//e.Graphics.DrawLine(MyPen, pl1, pl2);
G.DrawLine(MyPen, pl1, pl2);
}
}
but when I paint this picture, I have a trouble.
When I use e.graphics.drawline() line has drawn
but with G.drawline() there is no line.
In the end, I need to save my picture, but with e.drawline i have a black picture.
Try this out...note the differences and that I also added a MouseMove() handler for panel1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private class Class1
{
public int X1, X2, X3, X4;
}
private Class1 Mycl = new Class1();
private Dictionary<int, Class1> MyDict = new Dictionary<int, Class1>();
private void panel1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Mycl.X1 = e.X;
Mycl.X2 = e.Y;
Mycl.X3 = e.X;
Mycl.X4 = e.Y;
Point pt1 = panel1.PointToScreen(new Point(Mycl.X1, Mycl.X2));
Point pt2 = panel1.PointToScreen(new Point(Mycl.X3, Mycl.X4));
ControlPaint.DrawReversibleLine(pt1, pt2, panel1.BackColor);
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Point pt1 = panel1.PointToScreen(new Point(Mycl.X1, Mycl.X2));
Point pt2 = panel1.PointToScreen(new Point(Mycl.X3, Mycl.X4));
ControlPaint.DrawReversibleLine(pt1, pt2, panel1.BackColor);
Mycl.X3 = e.X;
Mycl.X4 = e.Y;
pt2 = panel1.PointToScreen(new Point(Mycl.X3, Mycl.X4));
ControlPaint.DrawReversibleLine(pt1, pt2, panel1.BackColor);
}
}
private void panel1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Mycl.X3 = e.X;
Mycl.X4 = e.Y;
MyDict.Add(MyDict.Count + 1, Mycl);
panel1.Invalidate();
Mycl = new Class1();
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
using (Pen MyPen = new Pen(Color.Black))
{
foreach (KeyValuePair<int, Class1> kvp in MyDict)
{
Point pl1 = new Point(kvp.Value.X1, kvp.Value.X2);
Point pl2 = new Point(kvp.Value.X3, kvp.Value.X4);
e.Graphics.DrawLine(MyPen, pl1, pl2);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
panel1.DrawToBitmap(bmp, new Rectangle(new Point(0,0), panel1.Size));
bmp.Save(#"C:\Users\Mike\Pictures\SomeImage.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
you need to differentiate between your screen graphics and your bitmap objects graphics ...
here is an example:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Button button1;
private PictureBox pictureBox1;
private Bitmap bmp;
private Point? p1 = null;
public Form1()
{
InitializeComponent();
bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
}
pictureBox1.Image = bmp;
}
private void InitializeComponent()
{
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.button1 = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(0, 23);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(477, 352);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
this.pictureBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown);
this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseMove);
this.pictureBox1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseUp);
//
// button1
//
this.button1.Dock = System.Windows.Forms.DockStyle.Top;
this.button1.Location = new System.Drawing.Point(0, 0);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(477, 23);
this.button1.TabIndex = 1;
this.button1.Text = "write bitmap to file";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.ClientSize = new System.Drawing.Size(477, 375);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Name = "Form1";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
p1 = pictureBox1.PointToClient(MousePosition);
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
Point p2 = pictureBox1.PointToClient(MousePosition);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawLine(Pens.Black, p1.Value, pictureBox1.PointToClient(MousePosition));
}
p1 = null;
pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (p1 != null)
{
e.Graphics.DrawLine(Pens.Black, p1.Value, pictureBox1.PointToClient(MousePosition));
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
var dialog=new SaveFileDialog();
dialog.DefaultExt = "bmp";
dialog.ValidateNames = true;
dialog.Filter = "Bitmap|*.bmp";
dialog.AddExtension = true;
dialog.OverwritePrompt=true;
var result=dialog.ShowDialog(this);
if (result == System.Windows.Forms.DialogResult.OK)
{
using (var fs = dialog.OpenFile())
{
bmp.Save(fs, System.Drawing.Imaging.ImageFormat.Bmp);
}
}
}
}
}
in the example you can see 2 different DrawLine(...) calls ... the one in the paint event handles on screen painting, which is NOT persisted in the bitmap ... the one in mouse up handles the modifications in the bitmap ...

C# unable to use background workers to use a while loop

I'm using a C# form and I essentially want to update a label for every second of the current time. Obviously the UI thread is getting in the way and stuff so I resorted to background workers and I'm sitting here scratching my head trying to update my label every second. I've tried using a while loop in several locations but it won't work. I'm obviously doing something wrong... Any solutions?
Code:
MainForm.Designer.cs:
using System;
namespace alarmClock
{
partial class MainForm
{
System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
public static DateTime now = DateTime.Now;
public static string time = now.ToLongTimeString();
public void setRealHour() {
hour.Text = time[0].ToString() + time[1].ToString();
}
public void setRealMinute() {
minute.Text = time[3].ToString() + time[4].ToString();
}
public void setRealSecond() {
second.Text = time[6].ToString() + time[7].ToString();
}
public void setHourTime() {
setHour.Text = MainForm.setH.ToString();
if(MainForm.setH < 10) {
setHour.Text = "0" + MainForm.setH.ToString();
}
if(MainForm.setH > 24) {
MainForm.setH=0;
setHour.Text = "0" + MainForm.setH.ToString();
}
}
public void setMinuteTime() {
setMinute.Text = MainForm.setM.ToString();
if(MainForm.setM < 10) {
setMinute.Text = "0" + MainForm.setM.ToString();
}
if(MainForm.setM > 60) {
MainForm.setM=0;
setMinute.Text = "0" + MainForm.setM.ToString();
}
}
public void setSecondTime() {
setSecond.Text = MainForm.setS.ToString();
if(MainForm.setS < 10) {
setSecond.Text = "0" + MainForm.setS.ToString();
}
if(MainForm.setS > 60) {
MainForm.setS=0;
setSecond.Text = "0" + MainForm.setS.ToString();
}
}
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.minute = new System.Windows.Forms.Label();
this.hour = new System.Windows.Forms.Label();
this.second = new System.Windows.Forms.Label();
this.checkboxTime = new System.Windows.Forms.CheckedListBox();
this.delTime = new System.Windows.Forms.Button();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.setHour = new System.Windows.Forms.Label();
this.setMinute = new System.Windows.Forms.Label();
this.setSecond = new System.Windows.Forms.Label();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.subHour = new System.Windows.Forms.Button();
this.addHour = new System.Windows.Forms.Button();
this.subMin = new System.Windows.Forms.Button();
this.addMin = new System.Windows.Forms.Button();
this.subSec = new System.Windows.Forms.Button();
this.addSec = new System.Windows.Forms.Button();
this.setTime = new System.Windows.Forms.GroupBox();
this.addTime = new System.Windows.Forms.Button();
this.bgwM = new System.ComponentModel.BackgroundWorker();
this.bgwS = new System.ComponentModel.BackgroundWorker();
this.bgwH = new System.ComponentModel.BackgroundWorker();
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
this.setTime.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1");
this.tableLayoutPanel1.Controls.Add(this.minute, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.hour, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.second, 2, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
//
// minute
//
resources.ApplyResources(this.minute, "minute");
this.minute.ForeColor = System.Drawing.Color.Black;
this.minute.Name = "minute";
//
// hour
//
resources.ApplyResources(this.hour, "hour");
this.hour.ForeColor = System.Drawing.Color.Black;
this.hour.Name = "hour";
//
// second
//
resources.ApplyResources(this.second, "second");
this.second.ForeColor = System.Drawing.Color.Black;
this.second.Name = "second";
//
// checkboxTime
//
this.checkboxTime.BackColor = System.Drawing.Color.Silver;
resources.ApplyResources(this.checkboxTime, "checkboxTime");
this.checkboxTime.ForeColor = System.Drawing.Color.Black;
this.checkboxTime.FormattingEnabled = true;
this.checkboxTime.Items.AddRange(new object[] {
resources.GetString("checkboxTime.Items"),
resources.GetString("checkboxTime.Items1")});
this.checkboxTime.Name = "checkboxTime";
this.checkboxTime.SelectedIndexChanged += new System.EventHandler(this.CheckboxTimeSelectedIndexChanged);
//
// delTime
//
resources.ApplyResources(this.delTime, "delTime");
this.delTime.Name = "delTime";
this.delTime.UseVisualStyleBackColor = true;
this.delTime.Click += new System.EventHandler(this.DelTimeClick);
//
// tableLayoutPanel2
//
resources.ApplyResources(this.tableLayoutPanel2, "tableLayoutPanel2");
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel4, 0, 0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
//
// tableLayoutPanel3
//
resources.ApplyResources(this.tableLayoutPanel3, "tableLayoutPanel3");
this.tableLayoutPanel3.Controls.Add(this.setHour, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.setMinute, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.setSecond, 2, 0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
//
// setHour
//
resources.ApplyResources(this.setHour, "setHour");
this.setHour.ForeColor = System.Drawing.Color.Black;
this.setHour.Name = "setHour";
//
// setMinute
//
resources.ApplyResources(this.setMinute, "setMinute");
this.setMinute.ForeColor = System.Drawing.Color.Black;
this.setMinute.Name = "setMinute";
//
// setSecond
//
resources.ApplyResources(this.setSecond, "setSecond");
this.setSecond.ForeColor = System.Drawing.Color.Black;
this.setSecond.Name = "setSecond";
//
// tableLayoutPanel4
//
resources.ApplyResources(this.tableLayoutPanel4, "tableLayoutPanel4");
this.tableLayoutPanel4.Controls.Add(this.subHour, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.addHour, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.subMin, 2, 0);
this.tableLayoutPanel4.Controls.Add(this.addMin, 3, 0);
this.tableLayoutPanel4.Controls.Add(this.subSec, 4, 0);
this.tableLayoutPanel4.Controls.Add(this.addSec, 5, 0);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
//
// subHour
//
resources.ApplyResources(this.subHour, "subHour");
this.subHour.Name = "subHour";
this.subHour.UseVisualStyleBackColor = true;
this.subHour.Click += new System.EventHandler(this.SubHourClick);
//
// addHour
//
resources.ApplyResources(this.addHour, "addHour");
this.addHour.Name = "addHour";
this.addHour.UseVisualStyleBackColor = true;
this.addHour.Click += new System.EventHandler(this.AddHourClick);
//
// subMin
//
resources.ApplyResources(this.subMin, "subMin");
this.subMin.Name = "subMin";
this.subMin.UseVisualStyleBackColor = true;
this.subMin.Click += new System.EventHandler(this.SubMinClick);
//
// addMin
//
resources.ApplyResources(this.addMin, "addMin");
this.addMin.Name = "addMin";
this.addMin.UseVisualStyleBackColor = true;
this.addMin.Click += new System.EventHandler(this.AddMinClick);
//
// subSec
//
resources.ApplyResources(this.subSec, "subSec");
this.subSec.Name = "subSec";
this.subSec.UseVisualStyleBackColor = true;
this.subSec.Click += new System.EventHandler(this.SubSecClick);
//
// addSec
//
resources.ApplyResources(this.addSec, "addSec");
this.addSec.Name = "addSec";
this.addSec.UseVisualStyleBackColor = true;
this.addSec.Click += new System.EventHandler(this.AddSecClick);
//
// setTime
//
resources.ApplyResources(this.setTime, "setTime");
this.setTime.BackColor = System.Drawing.Color.Silver;
this.setTime.Controls.Add(this.addTime);
this.setTime.Controls.Add(this.tableLayoutPanel2);
this.setTime.Name = "setTime";
this.setTime.TabStop = false;
//
// addTime
//
resources.ApplyResources(this.addTime, "addTime");
this.addTime.Name = "addTime";
this.addTime.UseVisualStyleBackColor = true;
this.addTime.Click += new System.EventHandler(this.AddTimeClick);
//
// bgwM
//
this.bgwM.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BgwMDoWork);
//
// bgwS
//
this.bgwS.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BgwSDoWork);
//
// bgwH
//
this.bgwH.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BgwHDoWork);
//
// MainForm
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.DarkGray;
this.Controls.Add(this.setTime);
this.Controls.Add(this.delTime);
this.Controls.Add(this.checkboxTime);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "MainForm";
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
this.tableLayoutPanel4.ResumeLayout(false);
this.setTime.ResumeLayout(false);
this.setTime.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
private System.ComponentModel.BackgroundWorker bgwH;
private System.ComponentModel.BackgroundWorker bgwS;
private System.ComponentModel.BackgroundWorker bgwM;
System.Windows.Forms.Button addTime;
System.Windows.Forms.GroupBox setTime;
System.Windows.Forms.Button addSec;
System.Windows.Forms.Button subSec;
System.Windows.Forms.Button addMin;
System.Windows.Forms.Button subMin;
System.Windows.Forms.Button addHour;
System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
System.Windows.Forms.Label setSecond;
System.Windows.Forms.Label setMinute;
System.Windows.Forms.Label setHour;
System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
System.Windows.Forms.Button subHour;
System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
System.Windows.Forms.Button delTime;
System.Windows.Forms.CheckedListBox checkboxTime;
System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
System.Windows.Forms.Label second;
System.Windows.Forms.Label hour;
System.Windows.Forms.Label minute;
void BgwHDoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
setRealHour();
}
void BgwMDoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
setRealMinute();
}
void BgwSDoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
setRealSecond();
}
}
}
MainForm.cs:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace alarmClock
{
public partial class MainForm : Form
{
public static int setH = 0;
public static int setM = 0;
public static int setS = 0;
public MainForm()
{
InitializeComponent();
bgwH.RunWorkerAsync();
bgwM.RunWorkerAsync();
bgwS.RunWorkerAsync();
}
void DelTimeClick(object sender, EventArgs e)
{
}
void SubHourClick(object sender, EventArgs e)
{
setH--;
setHourTime();
}
void AddHourClick(object sender, EventArgs e)
{
setH++;
setHourTime();
}
void SubMinClick(object sender, EventArgs e)
{
setM--;
setMinuteTime();
}
void AddMinClick(object sender, EventArgs e)
{
setM++;
setMinuteTime();
}
void SubSecClick(object sender, EventArgs e)
{
setS--;
setSecondTime();
}
void AddSecClick(object sender, EventArgs e)
{
setS++;
setSecondTime();
}
void AddTimeClick(object sender, EventArgs e)
{
}
void CheckboxTimeSelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
As Jeremy noted in the comments, a Timer would be a better choice.
For completeness, if you still wanted to use a BackgroundWorker, due to some other reason, you will need to use BackgroundWorker.ReportProgress() method. Any UI work must be done on the main UI thread. Using a BackgroundWorker you need to use the Reporting event handler to get your callback back on the main Thread.
You need to ensure BackgroundWorker.WorkerReportsProgress is set to TRUE. This is not by default. Then move your label set method into an Event Handler on ProgressChanged

Categories