【问题标题】:Get modal dialog handle for PrintDialog获取 PrintDialog 的模式对话框句柄
【发布时间】:2014-03-12 18:08:14
【问题描述】:

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

我尝试了很多win32函数:EnumWindowsEnumChildWindowsFindWindowFindWindowEx,但是找不到我的PrintDialog。我能找到的只是Form1,它的孩子是它的控件。我无法获得PrintDialog's 句柄。

我尝试过的一些代码:

导入win32:

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

调用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
      }
}

我已经检查了 Spy++,仍然有一个 PrintDialog 窗口。 PrintDialog 窗口的父窗口句柄与 Form1's 句柄完全相同。

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

【问题讨论】:

标签: c# .net printing


【解决方案1】:

问题是PrintDialog 的底层窗口是在ShowDialog 方法的执行期间创建的。在此方法调用之前它不存在,这就是您找不到窗口的原因。 所以你必须把你的工作注入到ShowDialog 内的PrintDialog 句柄上。这可以借助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();
}

另一个问题是找到PrintDialog窗口。 GetActiveWindow 确实是实现此目的的一种直接方法,因为当ShowDialog 正在运行时,预计对话框将处于活动状态。 更可靠的解决方案可能包括枚举顶级窗口并分析其所有者和/或其他道具。这是一种可能的方法,假设打印对话框是当前表单拥有的唯一窗口。修改了之前sn-p中的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);

【讨论】:

  • 正是我需要的。在阅读了一些示例后,我知道我在 showdialog 之前找不到对话框,但我不知道如何处理它。你的回答完全解决了我的问题。
  • 在FolderBrowserDialog上试过这个,窗口枚举产生一个项目,它的GetWindow返回一个零。在对话框实际显示之前触发窗口行走。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 1970-01-01
  • 2020-10-15
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多