How to close a Print Preview Dialog? - c#

I have a document printing function. I am trying to close the Print Preview Dialog form after the user presses the Print button. Once the print button in the print preview dialog is pressed, the event starts the function below to print the document. I am expecting the form to close when I call printPreviewDialog1.Close() but it just goes over the line and nothing happens.
But it doesn't close the print preview dialog form after the print job is done.
public void _start_Print(object sender, EventArgs e)
{
printDocument1.Print();
}
Added as requested in the comments. Initializing Print Preview Dialog
private void btnPrint_Click(object sender, EventArgs e)
{
PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog();
printPreviewDialog1.Document = printDocument1;
ToolStrip ts = new ToolStrip();
ts.Name = "wrongToolStrip";
foreach (Control ctl in printPreviewDialog1.Controls)
{
if (ctl.Name.Equals("toolStrip1"))
{
ts = ctl as ToolStrip;
break;
}
}
ToolStripButton printButton = new ToolStripButton();
ToolStripButton closeButton = new ToolStripButton();
foreach (ToolStripItem tsi in ts.Items)
{
if (tsi.Name.Equals("printToolStripButton"))
{
printButton = tsi as ToolStripButton;
}
else if (tsi.Name.Equals("closeToolStripButton")) // idk if this is the name of the close button im trying to programmatically close it after printing
{
closeButton = tsi as ToolStripButton;
}
}
ts.Items.Remove(printButton);
ToolStripButton b = new ToolStripButton();
b.ImageIndex = printButton.ImageIndex;
b.Visible = true;
ts.Items.Insert(0, b);
b.Click += new EventHandler(this._start_Print);
printPreviewDialog1.WindowState = FormWindowState.Maximized;
printPreviewDialog1.ShowDialog();
printPreviewDialog1.Dispose(); //< doesnt do anything
closeButton.PerformClick(); // < doesn't do anything, possibly using wrong name for toolstripbutton
}
Initializing Print Document as requested in the comments
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawRectange(Pens.Black, 60, 60, 60,60);
}

Solved.
I created a Global ToolStripButton and initialized this button with the closeToolStripButton in the printPreviewDialog.
Then I programmatically clicked this button after the print job was done.
private ToolStripButton closeButton = new ToolStripButton(); <-- global variable
private void btnPrint_Click(object sender, EventArgs e)
{
foreach (ToolStripItem tsi in ts.Items)
{
if (tsi.Name.Equals("closeToolStripButton"))
{
closeButton = tsi as ToolStripButton;
}
else if (tsi.Name.Equals("printToolStripButton"))
{
printButton = tsi as ToolStripButton;
}
}
ts.Items.Remove(printButton);
ToolStripButton b = new ToolStripButton();
b.ImageIndex = printButton.ImageIndex;
b.Visible = true;
ts.Items.Insert(0, b);
b.Click += new EventHandler(this._start_Printer); //<-- this starts the printer event where i "PerformClick() on the initialized closeButton"
printprevDialog.WindowState = FormWindowState.Maximized;
printprevDialog.ShowDialog();
}
public void _start_Printer(object sender, EventArgs e) // <--- then i just performed the close click here right after i hit the print button
{
printDocument1.Print();
closeButton.PerformClick(); // <-- this way im not violating cross thread operations
}

Related

programmatically button triggering?

So I'm trying to make a button to so that when it is clicked, the button will turn transparrent, and a game in the background will begin. I'm new and don't know what i'm doing, but here is my code:
public Form1()
{
//Just ignore all this
InitializeComponent();
Label[] labelArray = { label1, label2, label3, label4, label5,
label6, label7, label8, label9 };
for (int i = 0; i < labelArray.Length; i++)
{
labelArray[i].BackColor = System.Drawing.Color.Transparent;
}
//Button details...
Button buttonStart = new Button();
buttonStart.Location = new Point(90, 150);
buttonStart.Text = ("Click start to begin");
buttonStart.Size = new Size(150, 50);
//Adding the evnet handler
buttonStart.Click += new EventHandler(buttonStart_Click);
//Adding the button to the form
this.Controls.Add(buttonStart);
buttonStart.BringToFront();
//Clicking it, in the hopes that what in (buttonStart_Click event
//handler would do something)
buttonStart.PerformClick();
}
//Eventhandler that says it cannot recoqnize
//my "buttonStart", and I cannot seem to find any other way to do this
private void buttonStart_Click(object sender, EventArgs e)
{
buttonStart.BackColor = System.Drawing.Color.Transparent;
}
try this:
private void buttonStart_Click(object sender, EventArgs e)
{
this.buttonStart.visible = false;
}

