Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get modal dialog handle for PrintDialog

Tags:

c#

.net

printing

I have an windows app on .net 2.0. On Form1, I open a PrintDialog. How can I get that dialog's handle from my code?

I have tried a lot of win32 functions: EnumWindows, EnumChildWindows, FindWindow, FindWindowEx but it cannot find my PrintDialog. All I can find is just Form1 and its children are controls on it. There's no way I can get PrintDialog's handle.

Some code that i have tried:

Import win32:

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

calling win32 functions:

using (PrintDialog dlg = new PrintDialog
                                 {
                                     AllowCurrentPage = false,
                                     AllowSomePages = true,
                                     AllowSelection = false
                                 })
{    
      IntPtr printHandle = CustomPrintDialog.FindWindow("#32770", "Print");
      // some logic with printHandle go here
      if (dlg.ShowDialog(this)==DialogResult.OK){
          // some logic go here
      }
}

I have checked with Spy++, there is still a PrintDialog window. That PrintDialog window has Parent Window's handle exactly same as Form1's handle.

Does anyone can help me to get a PrintDialog's handle from its parent window?

like image 673
khoa_chung_89 Avatar asked Oct 21 '22 12:10

khoa_chung_89


1 Answers

The problem is that underlying window for the PrintDialog is created during the execution of the ShowDialog method. It does not exist before this method's invocation, that's why you cannot find the window. So you must inject your work on PrintDialog handle inside ShowDialog. This can be achieved with the help of Control.BeginInvoke method:

public partial class Form1 : Form
{
    ...

    private ShowPrintDialog()
    {
        using (var pd = new PrintDialog())
        {
            BeginInvoke(new MethodInvoker(TweakPrintDialog));
            if (pd.ShowDialog(this) == DialogResult.OK)
            {
                // printing
            }
        }
    }

    private void TweakPrintDialog()
    {
        var printDialogHandle = GetActiveWindow();
        // do your tweaking here
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr GetActiveWindow();
}

Another problem is to find PrintDialog window. GetActiveWindow is really a straightforward way to accomplish this, because the dialog is expected to be active while ShowDialog is in action. The more reliable solution may include enumerating top-level windows and analyzing their owners and/or other props. Here is one possible approach, assuming that print dialog is the only window at the moment that is owned by the form. The TweakPrintDialog method from the previous snippet is modified:

    private void TweakPrintDialog()
    {
        uint processId;
        var threadId = GetWindowThreadProcessId(this.Handle, out processId);
        EnumThreadWindows(threadId, FindPrintDialog, IntPtr.Zero);
        // printDialogHandle field now contains the found handle
        // do your tweaking here
    }

    private IntPtr printDialogHandle;

    private bool FindPrintDialog(IntPtr handle, IntPtr lParam)
    {
        if (GetWindow(handle, GW_OWNER) == this.Handle)
        {
            printDialogHandle = handle;
            return false;
        }
        else
        {
            return true;
        }
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    private delegate bool EnumWindowProc(IntPtr handle, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool EnumThreadWindows(uint threadId, EnumWindowProc enumProc, IntPtr lParam);

    private const uint GW_OWNER = 4;

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr GetWindow(IntPtr handle, uint cmd);
like image 117
baSSiLL Avatar answered Oct 23 '22 05:10

baSSiLL