目录
WebRuntime的应用组织模式:开启全新的Web前端设计时代
引言
互联网深刻的影响着人们获取信息的方式,做为互联网的入口,互联网浏览器给这个世界带来了深远的影响,从互联网的开端至今,浏览器差不多有30年的历史了,这30年软件世界发生了翻天覆地的变化。毋庸置疑,Windows操作系统之上的浏览器,在互联网历史上有着无法替代的历史地位。以Chrome为例,Google的互联网浏览器基本上是在Windows版本两年之后,才陆续推出其他操作系统的版本。对公共互联网而言,基本上也是现做成熟Windows版本,然后再雕琢其他操作系统对应的版本。浏览器打造了主导互联网的Web世界。
由于Web内容的易于制作、易于分发、易于维护等诸多优势,这些方面桌面客户端显得相形见绌。我们看到,Web开发者相比桌面客户端开发者而言在互联网时代显示出更大、更广阔的潜力。然而一个不争的事实是,互联网浏览器也是一款桌面客户端,只不过由于其内容空间巨大,人们差不多忽略了对应可执行文件的存在,对Web开发者而言,很少关心Chrome.exe、MsEdge.exe等的存在,日复一日的只是在制作各种类型的Webpage、关注各类与Web相关的技术框架。
我们必须承认,存在的必然是有道理的。桌面客户端曾经的黄金时代,同样是一段辉煌的历史,同时,桌面客户端一定拥有Web技术无法替代的因素,事实上,许多客户端我们是无法彻底放弃的,我们每一天都在与很多非Web技术打交道。桌面客户端似乎与浏览器技术形成了桌面操作系统的两个极端或者二者之间有一道明显的鸿沟,由此产生了技术上根本的差异。如果二者之间的差异是因为一条巨大的鸿沟的存在,那么这一条鸿沟应该到了填平的时刻了。
填平桌面客户端与现代互联网浏览器之间的鸿沟
Web内容驱动能力,明显是浏览器客户端相比桌面客户端具备的独特优势。如果桌面客户端具备与浏览器等价的Web驱动能力,那么情况就会完全不一样。我们认为让桌面客户端拥有互联网基因的关键是,让桌面客户端完全取代互联网浏览器,也就是说,我们需要一个简明的技术方案,使得绝大多数桌面客户端通过这个方案获得现代浏览器具备的全部功能的。
WebRuntime开源项目
**WebRuntime**是一个使得桌面客户端具备现代互联网浏览器全部功能的开源项目,这个项目的核心是提供一个简明的技术方案,使得开发者基于现有的主流技术开发出强大的互联网客户端软件。 WebRuntime提供单一可执行文件支持.NET/Win32/Java等主流运行时环境,应用直接内置Chromium全部的代码,我们推荐大家参考以下超链接:
每一个按照如上步骤形成的桌面客户端,其本身就是Chromium意义下的Browser进程,因此具备完整的互联网浏览器架构,为例区别于标准互联网浏览器,我们实现了扩展的DOM模型,使得.NET、COM、Java等对象直接成为DOM元素,这一点意味着,Javascript可以基于Sandbox技术,很好的处理应用程序的对象模型,特别,.NET Framework整体成为DOM的一部分,开发者可以运用Javascript代码创建.NET GUI对象、处理对应的事件。
关于Java技术
WebRuntime目前将每一个支持WebRuntime的Win32 应用(包含.NET应用)设计成EclipseLauncher,当然,我们可以在一般意义下支持Java,限于技术人力,我们目前只支持基于Eclipse技术的Java技术框架以及Java RCP应用
WebRuntime与Office VBA
WebRuntime的基本思路的源头之一是我们早期的动态VBA集成技术,这些设想可以参考动态VBA集成技术,由于VBA技术不再发行商业许可,我们彻底放弃了这个技术架构,转而用.NET Frame替代VBA,由此,我们的开源技术架构的基本轮廓如下:
-
给Win32客户端应用提供内置的互联网浏览器支持,使得开发者可以通过Web页面的模式形成应用模块、扩展应用系统的内容空间,运用Javascript将客户端软件逻辑分离,实现真正意义下的互联网云应用;
基于.NET的Demo
-
每一款Win32应用与标准互联网浏览器的差异是第一个窗口实例,浏览器打开的每一个窗口都是浏览器窗口,基于WebRuntime技术开发的客户端软件,打开每一个URL,用户获得的可能是其他窗口类型,例如可能是一个WinForm、一个MFC窗口,或者是一个SWT Form,也可能是Eclipse Workbench;
-
浏览器窗口提供子窗口模式,这一点使得WebRuntime明显的区别于那些基于CEF、Electron的客户端技术方案,开发者可以将浏览器窗口做为一个窗口对象的一个局部区域,然后基于浏览器标签组的方式组织应用:
(基于浏览器标签在WinForm之中组织应用) -
扩展DOM技术允许开发者用Win32 GUI对象与标准DOM元素协作形成基于应用的Web页面:
(基于Win32 GUI组件的面向应用的Web页面,明显有别于标准Web页面)
-
Javascript代替VBA宏语言;我们给出统一的技术方案,使得Javascript做为Win32应用系统的公共脚本语言,对每一个建立在WebRuntime基础之上的客户端软件,都可以基于这个技术统一模式应用内容;例如,可以基于Javascript脚本创建及其丰富的Form对象类型;
<script type="text/javascript"> var form = null; var treegrid = null; var panel1_ = null; var Splitter_ = null; var CompositeGrid_Splitter_ = null; cosmos.onLoadMdiCloudForm = function (e) { form = e.form; switch (form.name) { case "mainForm": { form.onGalaxyCreated = function (e) { } form.onXobjCreated = function (e) { var galaxy = e.xobj.getStr("galaxy"); var winNucleus = e.xobj.getStr("winNucleus"); //alert(galaxy); switch (galaxy) { case "webviewport": { switch (winNucleus) { case "__viewport_default__": { switch (e.xobj.name) { case "navCtrl": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": break; case "button1_OnClick": break; default: break; } } } break; case "mainClient": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; case "DynLayoutBtn_OnClick": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster") + "_OnClick", this.workElement.outerHTML); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; case "button1_OnClick": { if (!!this.workElement) { var xobj = this.sender; this.element.setAttribute("w12", "12345678"); if (!!xobj) { xobj.ObserveEx("key1", cosmos.getElementById("mainwindow_1")); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.Observe(0, 0, "key1", cosmos.getElementById("mainwindow_2").outerHTML); } } else { alert(this.sender + " sender is form"); } this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); } if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } break; case "button2_OnClick": { if (!!this.workElement) { var xobj = this.sender; var xml = cosmos.getElementById("mainwindow_2").outerHTML; xobj.Observe("key2", xml); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.ObserveEx(0, 0, "key2", cosmos.getElementById("mainwindow_1")); } this.ObserveEx(this.workElement.getAttribute("targetcluster"), this.workElement); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; } } } break; } } break; } } break; case "panel1": { panel1_ = e.galaxy; switch (winNucleus) { case "default": { switch (e.xobj.name) { case "Sunny_ntpctrl": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "button1_OnClick": { alert(this.docFragment.firstChild.outerHTML); } break; } } } break; case "Splitter1": { Splitter_ = e.grid; } break; } } break; } } break; case "mainclient@__viewport_default__@default_frame": { switch (winNucleus) { case "startup": break; case "compositegrid": { switch (e.xobj.name) { case "CompositeGrid_Splitter": CompositeGrid_Splitter_ = e.grid; break; } } break; } } break; } }; } break; case "create_form_1": { form.onCloudMessageForCloudForm = function (e) { switch (e.msgID) { case "button1_OnClick": { alert("您好\n" + e.form.workElement.outerHTML + "****\n" + e.form.getStr("textBox1")); } break; } } } break; case "create_form_2": { //alert(form); } break; } }; cosmos.onLoadCloudForm = function (e) { }; cosmos.onXobjCreated = function (e) { var galaxy = e.xobj.getStr("galaxy"); var winNucleus = e.xobj.getStr("winNucleus"); switch (galaxy) { case "client": switch (winNucleus) { case "default": switch (e.xobj.name) { case "Sunny_ntpctrl": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "button1_OnClick": { var xobj = this.sender; if (!!xobj) { //alert(xobj.parent.getLong("gridtype")); //xobj.ObserveEx("key1", cosmos.getElementById("mainwindow_1")); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.Observe(0, 1, "key1", cosmos.getElementById("mainwindow_2").outerHTML); } } else { alert(this.sender + " sender is form"); } alert(this.docFragment.firstChild.outerHTML); } break; } } } break; case "Splitter1": { Splitter_ = e.grid; } break; } break; } break; case "file_view": { // alert(e.xobj.name); } break; case "webviewport": { switch (winNucleus) { case "__viewport_default__": { switch (e.xobj.name) { case "navCtrl": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": break; case "button1_OnClick": break; default: break; } } } break; case "mainClient": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; case "DynLayoutBtn_OnClick": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster") + "_OnClick", this.workElement.outerHTML); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; case "button1_OnClick": { if (!!this.workElement) { var xobj = this.sender; this.element.setAttribute("w12", "12345678"); if (!!xobj) { xobj.ObserveEx("key1", cosmos.getElementById("mainwindow_1")); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.Observe(0, 0, "key1", cosmos.getElementById("mainwindow_2").outerHTML); } } else { alert(this.sender + " sender is form"); } this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); } if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } break; case "button2_OnClick": { if (!!this.workElement) { var xobj = this.sender; var xml = cosmos.getElementById("mainwindow_2").outerHTML; xobj.Observe("key2", xml); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.ObserveEx(0, 0, "key2", cosmos.getElementById("mainwindow_1")); } this.ObserveEx(this.workElement.getAttribute("targetcluster"), this.workElement); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; } } } break; } } break; case "default": { switch (e.xobj.name) { case "navCtrl": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": break; case "button1_OnClick": alert(e.xobj.name); break; default: break; } } } break; case "mdiclient": { e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); } } break; } } } break; case "mainClient": { //alert(e.xobj); e.xobj.onCloudMessageForXobj = function (e) { switch (this.msgID) { case "treeView1_OnAfterSelect": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); if (this.objtype == "docwebhost") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; case "DynLayoutBtn_OnClick": { if (!!this.workElement) { this.Observe(this.workElement.getAttribute("targetcluster") + "_OnClick", this.workElement.outerHTML); if (this.objtype == "docwebhost") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; case "button1_OnClick": { if (!!this.workElement) { var xobj = this.sender; this.element.setAttribute("w12", "12345678"); if (!!xobj) { xobj.ObserveEx("key1", cosmos.getElementById("mainwindow_1")); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.Observe(0, 0, "key1", cosmos.getElementById("mainwindow_2").outerHTML); } } else { alert(this.sender + " sender is form"); } this.Observe(this.workElement.getAttribute("targetcluster"), this.workElement.outerHTML); } if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } break; case "button2_OnClick": { if (!!this.workElement) { var xobj = this.sender; var xml = cosmos.getElementById("mainwindow_2").outerHTML; xobj.Observe("key2", xml); if (xobj.parent != null && xobj.parent.getLong("gridtype") == 4) { xobj.parent.ObserveEx(0, 0, "key2", cosmos.getElementById("mainwindow_1")); } this.ObserveEx(this.workElement.getAttribute("targetcluster"), this.workElement); if (this.objtype == "nucleus") { this.ShowWebContent("contents", this.workElement.getAttribute("content")); } } } break; } } } break; } } break; } } break; } } cosmos.onCosmosMessageReceived = function (e) { switch (e.xobj.msgID) { case "TANGRAMAPP_READY": { } break; case "TEST_MFC_MSG": { //alert(e.xobj.getStr("testinfo")+e.xobj.handle); } break; case "TREECTRL_TvnSelchanged": { var name = e.xobj.getStr("treenodekey"); alert(name); //alert(e.xobj.element.outerHTML); alert(e.xobj.getElementById(name).outerHTML); //alert(e.xobj.getElementById(name)); var elems = e.xobj.getElementsByTagName(name); alert(elems[0].outerHTML); } break; case "WM_COMMAND": { alert(e.xobj.name); switch (e.xobj.getStr("CtrlClass")) { case "Button": { alert("DocType:" + e.xobj.getStr("DocTypeID")); alert("galaxy:" + e.xobj.getStr("galaxy")); alert("winNucleus:" + e.xobj.getStr("winNucleus")); alert(e.xobj.name); console.log("WM_COMMAND_button\n"); //cosmos.sendMessage("COSMOS_CREATE_DOC", ".xxxx", "test", "33"); } break; case "Edit": { } break; } } break; default: break; } } cosmos.onMessageReceived = function (e) { if (e.param3 != null) { switch (e.param3) { default: break; } } } cosmos.onBindCLRObject = function (e) { alert(e.name); alert(e.objtype); alert(e.hwnd); } //**************************************************************** function CompositeGrid1() { var grid = cosmos.getXobj("default", "__viewport_default__", "navCtrl"); alert(grid); var node = cosmos.getXobj("mainclient@webviewport@default_frame", "compositegrid", "CompositeGrid_Splitter"); if (node) { node.getChild(0, 1).Observe("layout_1", document.getElementById("layout_1").outerHTML); } } function CreateExcelWorkBook1() { var elem = cosmos.getElementById("workbook1"); var xdoc = cosmos.Observe("officeapp:excel.application",elem); } function CreateExcelWorkBook2() { var elem = cosmos.getElementById("workbook2"); var xdoc = cosmos.Observe("officeapp:excel.application", elem); } function CreateExcelWorkBook3() { var elem = cosmos.getElementById("workbook3"); var xdoc = cosmos.Observe("officeapp:excel.application", elem); } function CreateExcelWorkBook4() { var elem = cosmos.getElementById("workbook4"); var xdoc = cosmos.Observe("officeapp:excel.application", elem); } function OnCreate_Form1_SunnyForms2() { var elem = cosmos.getElementById("create_form_1"); var xform = cosmos.createWinForm(elem, 0, function (form) { form.addEventListener("button1", "OnClick", function (e) { e.setStr("textBox1", "fill textbox by javascript: " + e.handle); }); form.BindCtrlValue("textBox1;button1", function (e) { alert("hi" + " -- " + e.getStr("textBox1")); }); }); } function OnCreate_Form1_SunnyForms2_1() { var elem = cosmos.getElementById("create_form_1_1"); var xform = cosmos.createWinForm(elem, 0, function (form) { form.addEventListener("button1", "OnClick", function (e) { e.setStr("textBox1", "fill textbox by javascript: " + e.handle); }); form.BindCtrlValue("textBox1;button1", function (e) { alert("hi" + " -- " + e.getStr("textBox1")); }); }); } function OnCreate_Form1_SunnyForms2_2() { var elem = cosmos.getElementById("create_form_1_2"); var xform = cosmos.createWinForm(elem, 0, function (form) { form.addEventListener("button1", "OnClick", function (e) { e.setStr("textBox1", "fill textbox by javascript: " + e.handle); }); form.BindCtrlValue("textBox1;button1", function (e) { alert("hi" + " -- " + e.getStr("textBox1")); }); }); } function OnCreate_Form1_SunnyForms2_3() { var elem = cosmos.getElementById("create_form_1_3"); var xform = cosmos.createWinForm(elem, 0, function (form) { form.addEventListener("button1", "OnClick", function (e) { e.setStr("textBox1", "fill textbox by javascript: " + e.handle); }); form.BindCtrlValue("textBox1;button1", function (e) { alert("hi" + " -- " + e.getStr("textBox1")); }); }); } function OnCreate_Form2_SunnyForms2() { var xform = cosmos.createWinForm(cosmos.getElementById("create_form_2"), 0, function (x) { x.addEventListener("button1", "OnClick", function (e) { alert(e); alert("hi" + " -- " + e.handle); e.setStr("textBox1", "test modify textbox"); }); x.BindCtrlValue("textBox1", function (e) { //alert("hi" + " -- " + e.getStr("textBox1")); }); }); } function BrowserFormApp1() { var xform = cosmos.createWinForm(cosmos.getElementById("create_form_3"), 0, function (x) { x.form.addEventListener("button1", "OnClick", function (e) { alert("hi" + " -- " + x.form.handle); //x.form.xobj.setStr("textBox1", "test modify textbox"); }); }); } function BrowserFormApp2() { var xform = cosmos.createWinForm(cosmos.getElementById("create_form_4"), 0, function (x) { x.form.addEventListener("button1", "OnClick", function (e) { alert("hi" + " -- " + x.form.handle); //x.form.xobj.setStr("textBox1", "test modify textbox"); }); }); } function OpenMdiApp1() { // cosmos.openUrl("host:WebPage/mdiform1.html", 200); cosmos.openUrl("host:WebPage/mdiform1.html|host:webpage/sunny.html", 200); } function OpenMdiFormApp1() { // cosmos.openUrl("host:WebPage/mdiform1.html", 200); cosmos.openUrl("host:WebPage/mdiformapp1.html|host:webpage/sunny.html", 200); } function OpenCWRURL() { cosmos.openUrl("host:webpage/CWR.html", 2); } function OpenCERURL() { cosmos.openUrl("host:webpage/CER.html", 2); } function OpenAppURLAsSubPage1() { cosmos.openUrl("host:webpage/SubWebApp1.html", 2); } function OpenAppURLAsSubPage2() { cosmos.openUrl("host:webpage/SubWebApp2.html", 2); } function OpenAppURLAsSubPage3() { cosmos.openUrl("host:webpage/WebApp3.html", 2); } </script>(一个页面之中的Javascript脚本)
-
.NET WinForm代替VBA Form2,我们在WebRuntime之中提供独特的Cloud WinForm技术,这个技术使得WinForm对象拥有动态html的描述特征,使得WinForm对象自然成为html的一部分:
<Forms> <Form1 objid="sunnyForms2.Form1,sunnyForms2" caption="Form1@SunnyForm2" id="create_form_1" width="1400" height="1600" model="2"> <mainpanel id="mainpanel"> <default> <winNucleus> <xobj id='splitter' rows='1' cols='2' height='300,' width='300,250,' middlecolor='RGB(255,224,192)'> <xobj id='tangramtabctrl_Page2' objid="nucleus"></xobj> <xobj id='create_form_message' objid="sunnyForms2.Form4,sunnyForms2"></xobj> </xobj> </winNucleus> </default> </mainpanel> <contentpanel id="contentpanel"> <default> <winNucleus> <xobj style="18"> <xobj objid="nucleus" caption="Content Panel"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </contentpanel> <eventmap> <button1 event="OnClick"> <btn content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="29"> <xobj objid="nucleus" caption="test button onclick 2"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> <btn target="mainClient" winNucleus="__viewport_default__" galaxy="default" content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="18"> <xobj objid="nucleus" caption="test button onclick 2 from a form button click"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> </button1> </eventmap> </Form1> <Form1 objid="sunnyForms2.Form1,sunnyForms2" caption="Form1@SunnyForm2" id="create_form_1_1" width="1400" height="1600" model="2"> <mainpanel id="mainpanel"> <default> <winNucleus> <xobj style="18"> <xobj caption="Start Page" rows="3" cols="3" width="150,100,100" height="200,180,100"> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl"></xobj> <xobj objid="SunnyForms.Form1,SunnyForms"></xobj> <xobj style="39" activepage="1"> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="First Page"></xobj> <xobj objid="nucleus" caption="Compound grid World Gives You An Unexpected Surprise"></xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl" caption="Third Page"></xobj> </xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl"></xobj> </xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </mainpanel> <contentpanel id="contentpanel"> <default> <winNucleus> <xobj style="19"> <xobj objid="nucleus" caption="Content Panel"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </contentpanel> <eventmap> <button1 event="OnClick"> <btn content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="29"> <xobj objid="nucleus" caption="test button onclick 2"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> <btn target="mainClient" winNucleus="__viewport_default__" galaxy="default" content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="13"> <xobj objid="nucleus" caption="test button onclick 2 from a form button click"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> </button1> </eventmap> </Form1> <Form1 objid="sunnyForms2.Form1,sunnyForms2" caption="Form1@SunnyForm2" id="create_form_1_2" width="1400" height="1600" model="2"> <mainpanel id="mainpanel"> <default> <winNucleus> <xobj style="17"> <xobj caption="Start Page" rows="3" cols="3" width="150,100,100" height="200,180,100"> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl"></xobj> <xobj objid="SunnyForms.Form1,SunnyForms"></xobj> <xobj style="39" activepage="1"> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="First Page"></xobj> <xobj objid="nucleus" caption="Compound grid World Gives You An Unexpected Surprise"></xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl" caption="Third Page"></xobj> </xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl"></xobj> </xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </mainpanel> <contentpanel id="contentpanel"> <default> <winNucleus> <xobj style="29"> <xobj objid="nucleus" caption="Content Panel"></xobj> <xobj url="host:Template/doctemplate1.html|host:webpage/newweb.html" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </contentpanel> <eventmap> <button1 event="OnClick"> <btn content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="29"> <xobj objid="nucleus" caption="test button onclick 2"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> <btn target="mainClient" winNucleus="__viewport_default__" galaxy="default" content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="18"> <xobj objid="nucleus" caption="test button onclick 2 from a form button click"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> </button1> </eventmap> </Form1> <Form1 objid="sunnyForms2.Form1,sunnyForms2" caption="Form1@SunnyForm2" id="create_form_1_3" width="1400" height="1600" model="2"> <mainpanel id="mainpanel"> <default> <winNucleus> <xobj style="19"> <xobj caption="Start Page" rows="3" cols="3" width="150,100,100" height="200,180,100"> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl"></xobj> <xobj objid="SunnyForms.Form1,SunnyForms"></xobj> <xobj style="18" activepage="1"> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="First Page"></xobj> <xobj objid="nucleus" caption="Compound grid World Gives You An Unexpected Surprise"></xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl" caption="Third Page"></xobj> </xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl1,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl"></xobj> </xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </mainpanel> <contentpanel id="contentpanel"> <default> <winNucleus> <xobj style="33"> <xobj objid="nucleus" caption="Content Panel"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </default> </contentpanel> <eventmap> <button1 event="OnClick"> <btn content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="29"> <xobj objid="nucleus" caption="test button onclick 2"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> <btn target="mainClient" winNucleus="__viewport_default__" galaxy="default" content="content_using_browser" targetcluster="content_using_browser2"> <winNucleus> <xobj style="23"> <xobj objid="nucleus" caption="test button onclick 2 from a form button click"></xobj> <xobj objid="SunnyCtrl.UserControl3,SunnyCtrl" caption="Second Page 2"></xobj> <xobj objid="SunnyCtrl.UserControl2,SunnyCtrl" caption="Third Page"></xobj> </xobj> </winNucleus> </btn> </button1> </eventmap> </Form1> <Form2 type="winform" objid="sunnyForms2.Form2,sunnyForms2" caption="Form2@SunnyForm2" id="create_form_2" width="1600" height="1200"> <mainpanel> <default> <winNucleus> <xobj id='properties' height='300,250,100,' width='300,200,100,' middlecolor='RGB(255,224,192)'> <xobj id='tangramtabctrl_Page2' objid="nucleus" caption='111'></xobj> <xobj id='create_form_message' objid="sunnyForms2.Form4,sunnyForms2" caption='222'></xobj> <xobj id='create_form_message2' objid="sunnyForms2.Form4,sunnyForms3" caption='333'></xobj> </xobj> </winNucleus> </default> </mainpanel> </Form2> <Form3 type="winform" objid="sunnyForms2.Form3,sunnyForms2" caption="Form3@SunnyForm2" id="create_form_3" width="2000" height="1600"> <mainpanel> <default> <winNucleus> <xobj id='tangramtabctrl_Page1' url="host:webpage\cwr.html" caption='Form3'></xobj> </winNucleus> </default> </mainpanel> </Form3> <Form4 type="winform" objid="sunnyForms2.Form4,sunnyForms2" caption="Form4@SunnyForm2" id="create_form_4" width="2000" height="1600"> <mainpanel> <default> <winNucleus> <xobj rows="1" cols="2" width="500,200" masterrow="0" mastercol="0"> <xobj rows="2" cols="1" height="400,200" masterrow="0" mastercol="0"> <xobj id='Page1' url="host:webpage\cwr.html|host:sunny2.html"></xobj> </xobj> <xobj id='Page2' caption='Form3'></xobj> </xobj> </winNucleus> </default> </mainpanel> </Form4> </Forms>(Web页面之中的 Cloud WinForm示范)
-
每一个WebRuntime客户端,都是一个Eclipse Laucher,这一点意味着您可以开发出Java-Chromium-.NET混合系统,同时支持Java、Web、.NET。如下图:
WebRuntime的应用组织模式:开启全新的Web前端设计时代
一旦一个具体的应用集成了WebRuntime,那么后续的工作几乎与Web开发是一致的,只不过开发者面对的是一个更大的DOM,从这一阶段起,应用软件的内容组织,本质上就是html前端设计,由此开始,几乎所有的前端Web技术,例如VUE,都可以用于Windows客户端开发。
用于开发者面对的不再是标准浏览器,而是一个大众化的exe文件,每一个具体的应用,都需要一个初始化Web页面,用于描述应用系统的基本特征,例如“新标签页”样式等等,我们会陆陆续续提供相关的技术文档。
(一个MFC应用的内置浏览器新标签页)
(形形色色的Web页面)
欢迎您加入我们的开发技术体系
Win32技术Web前端化,是一个刚刚形成的新颖的面向互联网、云计算的客户端技术平台,我们深知自己技术视野的局限,所以期待您贡献自己的精彩想法,同时也希望我们可以联手打造出属于中国人的互联网软件新技术平台,WebRuntime本质上是面向互联网大环境的运行时架构,其中体现出中华文化的关键一点,就是“海纳百川、包容”,我们深知中华文化的博大精深,期待我们用自己民族的文化精华打造今天的互联网客户端技术。
当每一款Win32客户端都具备浏览器基因
当每一款客户端程序都具备浏览器基于,那么互联网的内容世界就会被进一步放大,WebDOM就会从标准DOM元素的有限性提升为DOMPlus,一个包容性更加强大的无限元素类型的DOM,这样的页面世界,势必引发互联网世界进一步演化,由此催生了一次巨大的变革,随着互联网浏览器独特地位的消失,桌面客户端与Web之间的鸿沟也就会逐渐填平,所有这一切,期待您的加入……