最经遇到一个很棘手的问题,写出来大家探讨一下。
工作流系统中存在很多自定义的表单,由于是老系统,这些表单只能支持IE。现在做移动应用,需要将这些自定义的aspx表单展示在mobile safari浏览器中。
这些自定义表单用了大量的htc、只支持ie的javascript。而现在的任务是需要将这些表单展示在mobile safari浏览器中。
想了很多办法感觉都不好。昨天突然想到一个办法就是根据Url将表单转换成图片,然后展示到移动客户端。大致流程是:在服务端创建一个WebBrowser实例,在这个WebBrowser加载这个表单Url。由于WebBrowser内置的是IE内核,所以htc,javascript、css都能很好的运行,然后将通过ActiveX 将这个WebBrowser转换成图片。代码如下:
IViewObject.cs
< class="brush:csharp;gutter:false;"> [ComVisible(true), ComImport()] [GuidAttribute("0000010d-0000-0000-C000-000000000046")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IViewObject { [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int Draw( [MarshalAs(UnmanagedType.U4)] UInt32 dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcBounds, [MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcWBounds, IntPtr pfnContinue, [MarshalAs(UnmanagedType.U4)] UInt32 dwContinue); [PreserveSig] int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hicTargetDev, [Out] IntPtr ppColorSet); [PreserveSig] int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze); [PreserveSig] int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze); void SetAdvise([In, MarshalAs(UnmanagedType.U4)] int aspects, [In, MarshalAs(UnmanagedType.U4)] int advf, [In, MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink); void GetAdvise([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] paspects, [In, Out, MarshalAs(UnmanagedType.LPArray)] int[] advf, [In, Out, MarshalAs(UnmanagedType.LPArray)] IAdviseSink[] pAdvSink); }
HtmlCapture.cs
public
class
HtmlCapture
{
private
WebBrowser web;
private
Timer tready;
private
Rectangle screen;
private
Size
?
imgsize
=
null
;
//
an event that triggers when the html document is captured
public
delegate
void
HtmlCaptureEvent(
object
sender,
Uri url, Bitmap image);
public
event
HtmlCaptureEvent HtmlImageCapture;
//
class constructor
public
HtmlCapture()
{
//
initialise the webbrowser and the timer
web
=
new
WebBrowser();
tready
=
new
Timer();
tready.Interval
=
2000
;
screen
=
Screen.PrimaryScreen.Bounds;
//
set the webbrowser width and hight
web.Width
=
screen.Width;
web.Height
=
screen.Height;
//
supss script errors and hide scroll bars
web.ScriptErrorsSupssed
=
true
;
web.ScrollBarsEnabled
=
false
;
//
attached events
web.Navigating
+=
new
WebBrowserNavigatingEventHandler(web_Navigating);
web.DocumentCompleted
+=
new
WebBrowserDocumentCompletedEventHandler(web_DocumentCompleted);
tready.Tick
+=
new
EventHandler(tready_Tick);
}
#region
Public methods
public
void
Create(
string
url)
{
imgsize
=
null
;
web.Navigate(url);
}
public
void
Create(
string
url, Size imgsz)
{
this
.imgsize
=
imgsz;
web.Navigate(url);
}
#endregion
#region
Events
void
web_DocumentCompleted(
object
sender,
WebBrowserDocumentCompletedEventArgs e)
{
//
start the timer
tready.Start();
//
string s = web.Document.GetElementById("").InnerHtml;
}
void
web_Navigating(
object
sender, WebBrowserNavigatingEventArgs e)
{
//
stop the timer
tready.Stop();
}
void
tready_Tick(
object
sender, EventArgs e)
{
//
stop the timer
tready.Stop();
//
get the size of the document's body
Rectangle body
=
web.Document.Body.ScrollRectangle;
//
check if the document width/height is greater than screen width/height
Rectangle docRectangle
=
new
Rectangle()
{
Location
=
new
Point(
,
),
Size
=
new
Size(body.Width
>
screen.Width
?
body.Width : screen.Width,
body.Height
>
screen.Height
?
body.Height : screen.Height)
};
//
set the width and height of the WebBrowser object
web.Width
=
docRectangle.Width;
web.Height
=
docRectangle.Height;
//
if the imgsize is null, the size of the image will
//
be the same as the size of webbrowser object
//
otherwise set the image size to imgsize
Rectangle imgRectangle;
if
(imgsize
==
null
)
imgRectangle
=
docRectangle;
else
imgRectangle
=
new
Rectangle()
{
Location
=
new
Point(
,
),
Size
=
imgsize.Value
};
//
create a bitmap object
Bitmap bitmap
=
new
Bitmap(imgRectangle.Width, imgRectangle.Height);
//
get the viewobject of the WebBrowser
IViewObject ivo
=
web.Document.DomDocument
as
IViewObject;
ivo.ToString();
using
(Graphics g
=
Graphics.FromImage(bitmap))
{
//
get the handle to the device context and draw
IntPtr hdc
=
g.GetHdc();
ivo.Draw(
1
,
-
1
, IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, hdc,
ref
imgRectangle,
ref
docRectangle, IntPtr.Zero,
);
g.ReleaseHdc(hdc);
}
//
invoke the HtmlImageCapture event
HtmlImageCapture(
this
, web.Url, bitmap);
}
#endregion
}
}
下面我们使用上面代码可以截图工作流表单的图片了:
< class="brush:csharp;gutter:false;"> void hc_HtmlImageCapture(object sender, Uri url, Bitmap image) { image.Save("C:/test.bmp"); } private void button1_Click(object sender, EventArgs e) { HtmlCapture hc = new HtmlCapture(); hc.HtmlImageCapture += new HtmlCapture.HtmlCaptureEvent(hc_HtmlImageCapture); hc.Create("http://10.5.23.117:8011/Recipe1.aspx"); }
这样效果和PC端展示一样。
截取百度快照:
获取的图片:
尽管展示和pc端一样,但是图片存在的问题主要有:
1、不支持复制粘贴
2、不支持多标签页的切换(移动端不需要支持表单编辑功能)
3、不支持超链接点击
总结:由于WebBrowser支持htc、已经写好的javascript代码,而js和htc做了不少业务逻辑处理,所以在服务端使用WebBrowser去处理表单的思路是正确的。但是进一步如何解决上面的三个问题。需要进一步探讨。在不大量修改之前存在的工作流表单的前提下,如果你有更好的想法,期待你的告诉我。
附:根据url抓取图片代码
原文链接: http://www.cnblogs.com/zhuqil/archive/2011/08/17/2143502.html