最近在尝试一种有意思的桌面应用的写法:使用HTML+JS+CSS来做视图的展示,而不用winform的控件。效果还不错。
1.新建一个窗体Form。
2.在Form里添加一个WebBrowser控件。
public static WebBrowser CreateWebBrower(Object objectForScripting) { WebBrowser webBrowser1 = new WebBrowser(); webBrowser1.ScrollBarsEnabled = false; webBrowser1.AllowWebBrowserDrop = false;//将 WebBrowser 控件的 AllowWebBrowserDrop 属性设置为 false,以防止 WebBrowser 控件打开拖放到其上的文件。 webBrowser1.IsWebBrowserContextMenuEnabled = false;//将该控件的 IsWebBrowserContextMenuEnabled 属性设置为 false,以防止 WebBrowser 控件在用户右击它时显示其快捷菜单. webBrowser1.WebBrowserShortcutsEnabled = false;//将该控件的 WebBrowserShortcutsEnabled 属性设置为 false,以防止 WebBrowser 控件响应快捷键。 webBrowser1.ScriptErrorsSuppressed = true;//将该控件的 ScriptErrorsSuppressed 属性设置为 true,以防止 WebBrowser 控件显示脚本代码问题的错误信息。 if (objectForScripting != null) { webBrowser1.ObjectForScripting = objectForScripting; } return webBrowser1; }
3.使用html编写页面的视图展示,比用winform control灵活多了。
4.指定WebBrowser1.url 为刚刚第3步做的页面。
WebBrowser1.Url = new Uri("file://" + Path.Combine(Application.StartupPath, "web/index.htm"));
5.指定WebBrowser1.ObjectForScripting为刚刚新建立的窗体对象,并且在窗体类上声明"com可见性“。这么做:
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class Form1 : Form { public Form1() { InitializeComponent(); } }
6.在窗体里写个方法,必须是public的。这种方法,我们先叫“后台方法”
public void Run2() { }
7.这样我们就可用在html里调用这个run2方法了
window.external.Run2();
上面我们就完成了一个基本结构,在这个结构里,我们可以使用html编写页面,并在winform窗体里展示,并且可以在html页面里用js调用c#编写的方法。当然方法里是可以传参数的,可以传基本数据的参数,比如string,int,float 等。
--------------------
不过,我们要指定js是事件驱动的。我们调用一个方法后,如果方法执行事件过长,阻塞在那里可不好,于是我们就要考虑回调的方法实现。
如下:
在html页里,我需要调用一个后台方法(假设为:method1,这里指按照上面的步骤用c#写的方法),当方法method1完成后,调用回调方法,以使得在html里能收到回调的数据。
我们分步骤看看如何实现它。
1.我们在js里这么调用我们的后台方法,仔细看下面的方法fn4,在这个方法里,调用了后台方法Run2,并传入了一个参数“fn4_callback”,这个参数其实是个方法(function).我们想执行一个长时间的后台方法(run2),当run2方法执行完毕后,回调执行我们的fn4_callback方法。
function fn4() {
window.external.Run2(fn4_callback);
}
function fn4_callback(no,str) {
alert(no);
alert(str);
}
2.我们看看后台方法里,如何写run2。
public void Run2(object str) { //dosomethind 长时间的 Type t = str.GetType(); t.InvokeMember("", System.Reflection.BindingFlags.InvokeMethod, null, str, new object[]{1,"xx"}); }
注意这里的参数是object类型,使用getType()方法查看的话是个“System.__ComObject”类型。我们使用的反射的方式来调用它。比较给力的就是
t.InvokdeMember方法了。
这样我们就完成了整个回调的实现。非常的爽。
代码下载:http://yunpan.cn/Qe3yByINkUW52
---------
参考:http://www.pcreview.co.uk/forums/handling-javascript-functions-and-closures-passed-into-c-function-t3106028.html