2009-12-10 118 views
4

我想創建一個面板的圖像並將其保存到一個文件夾。問題在於面板上有滾動條,生成的圖像僅用於面板的可見部分。C#Windows窗體控制圖像?

我使用的代碼就像Panel.DrawToImage。在這裏可以有任何幫助將整個面板保存爲圖片而不僅僅是可見部分嗎?

回答

2

這裏沒有快樂的答案,DrawToBitmap只能繪製對用戶可見的內容。諸如改變面板的位置和尺寸之類的技巧通常由於父母對控制尺寸的限制而迅速耗盡。窗體本身永遠不會比屏幕大,現在您還將依賴目標機器上視頻適配器的分辨率。

一個醜陋的黑客是多次運行DrawToBitmap,更改每次調用之間Panel的AutoScrollPosition屬性。你必須把結果圖像拼接在一起。當然要特別注意最後一個,因爲它不會像其他的那麼大。

一旦你開始考慮這樣的代碼,你真的應該考慮PrintDocument或報告生成器。一個好處是,打印輸出將看起來像一個heckofalot清潔劑。由於視頻和打印機分辨率的巨大差異,打印的屏幕截圖總是很​​難看。

+0

謝謝!這似乎是目前唯一的方法!雖然有點工作!再次感謝!! – Shri 2009-12-10 22:21:44

+0

嘿傢伙只是在這個更新.... 一個解決方法是在內存中創建相同的控制,以及定義自定義高度和寬度,然後調用DrawToBitmap函數! 是一個甜蜜的成功!希望這可以幫助別人! – Shri 2009-12-11 06:39:42

+1

用於PrintDocument – hometoast 2009-12-11 14:44:06

0

嗯...聽起來像(你在原始問題中沒有這麼說),但是你有一個圖框作爲面板容器內的容器,即嵌套容器嗎?

你有沒有考慮這樣做:

 
// Assume pic is the type of PictureBox and the image property is assigned 
PictureBox pic; 

// And that the picturebox is embedded in the Panel variable p. 
p.Controls.Add(pic); 

// ... 

// So why not do this? 
pic.Image.Save(...); 

Image類的Save方法有5個重載所以選擇一個在您方便的。

希望這會有所幫助, 最好的問候, 湯姆。

+2

我想他想在屏幕上「截取」一個容器控件。 – hometoast 2009-12-10 14:36:49

+0

@hometoast:哦...現在我明白了......呃...... Alt + PrtScrn怎麼樣,並將其粘貼到mspaint中?或者其他一些屏幕抓取工具?總之,答案是否定的,因爲無論圖像是否被裁剪,屏幕捕捉的內容都不存在! – t0mm13b 2009-12-10 14:45:58

1

考慮暫時提高面板的尺寸,要求p.Layout(),然後p.DrawToImage()

+0

控制大於屏幕的顯示大小。所以滾動條是不可能擺脫! – Shri 2009-12-10 22:20:01

1

也許你可以在需要的尺寸克隆控制到另一個(隱藏)的形式(這樣滾動條沒有顯示),並打電話給你的DrawToImage()函數?

4

我認爲WM_PRINT消息會有幫助。這裏有一個差不多的作品。 (它仍然自己打印滾動條,並且背景在「滾動條外」部分丟失。)也許你可以玩這個並讓它工作,或者有更多WinForms體驗的人可以將它帶到下一個級別?

中聲明你的類以下內容:

[DllImport("user32.dll")] 
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 

private const int WM_PRINT = 791; 

/// <summary> 
/// The WM_PRINT drawing options 
/// </summary> 
[Flags] 
private enum DrawingOptions 
{ 
    /// <summary> 
    /// Draws the window only if it is visible. 
    /// </summary> 
    PRF_CHECKVISIBLE = 1, 

    /// <summary> 
    /// Draws the nonclient area of the window. 
    /// </summary> 
    PRF_NONCLIENT = 2, 
    /// <summary> 

    /// Draws the client area of the window. 
    /// </summary> 
    PRF_CLIENT = 4, 

    /// <summary> 
    /// Erases the background before drawing the window. 
    /// </summary> 
    PRF_ERASEBKGND = 8, 

    /// <summary> 
    /// Draws all visible children windows. 
    /// </summary> 
    PRF_CHILDREN = 16, 

    /// <summary> 
    /// Draws all owned windows. 
    /// </summary> 
    PRF_OWNED = 32 
} 

然後,繪製控制位圖:

using (Bitmap screenshot = new Bitmap(this.panel1.DisplayRectangle.Width, this.panel1.DisplayRectangle.Height)) 
using (Graphics g = Graphics.FromImage(screenshot)) 
{ 
    try 
    { 
     SendMessage(this.panel1.Handle, WM_PRINT, g.GetHdc().ToInt32(), (int)(DrawingOptions.PRF_CHILDREN | DrawingOptions.PRF_CLIENT | DrawingOptions.PRF_NONCLIENT | DrawingOptions.PRF_OWNED)); 
    } 
    finally 
    { 
     g.ReleaseHdc(); 
    } 
    screenshot.Save("temp.bmp"); 
} 

編輯:這裏有一個替代油漆策略,可能讓你你在找什麼。我正在做一些假設,但也許它會起作用。它描繪位圖上的一個虛擬的背景,並且還刪除滾動條:

using (Bitmap screenshot = new Bitmap(this.panel1.DisplayRectangle.Width, this.panel1.DisplayRectangle.Height)) 
using (Graphics g = Graphics.FromImage(screenshot)) 
{ 
    g.FillRectangle(SystemBrushes.Control, 0, 0, screenshot.Width, screenshot.Height); 
    try 
    { 
     SendMessage(this.panel1.Handle, WM_PRINT, g.GetHdc().ToInt32(), (int)(DrawingOptions.PRF_CHILDREN | DrawingOptions.PRF_CLIENT | DrawingOptions.PRF_OWNED)); 
    } 
    finally 
    { 
     g.ReleaseHdc(); 
    } 
    screenshot.Save("temp.bmp"); 
} 
0

我想創建一個具有正確大小的位圖(與正確的顏色清除或漆面板的背景圖片吧),然後遍歷所有子控件和.DrawToImage它們中的每一個到正確的位置。

0

你需要使你的面板AutoZize=TrueAutoScroll=False,比放到另一個容器,並使容器AutoScroll=true