概述
最近在Winform的開發中用到了Flash動態圖表FusionCharts Free,這是個開源的flash組件。商業版可以使用FusionCharts V3,免費版本的是FusionCharts
Free v2.2。:http://www.fusioncharts.com/free/download/。大家可以去看看,效果還是非常炫的。商業版比免費版能夠提供更多的圖表,匯出pdf,image,csv等功能,當然免費版這些功能大家就別指望了。
一般flash組件都是以flash的形式在網頁中呈現的。因此如果要在Winform中Flash圖表個人認為有兩種方案。1.
利用WebBrowser控制項,將url執行包含這個flash的網頁。2.利用Flash的com組件shockwave Flash。第一種方式實現方式比較簡單,第二種個人認為最好的是有Flex的組件作為容器,這樣可以根據傳遞進來的參數顯示不同的圖表。
因為免費版沒有匯出pdf,image,csv等功能,所以只好自己去寫了。而且是載入到WebBrowser控制項,因此我對WebBrowser進行了擴充。目前常用的Flash圖表都可以展示,匯出pdf,image,excel,等格式。
相關圖片預覽
先上幾張圖片給大家一個直觀點的認識
圖1.匯出的圖片
圖2.匯出的pdf
遇到的問題
1. 如標題所說的關於WebBrowser.DrawToBitmap問題,因為此控制項是沒有這個方法的,但是你用了也不會出錯,但是問題就來了,有時候可以匯出圖片有時候又不能,載入的網頁裡面不存在Ajax內容之類的。網上有不少對此問題的解決辦法,但是所見之處基本都是錯誤的。一種普遍的做法如下:
代碼
publicvoid WriteBmp(string bmpPath)
{
while (webbrowser.ReadyState
!= WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
System.Drawing.Rectangle r =new System.Drawing.Rectangle(Point.Empty,
new Size(int.Parse(webbrowser.Document.Body.GetAttribute("scrollWidth")),
int.Parse(webbrowser.Document.Body.GetAttribute("scrollHeight"))));
Bitmap bmp =new Bitmap(r.Width, r.Height);
webbrowser.DrawToBitmap(bmp, r);
bmp.Save(bmpPath);
bmp.Dispose();
}
結果就導致了時而可以時而不可以的問題。對這個問題,國外的網站有不錯的解決方案:
1.http://bytes.com/topic/c-sharp/answers/605264-taking-screenshot-webbrowser-tab。
2.
http://efreedom.com/Question/1-2434156/WebBrowser-DrawToBitmap-Methods
根據上面的方法,我將代碼列出來給大家供參考,以上兩種方法我用過了效果都很棒(上面的就是這樣產生的):
代碼
[DllImport("user32.dll")]
privatestaticexternbool PrintWindow(IntPtr hwnd, IntPtr hdcBlt,
uint nFlags);
publicvoid WriteBmp(string bmpPath)
{
int screenWidth
= webbrowser.Document.Body.ScrollRectangle.Width;
int screenHeight
= webbrowser.Document.Body.ScrollRectangle.Height;
IntPtr myIntptr = webbrowser.Handle;
int hwndInt
= myIntptr.ToInt32();
IntPtr hwnd = myIntptr;
// Set hdc to the bitmap
Bitmap bm =new Bitmap(screenWidth, screenHeight);
Graphics g = Graphics.FromImage(bm);
IntPtr hdc = g.GetHdc();
// Snapshot the WebBrowser
bool result
= PrintWindow(hwnd, hdc,
0);
g.ReleaseHdc(hdc);
g.Flush();
// Save the bitmap, if successful
if (result
==true)
bm.Save(bmpPath);
}
第2種方式:
代碼
publicstaticclass ApiConstants
{
publicconstint SRCCOPY
=13369376;
}
publicstaticclass Utilities
{
publicstatic Image CaptureScreen()
{
return CaptureWindow(User32.GetDesktopWindow());
}
publicstatic Image CaptureWindow(IntPtr handle)
{
IntPtr hdcSrc = User32.GetWindowDC(handle);
RECT windowRect =new RECT();
User32.GetWindowRect(handle, ref windowRect);
int width
= windowRect.right
- windowRect.left;
int height
= windowRect.bottom
- windowRect.top;
IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap);
Gdi32.BitBlt(hdcDest, 0,
0, width, height, hdcSrc,
0, 0, ApiConstants.SRCCOPY);
Gdi32.SelectObject(hdcDest, hOld);
Gdi32.DeleteDC(hdcDest);
User32.ReleaseDC(handle, hdcSrc);
Image image = Image.FromHbitmap(hBitmap);
Gdi32.DeleteObject(hBitmap);
return image;
}
}
publicstaticclass User32
{
[DllImport("user32.dll")]
publicstaticextern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
publicstaticextern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
publicstaticextern IntPtr GetWindowRect(IntPtr hWnd,
ref RECT rect);
[DllImport("user32.dll")]
publicstaticextern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
}
publicclass Gdi32
{
[DllImport("gdi32.dll")]
publicstaticexternbool BitBlt(IntPtr hObject,
int nXDest,
int nYDest, int nWidth,
int nHeight, IntPtr hObjectSource,
int nXSrc,
int nYSrc, int dwRop);
[DllImport("gdi32.dll")]
publicstaticextern IntPtr CreateCompatibleBitmap(IntPtr hDC,
int nWidth,
int nHeight);
[DllImport("gdi32.dll")]
publicstaticextern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
publicstaticexternbool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")]
publicstaticexternbool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
publicstaticextern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
}
[StructLayout(LayoutKind.Sequential)]
publicstruct RECT
{
publicint left;
publicint top;
publicint right;
publicint bottom;
}
//如果是.net的擴充方法,如果你.net庫版本比較高就去掉注釋
//public static class ControlExtensions
//{
// public static Image DrawToImage(this Control control)
// {
// return Utilities.CaptureWindow(control.Handle);
// }
//}
2.關於匯出pdf的問題,大家可以去下載itextsharp開源的組件,學習文檔可以參考
1. http://itextpdf.com/book/examples.php。java版的
2. http://www.cnblogs.com/islands/archive/2008/06/27/1231288.html
小結
以上是自己在Flash動態圖表開發中一點小小的心得,寫出來和大家一起分享,本文的目的給遇到類似問題的朋友一種解決方案,在你搜尋完google,再搜尋baidu發現都不能解決你問題的時候,或許此文能給你點協助。
作者:Jackhuclan
出處:http://jackhuclan.cnblogs.com/
本文著作權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。