2010-08-19 95 views
1

在WPF應用程序(C#)中,其中一個元素是通過覆蓋HwndHost類創建的Win32窗口。在任何時候,WPF中都有大約10個Win32窗口實例。一個應該完全渲染(工作正常),另外9個應該只顯示預覽,而不創建Win32窗口,只是一個位圖。將Win32窗口繪製到文件

我一直在想方設法生成所說的位圖。嘗試了很多不同的東西,但到目前爲止還沒有真正起作用。我遇到的主要問題是HwndHost.WndProc僅在窗口可見時調用。

我可以截取一個可見的窗口,將其渲染到內存並創建一個位圖罰款..我只需要一些這樣做,而窗口不可見的方式。

我的理解還是比較模糊的,所以任何見解都是值得讚賞的。

+0

你是說只有當窗口在屏幕上可見時或僅在窗口至少在屏幕上顯示一次後才調用HwndHost.WndProc?窗口句柄可能只有在第一次顯示窗口時纔會創建。如果窗口(或其父窗口)在顯示後隱藏或最小化,則仍然應該在wndproc中獲取消息。 – dthorpe 2010-08-19 18:37:21

+0

直到第一次在屏幕上顯示窗口。在顯示之前是否可以將此窗口繪製到內存中? 或者,也許一種解決方法是在新窗口中產生, Show(); Hide(); 然後嘗試畫? – mkocubinski 2010-08-19 18:48:15

+0

請在標籤中留下「C#」等標籤,並將它們放在標題外面。這是多餘的。 – 2010-08-19 19:34:43

回答

4

您可以通過模擬WM_PAINT消息強制窗口繪製位圖。你將需要設置一個內存DC並選擇你的目標位圖,然後將這個DC句柄作爲參數傳遞給paint消息。有關詳細信息,請參閱MSDN docs

一旦參數都準備好滾動,請執行SendMessage(HwndHost.Handle,WM_PAINT等)。當該調用返回時,位圖應包含窗口的圖像。

請注意,有很多消息需要完全繪製整個窗口。一般模式是:

  1. 使窗口的整個客戶區失效。否則,由於剪輯矩形將爲空,因此不會繪製任何內容。
  2. 設置你的內存位圖的內存DC
  3. 發送WM_ERASEBKGND消息的窗口句柄,傳遞內存DC處理
  4. 發送WM_PAINT消息的窗口句柄,傳遞內存DC處理

窗口的圖像現在應該位於內存位圖中。

如果您還想要捕獲目標窗口的邊框,窗口框架和窗口標題,則需要模擬非客戶端繪製消息:WM_NCPAINT是主要的,不在我頭頂。

還有一個WM_PRINT消息,據說有助於繪製到打印的內存DC中,但是我在使用Windows之前的幾個版本時遇到了麻煩。子控件不畫自己,等

+0

謝謝,這是我昨晚開始去的方向。現在閱讀,這更加清晰。非常詳細,非常感謝! – mkocubinski 2010-08-20 16:12:20

0

我不知道這是如何工作在C#與WPF ,所以我只會給你Windows API的觀點,並希望它能引導你找到一個解決方案。

所有繪圖都是通過Device Context(DC)完成的。當Windows要求您繪製一個窗口時,它還使您可以訪問與窗口的可繪製表面相對應的DC。

要在沒有窗口的情況下進行繪製,您需要創建自己的DC,並且由於這些位不會進入窗口,因此需要在DC中選擇一個位圖來保存結果。在Windows API中,您將使用CreateCompatibleDCSelectObject。一旦你有了一個DC,你就可以像往常一樣繪製它,然後取消選擇該位圖。