Prevent printing blank pages

I just need to reset "border" after print previewing. I preview the page I wantted to print correctly but when I do printing it gives blank pages because "border" wasnt reset. Where should I put "border=0"?("border" is no. rows in a datagridview)
private void button5_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
PrintPreviewDialog ppd = new PrintPreviewDialog();
ppd.Document = pd;
ppd.ShowDialog();
}
private void pd_PrintPage(object sender, PrintPageEventArgs e)
{
prntt(sender, e);
}
public void prntt(object sender, PrintPageEventArgs e)
{
for (; border < ViewA.RowCount; border++)
{
if (ustsin + yuk > e.MarginBounds.Bottom - 400f)
{
e.HasMorePages = true;
return;
}
texts = ViewA.Rows[border].Cells["Persons"].Value.ToString();
...
graphics.DrawString(texts, font, Brushes.Black, new RectangleF(e.MarginBounds.Left, ustsin, 115f, 90f));
...
float hoho = (float)e.Graphics.MeasureString(texts, font, 115, StringFormat.GenericTypographic).Height;
...
var mesele = new float[] { hoho, koko, moko };
float kapa = mesele.OrderByDescending(s => s).First();
ustsin += kapa + yuk;
}
e.HasMorePages = false;
}
if I can close when we press the print button in print preview, can I reset in its closing event?
edit: I did this, it seems to work but when I send it to xps, it shows 2 pages in the screen. like this http://i.imgur.com/a9KnkA0.png . How can I make this show 1 page?
private void printDocument1_EndPrint(object sender, PrintEventArgs e)
{
border = 0;
}
initially set it to 0 and reset it after ppd.ShowDialog();
ppd.ShowDialog();
border = 0;
UPDATE
Looks like PrintPreviewDialog doesn't support much as you (and many others expect), it's up to the user (not to programmer). You can try this a little hacky stuff:
//code in your button5_Click
ToolStripButton onePageButton = ((ToolStrip)ppd.Controls[1]).Items[3] as ToolStripButton;
BeginInvoke((Action)(() => onePageButton.PerformClick()));
ppd.ShowDialog();
UPDATE
To intercept the Clicking on the Print button, you have to add a little much more code. You have to detect the click before the Click is fired on the item (print button), show the message box asking for confirmation and re-click the item if user agrees. Here is the code for you:
//Use this class to add message interceptor into your ToolStrip message loop
public class NativeToolStrip : NativeWindow {
ToolStrip ts;
bool letClicked;
protected override void OnHandleChange() {
base.OnHandleChange();
Control c = Control.FromHandle(Handle);
ts = c as ToolStrip;
}
protected override void WndProc(ref Message m) {
if (m.Msg == 0x202&&!letClicked) {//WM_LBUTTONUP = 0x202
int x = m.LParam.ToInt32() & 0x00ff;
int y = m.LParam.ToInt32() >> 16;
ToolStripItem item = ts.GetItemAt(new Point(x, y));
//check if the first item (the Print Button) is clicked
if (item != null && ts.Items.IndexOf(item) == 0) {
if (MessageBox.Show("Do you want to print?", "Print confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
return;//discard message
else {
letClicked = true;
item.PerformClick();
}
}
}
base.WndProc(ref m);
if (letClicked) letClicked = false;
}
}
//This code should be done somewhere like in your form constructor
//BUT your PrintPreviewDialog should also be declared once in the form scope
//You can also place this in your button5_Click BUT it's not recommended
ToolStrip ts = (ToolStrip)ppd.Controls[1];
new NativeToolStrip().AssignHandle(ts.Handle);

Button text bold on click

I made a quiz game and I want the text on the button to be bold when clicked. This code works:
button7.Font = new Font(button7.Font.Name, button7.Font.Size, FontStyle.Bold);
The problem I'm having is when I click on the 'Next' button to go to the next question, the text is still bold even though the answer hasn't been clicked. How do I solve this?
Just do this on "Next" button click
button7.Font = new Font(button7.Font.Name, button7.Font.Size, FontStyle.Regular);
You need to un-bold everything when you click Next. The code below should help (it also includes a possibly cleaner bolding implementation).
// usage
foreach(var button in GetAnswerButtons())
{
button.Click += OnClickToBold;
button.Click += OnClickSetPropertyBasedOnCorrectness;
}
nextButton.Click += NextClick;
// implementations
private void OnClickToBold(object sender, EventArgs e)
{
var button = sender as Button;
if (button == null) return;
button.Font = new Font(button.Font.Name, button.Font.Size, FontStyle.Bold);
}
private void OnClickSetPropertyBasedOnCorrectness(object sender, EventArgs e)
{
var button = sender as Button;
if (button == null) return;
button.WhateverProperty = IsCorrectAnswer(button)
? valueWhenCorrect
: valueWhenWrong;
}
private void NextClick(object sender, EventArgs e)
{
foreach(var button in GetAnswerButtons())
{
button.Font = new Font(button.Font.Name, button.Font.Size, FontStyle.Regular);
UnsetPropertyBasedOnCorrectness(button);
}
}
private IEnumerable<Button> GetAnswerButtons() { ... }
private void UnsetPropertyBasedOnCorrectness(Button b) { ... }

C# print preview gets closed when you close another form

I'm showing a print preview window for some large pages. The rendering of these takes some time so I want to show more progress information than the default 'Page 1/1' message.
I created a simple windows form project that shows my current approach:
(you can create a new windows form project with two forms and copy paste if you like)
public event EventHandler PrintReady;
public event ProgressChangedEventHandler ProgressChanged;
private void button1_Click(object sender, EventArgs e)
{
var printDocument = new PrintDocument();
printDocument.PrintPage += new PrintPageEventHandler(printDocument_PrintPage);
printDocument.EndPrint += new PrintEventHandler(printDocument_EndPrint);
var printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = printDocument;
// Create the 'progress' form.
var form2 = new Form2(this);
form2.Show();
printPreviewDialog.ShowDialog();
}
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
for (int i = 0; i < 100; i++)
{
// This is where I do some rendering.
Thread.Sleep(20);
if (this.ProgressChanged != null)
{
this.ProgressChanged.Invoke(this, new ProgressChangedEventArgs(i, null));
}
}
}
void printDocument_EndPrint(object sender, PrintEventArgs e)
{
if (this.PrintReady != null)
{
this.PrintReady.Invoke(this, null);
}
}
And then off course my progress form:
public Form2(Form1 form1)
{
form1.ProgressChanged += new ProgressChangedEventHandler(ProgressChangedHandler);
form1.PrintReady += new EventHandler(PrintReadyHandler);
InitializeComponent();
}
void PrintReadyHandler(object sender, EventArgs e)
{
this.Close();
}
void ProgressChangedHandler(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
The 'this.Close()' also closes my print preview! If I remove that line then the print preview is just shown and stays open. So the Close() function is closing both the progress window and the PrintPreview window.
Why is this happening?
I think you need to specify the owner of the Print Preview dialog as form1 - see below:
printPreviewDialog.ShowDialog(this);

Windows Forms right-click menu for multiple controls

I have several controls in a Windows Form and I want an identical menu to popup on each when right-clicked. However, the action should vary slightly based on which control was clicked.
The problem I'm having is that the ToolStripMenuItem doesn't have any information about which control was originally clicked to make the tool strip visible. I really don't want to need a separate context menu for each control!
Thus far my code looks something like:
private void InitializeComponent()
{
this.openMenuItem = new ToolStripMenuItem();
this.openMenuItem.Text = "Open";
this.openMenuItem.Click += new EventHandler(this.openMenuItemClick);
this.runMenuItem = new ToolStripMenuItem();
this.runMenuItem.Text = "Run";
this.runMenuItem.Click += new EventHandler(this.runMenuItemClick);
this.contextMenuStrip = new ContextMenuStrip(this.components);
this.contextMenuStrip.Items.AddRange(new ToolStripMenuItem[]{
this.openMenuItem,
this.runMenuItem});
this.option1 = new Label();
this.option1.Click += new EventHandler(this.optionClick);
this.option2 = new Label();
this.option2.Click += new EventHandler(this.optionClick);
}
void optionClick(object sender, EventArgs e)
{
MouseEventArgs mea = e as MouseEventArgs;
Control clicked = sender as Control;
if(mea==null || clicked==null) return;
if(mea.Button == MouseButtons.Right){
this.contextMenuStrip.Show(clicked, mea.Location);
}
}
void openMenuItemClick(object sender, EventArgs e)
{
//Open stuff for option1 or option2, depending on which was right-clicked.
}
void runMenuItemClick(object sender, EventArgs e)
{
//Run stuff for option1 or option2, depending on which was right-clicked.
}
Within runMenuItemClick you need to cast then sender to a ToolStripMenuItem and then cast its owner to a ContextMenuStrip. From there you can look at the ContextMenuStrip's SourceControl property to get the name of the control that clicked the item.
void runMenuItemClick(object sender, EventArgs e) {
var tsItem = ( ToolStripMenuItem ) sender;
var cms = ( ContextMenuStrip ) tsItem.Owner;
Console.WriteLine ( cms.SourceControl.Name );
}

Categories