views:

181

answers:

1

I have a program which prints a series of pages, stopping after each page to ask the user to verify they want it printed and insert the paper to printed to. The problem is, in some situations, it goes and prints the item, which pops up a print progress window, and then when that window goes away it tries to return focus to the form. But by that time, the next modal dialog is being shown, and that prevents the original window from being refocused.

Sometimes it even brings a window from the background to cover my original form. It works fine if I don't show any dialogs after printing, but that's not really an option. This only occurs with certain printers.

If anyone else has run into this, how did you fix it?

Sample code:

private void Print(int ItemCount)
{
    for (int i = 0; i < ItemCount; i++)
    {
        MessageBox.Show("Insert paper to print to.");
        using (PrintDocument PrintDoc = new PrintDocument())
        {
            PrintDoc.PrintPage += new PrintPageEventHandler(PrintDoc_PrintPage);
            PrintDoc.Print();
        }
    }
}

void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
{
    e.Graphics.DrawEllipse(Pens.Black, new Rectangle(10, 10, 100, 100));
    e.HasMorePages = false;
}
A: 

I think the solution for you is to query the printer and wait until it is 'Idle' before proceeding to the next page. That way it won't get ahead of itself and display dialogs that cause it to lose focus. Some print drivers display dialogs (like pdf writers) which hang the printout while the code behind keeps going.

PrintDialog pd = new PrintDialog();
pd.ShowDialog();
for (int i = 0; i < ItemCount; i++)
{
MessageBox.Show("Insert paper to print to.");
using (PrintDocument PrintDoc = new PrintDocument())
{
    PrintDoc.PrinterSettings = pd.PrinterSettings;
    PrintDoc.PrintPage += new PrintPageEventHandler(PrintDoc_PrintPage);
    PrintDoc.Print();
}
object status = Convert.ToUInt32(9999);
while ((uint)status != 0) // 0 being idle
{
    ManagementObjectSearcher mos = new ManagementObjectSearcher("select * from Win32_Printer where Name='" + pd.PrinterSettings.PrinterName + "'");
    foreach (ManagementObject service in mos.Get())
    {
    status = service.Properties["PrinterState"].Value;
    Thread.Sleep(50);
    }
}
}

I added the PrintDialog so I could know which printer is being used, that way I can query the state and wait until it is idle again before moving onto the next page. This new code will require:

using Management;
using Threading;
Jack B Nimble
I just saw your answer, and tried putting your code into a test program. Unfortunately I'm having a hard time reproducing the original problem (no access to the physical printer that has the issue), but I'll try to get something up and running. I think I did experimenting with sleep statements, and I don't think any of them had any effect before, so I'm not too hopeful, but I'll at least try it.
Bryce Wagner