问题是底层窗口PrintDialog
是在执行期间创建的ShowDialog
方法。在调用该方法之前它并不存在,这就是为什么你找不到该窗口。
所以你必须将你的工作注入PrintDialog
里面有把手ShowDialog
。这可以通过以下方式实现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();
}
另一个问题是找到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);