【问题标题】:Redraw Window Control Synchronously (with blocking method)同步重绘窗口控件(使用阻塞方法)
【发布时间】:2012-12-12 23:35:07
【问题描述】:

我要做的是使控件(在同一进程中,但我无法控制)重绘自身,并让我的代码阻塞,直到它完成重绘

我尝试使用UpdateWindow,但这似乎没有等待重绘完成。

我需要等待它完成重绘的原因是我想在之后抓取屏幕。

该控件不是 dotNet 控件,而是常规的 windows 控件。

我已经确认:

  • 句柄正确。
  • UpdateWindow 返回 true。
  • 尝试在调用 UpdateWindow 之前发送 InvalidateRect(hWnd, IntPtr.Zero, true) 以确保窗口需要失效。
  • 尝试在控件的父窗口上做同样的事情。

使用的代码:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool InvalidateRect(IntPtr hWnd, IntPtr rect, bool bErase);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UpdateWindow(IntPtr hWnd);

public bool PaintWindow(IntPtr hWnd)
{
    InvalidateRect(hWnd, IntPtr.Zero, true);
    return UpdateWindow(hWnd);
}
//returns true

【问题讨论】:

  • 也许你可以在 WM_PAINT 情况下禁用渲染,然后重新启用它。
  • @S.A.Parkhid 你能详细说明一下吗?
  • 嗯.. 为什么你认为 UpdateWindow 似乎没有等待重绘完成

标签: c# winapi gdi invalidation redraw


【解决方案1】:

您可以使用Application.DoEvents 强制应用程序处理所有排队的消息(包括 WM_PAINT!)。像这样的:

public bool PaintWindow(IntPtr hWnd)
{
    InvalidateRect(hWnd, IntPtr.Zero, true);
    if (UpdateWindow(hWnd))
    {
        Application.DoEvents();
        return true;
    }

    return false;
}

但如果你还是要抢屏,发WM_PRINT消息,一石两鸟不是更好吗?

你可以通过下面的代码来实现:

internal static class NativeWinAPI
{
    [Flags]
    internal enum DrawingOptions
    {
        PRF_CHECKVISIBLE = 0x01,
        PRF_NONCLIENT = 0x02,
        PRF_CLIENT = 0x04,
        PRF_ERASEBKGND = 0x08,
        PRF_CHILDREN = 0x10,
        PRF_OWNED = 0x20
    }

    internal const int WM_PRINT = 0x0317;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg,
        IntPtr wParam, IntPtr lParam);
}

public static void TakeScreenshot(IntPtr hwnd, Graphics g)
{
    IntPtr hdc = IntPtr.Zero;
    try
    {
        hdc = g.GetHdc();

        NativeWinAPI.SendMessage(hwnd, NativeWinAPI.WM_PRINT, hdc,
            new IntPtr((int)(
                NativeWinAPI.DrawingOptions.PRF_CHILDREN |
                NativeWinAPI.DrawingOptions.PRF_CLIENT |
                NativeWinAPI.DrawingOptions.PRF_NONCLIENT |
                NativeWinAPI.DrawingOptions.PRF_OWNED
                ))
            );
    }
    finally
    {
        if (hdc != IntPtr.Zero)
            g.ReleaseHdc(hdc);
    }
}

【讨论】:

  • 谢谢,我会试一试,让你知道。
  • 明天才能测试,我会尽快更新。
  • Application.DoEvents 工作,WM_PRINT 不幸的是没有。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 2012-10-12
  • 1970-01-01
相关资源
最近更新 更多