获取PrintDialog的模态对话框句柄

kho*_*_89 5 .net c# printing

我在.net 2.0上有一个Windows应用程序.在Form1,我打开一个PrintDialog.如何从我的代码中获取该对话框的句柄?

我已经尝试了很多的Win32函数:EnumWindows,EnumChildWindows,FindWindow,FindWindowEx但它无法找到我的PrintDialog.所有我能找到的只是Form1它的孩子是它的控制.我无法PrintDialog's办理.

我试过的一些代码:

导入win32:

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

调用win32函数:

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
      }
}
Run Code Online (Sandbox Code Playgroud)

我用Spy ++检查过,还有一个PrintDialog窗口.该PrintDialog窗口的父窗口句柄与句柄完全相同Form1's.

有没有人可以帮助我PrintDialog's从父窗口获取句柄?

小智 3

问题是PrintDialog在方法执行期间创建了底层窗口ShowDialog。在调用该方法之前它并不存在,这就是为什么你找不到该窗口。所以你必须将你的工作注入到PrintDialoghandle里面ShowDialog。这可以借助以下Control.BeginInvoke方法来实现:

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();
}
Run Code Online (Sandbox Code Playgroud)

另一个问题是寻找PrintDialog窗口。GetActiveWindow这确实是实现此目的的一种简单方法,因为对话框在运行时应该处于活动状态ShowDialog。更可靠的解决方案可能包括枚举顶级窗口并分析它们的所有者和/或其他道具。这是一种可能的方法,假设打印对话框是表单当前唯一的窗口。TweakPrintDialog前面代码片段中的方法已修改:

    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);
Run Code Online (Sandbox Code Playgroud)