.NET Desktop程序员:互联网大环境下软件生产力的创造者

 目录

引言

桌面软件如何适配今天的互联网

让.NET桌面软件工程拥有互联网基因

WebRuntime是什么?

具体案例

让应用适配不同的应用场景

基于应用的Web页面

Cloud WinForm:强大的Web生产力

总结


引言

        对每个.NET开发者而言,以下代码不会陌生:

namespace FirstApp
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

可以说每一个C#写的WinForm工程差不多都包含与上述代码等价的部分。其中的关键是:

            Application.Run(new Form1());

2002年一月微软正式发行.NET Framework,时至今日快20年了,这一行几乎就没有变过。20年的时间里建立在.NET基础之上的桌面客户端系统不计其数,尽管每个系统形态各异,对绝大多数.NET桌面应用系统而言,Application.Run的调用是不可避免的,这是一个客观的、毋庸置疑的事实。

桌面软件如何适配今天的互联网

       互联网浏览器的出现,改变了人们获取信息的习惯,同时,也改变了软件开发、部署、升级以及运营的模式,这一切对桌面软件的生态形成了巨大的挑战。以浏览器为切入点的Web软件,在很多方面,都显示出桌面软件无法比拟的优势由于Web DOM元素的有限性,Web应用目前还无法彻底替代桌面软件,但是一种趋势似乎已经形成,桌面应用大有“昨日黄花”的困惑,有办法改变这个态势吗?

        或许我们即将迎来互联网的进一步演化,5G的兴起,网络速度不再是问题,本地计算机硬盘存储几乎也不是问题,计算机芯片的主频越来越大,这一切,预示着越来越强大的桌面计算机不再是奢侈品,似乎桌面软件还具备客观的基础物理环境。但是,面对咄咄逼人的Web生态,即使C#这样优秀的语言也显得力不从心,我们认为,软件界需要一次变革,或者变革一直在悄无声息的酝酿之中……

        让每一款桌面应用都具备互联网浏览器的基因,是我们的一种愿景。如果这一设想得以成立,那么互联网浏览器独特的地位就会逐渐消失,浏览器的竞争也会渐渐的淡化,桌面软件与Web软件的边界也就消失了。

让.NET桌面软件工程拥有互联网基因

       本文面向所有Windows .NET程序员,需要具备以下几个方面的基础知识以及准备工作

  1. 修改.NET工程的编译选项,我们只支持64位应用(DebugRelease 64位编译);
  2. 下载 (点击)WebRuntime运行时支撑包,需要将运行时必要的支撑包放在与exe文件相同文件夹之内;
  3. 正确配置工程的Manifest文件(app.manifest包含在WebRuntime运行时支撑包之中);
  4. 引用Cosmos.dllCosmos.dll包含在WebRuntime运行时支撑包之中)

具体的细节工作参考我们提供的 一分钟视频教程 操作:

                                           让.NET工程拥有互联网基因

WebRuntime是什么?

WebRuntime是一个开源项目。这个项目的核心目标是:让开发者将现代浏览器做为一个应用的起点。不同于现有的基于浏览器控件(CEF、WebView2)以及Electron等方案,WebRuntime完整的保留了Chromium的全部代码,这一点从根本上确保一个具体的应用包含(但不限于)Web浏览器的所有功能。对.NET开发者而言,在代码上,其工作量就是一行代码 的改变,即

            Application.Run(new Form1());

修改为

            Universe.Cosmos.Run();

注意,在这里我们忽略了“new Form1()”。这一行的替换,给替换之后的.NET应用带来以下几个重要改变:

  1. .NET桌面应用转化为以Chromium为基础的桌面应用,自然包含现代Web Browser全部功能。与标准浏览器的差异是:我们允许第一个窗口是用户开发的自定义窗口(标准浏览器每一次打开的都是浏览器窗口),同时我们允许开发者在Web页面之中创建不同类型的Win32窗体,也就是说用户启动程序的时候,会首先显示开发者指定的窗口做为应用程序的主窗口,当用户启动应用程序的第二个实例,或者在程序中打开一个新的URL,会激活新的浏览器窗口;
  2. .NET Framework类对象做为DOM元素,特别是WinForm、UserControl等GUI对象可以作为DOM元素显示在Web页面之上;
  3. .NET与Javascript交互操作,这一点确保Web页面之中,Javascript操作.NET对象、处理响应.NET对象的事件;
  4. Cloud WinForm,允许Web页面之中定义任意多个动态WinForm元素,使得开发者可以基于Javascript脚本实例化任意数量的Form对象,类似于Office VBAForm。

具体案例

我们在 二进制包(下载TheUniverse.zip) 之中,提供了最简单的示范应用FirstApp.exe,开发者可以在Git上下载FirstApp源代码,或者自己创建一个最简单的工程。

正确运行FirstApp.exe,我们需要一个初始化WebPage:”FirstApp.index.html“,页面的代码如下:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>欢迎您进入一个全新的.NET世界, 我是您的朋友WebRuntime</title>
    <link rel="icon" href="webpage/app.png" sizes="32x32">
    <script type="text/javascript">
        function OpenAppURL1() {
            cosmos.openUrl("host:webpage/WebApp1.html", 100);
        }
        function OpenAppURL2() {
            cosmos.openUrl("host:webpage/WebApp2.html", 100);
        }
        function OpenAppURL3() {
            cosmos.openUrl("host:webpage/WebApp3.html", 100);
        }
        function OpenAppURL4() {
            cosmos.openUrl("host:webpage/WebApp4.html", 100);
        }
        function OpenAppURL5() {
            cosmos.openUrl("host:webpage/WebApp5.html", 100);
        }
        function OpenAppURL6() {
            cosmos.openUrl("host:webpage/WebApp6.html", 100);
        }

        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>
</head>
<body>
    <cosmos>
        <!-- Define new DOM elements -->
        <define tagName="mainWindow"></define>
        <define tagName="application"></define>
        <define tagName="webViewport"></define>
        <!-- End Define new DOM elements -->
        <!-- The "application" element is required, it can provide application-level configuration. -->
        <application>
            <ntp>
                <winNucleus>
                    <xobj id='grid' rows='1' cols='2' width='350,350,' splitterwidth='6'>
                        <xobj objid="FirstApp.Form1,host"></xobj>
                        <xobj objid="nucleus"></xobj>
                    </xobj>
                </winNucleus>
            </ntp>
            <defaultworkbench>
                <winNucleus>
                    <xobj id='grid' rows='1' cols='2' width='350,350,' splitterwidth='6'>
                        <xobj objid="FirstApp.Form1,host"></xobj>
                        <xobj objid="nucleus"></xobj>
                    </xobj>
                </winNucleus>
            </defaultworkbench>
            <urls>
                <url url="host:WebPage/sunny.html"></url>
            </urls>
        </application>
        <mainWindow objid="FirstApp.Form1,host" caption="The Universe" width="2400" height="1600" id="mainForm">
            <panel1 id="mainworkclient">
                <default>
                    <winNucleus>
                        <xobj style="39" activepage="1">
                            <xobj caption="Cloudx Application" id='Splitter1' rows='1' cols='2' height='250,' width='350,350,' borderwidth='0' splitterwidth='6'>
                                <xobj objid="nucleus">
                                </xobj>
                                <xobj objid="" id="Sunny_ntpctrl">
                                </xobj>
                            </xobj>
                            <xobj caption="Common Web Runtime for Application" url="host"></xobj>
                        </xobj>
                    </winNucleus>
                </default>
            </panel1>
        </mainWindow>
        <webViewport>
            <winNucleus>
                <xobj rows="1" cols="2" width="750," id="xxx" caption="test caption">
                    <xobj objid="FirstApp.Form1,host" id="navCtrl">
                    </xobj>
                    <xobj objid="nucleus" id="mainClient">
                    </xobj>
                </xobj>
            </winNucleus>
        </webViewport>
    </cosmos>
    <strong style="font-size:32px; color:black">欢迎<i style="color:fuchsia">您来到</i><i style="color:blue">FirstApp的 </i><b style="color:coral">.NET桌面软件生态世界</b>!</strong>
    <h1 style="font-size: 16px; color:midnightblue"><i style="font-size:32px; color:blue">点击以下超链接</i> 体验全新的Web页面...</h1>
    <p>
        <a href="javascript:void(0);" onclick="OpenAppURL1();" style="font-size:16px;color:firebrick"><b>The First WebPage for Application</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURL2();" style="font-size:16px;color:blueviolet"><b>让您的应用系统拥有互联网基因</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURL3();" style="font-size:16px;color:forestgreen"><b>新的Web页面,新的表现力</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURL4();" style="font-size:16px;color:brown"><b>让Web应用与桌面应用之间的鸿沟渐渐消失</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURL5();" style="font-size:16px;color:cadetblue"><b>冲破约束,一片新天地呼之欲出</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURL6();" style="font-size:16px;color:dodgerblue"><b>您可以做更多的事情,你的Web你做主</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURLAsSubPage1();" style="font-size:16px;color:saddlebrown"><b>页面无处不在</b></a>
        <hr />
        <a href="javascript:void(0);" onclick="OpenAppURLAsSubPage2();" style="font-size:16px;color:springgreen"><b>您的创造力无限……</b></a>
        <hr />
    </p>
</body>
</html>

 这里的规则是:每个”exeName.exe“需要一个初始化页面:”exeName.index.html“。

有了FirstApp.index.html,现在可以运行FirstApp.exe了。

                                         FirstApp运行视频

启动FirstApp.exe,我们看到:

对比一下Form1设计器界面:       

我们发现,运行时窗体增加了很多元素,这一切都是如下Web页面元素:

        <mainWindow objid="FirstApp.Form1,host" caption="The Universe" width="2400" height="1600" id="mainForm">
            <panel1 id="mainworkclient">
                <default>
                    <winNucleus>
                        <xobj style="39" activepage="1">
                            <xobj caption="Cloudx Application" id='Splitter1' rows='1' cols='2' height='250,' width='350,350,' borderwidth='0' splitterwidth='6'>
                                <xobj objid="nucleus">
                                </xobj>
                                <xobj objid="" id="Sunny_ntpctrl">
                                </xobj>
                            </xobj>
                            <xobj caption="Common Web Runtime for Application" url="host"></xobj>
                        </xobj>
                    </winNucleus>
                </default>
            </panel1>
        </mainWindow>

 产生的效果,其中,panel1是Form1上的一个控件,这里给出的设计是,当Form窗体页面化的时候,其中心位置的控件,可以被Web页面进一步动态化。点击Form1窗体上给出的一组”超链接“,可以直接激活内置的浏览器:

 (应用页面,是由.NET控件与标准DOM元素合成的)

(调试界面) 

(新标签页 New TabPage) 

我们在FirstApp.index.html的如下部分确定每个新页面的基本样式:

        <application>
            <ntp>
                <winNucleus>
                    <xobj id='grid' rows='1' cols='2' width='350,350,' splitterwidth='6'>
                        <xobj objid="FirstApp.Form1,host"></xobj>
                        <xobj objid="nucleus"></xobj>
                    </xobj>
                </winNucleus>
            </ntp>
            <urls>
                <url url="host:WebPage/sunny.html"></url>
            </urls>
        </application>

(ntp 节点,ntp=”New TabPage“)

我们注意到,Universe.Cosmos.Run()是无参数的,所以,应用系统启动的时候不会创建任何GUI对象。后续为了行文方便,我们假设已经有了一个符合我们条件的FirstApp.exe,这里FirstApp您大可以替换成您自己选择的任何C# WinForm工程。我们希望FirstApp里面的Form1是如下方式设计的:

        在下载的二进制包之中,提供了一个有一些复杂度的初始化页面”FirstApp1.index.html“,您可以将这个文件替换FirstApp.index.html(修改一下名字),看看更加综合的效果。

让应用适配不同的应用场景

我们注意到,新的.NET应用的执行入口:

            Universe.Cosmos.Run();

由于Run方法没有参数,事实上应用程序的主窗体是由初始化页面”AppExeName.index.html“的如下元素确定的:

        <mainWindow objid="FirstApp.Form1,host" caption="The Universe" width="2400" height="1600" id="mainForm">
            <panel1 id="mainworkclient">
                <default>
                    <winNucleus>
                        <xobj style="39" activepage="1">
                            <xobj caption="Cloudx Application" id='Splitter1' rows='1' cols='2' height='250,' width='350,350,' borderwidth='0' splitterwidth='6'>
                                <xobj objid="nucleus">
                                </xobj>
                                <xobj objid="" id="Sunny_ntpctrl">
                                </xobj>
                            </xobj>
                            <xobj caption="Common Web Runtime for Application" url="host"></xobj>
                        </xobj>
                    </winNucleus>
                </default>
            </panel1>
        </mainWindow>

(注意元素panel1,当然,可以类似增加panel2,需要在Form上存在对应的控件)

我们后续的系列文章会系统介绍这个mainwindow元素,这里应该可以看出一些线索,也就是说,主窗体是可以描述的,意味着主窗体的”多样化“。当我们将exe复制到不同的目录,匹配上不同的初始化页面,那么应用场景也就完全不一样了,事实上,mainwindow有一个”objid“属性,这个属性其实就是一个.NET对象的”QualifiedName“,基于这个属性,我们可以将一个应用系统的主窗口依据页面而动态化。

        由于应用是由第一个页面启动的,一个页面里面就可以组织更多的页面,进而应用系统的具体组织原则就发生了变化,如果我们将mainwindow的子元素(child element)去掉,那么应用系统就是没有替换Run方法之前的原始系统,也就是说,原始应用系统就是一个”特解“,非常类似于微分方程,依据不同的”初值条件”以及”边值条件“求特解。

        由于WebRuntime进行了内部处理,我们发现,大量的已存在的应用系统,经过一行代码修改之后,都可以建立属于自己的应用生态,这个效果使得那些已存在的应用系统在互联网时代得以找到新的增值空间,从这个角度看,互联网技术盘活了绝大多数技术资源。也就是说,完全可以在原有模型基础之上做基于Web的后续增值开发。

基于应用的Web页面

        由于新的应用就是一款现代浏览器,不同于标准浏览器,应用系统支持.NET GUI元素(Form、Control、WPF控件……)与标准Web DOM元素形成新的Web页面,这一点给宿主应用系统增加了无限的扩展能力,特别,我们推广浏览器子窗口模式,这一点使得一个GUI对象,例如WinForm对象基于一组标签灵活的组织具体的应用:

(基于“浏览器标签”在GUI对象之中组织应用,
使得软件更加友好、富于表现力,同时可以更好的动态控制)
 

 面向应用的页面,可以说是标准页面的自然扩展,这个特色使得应用系统的适配性更强,是一种强大的基于内容生态的软件组织机制。

Cloud WinForm:强大的Web生产力

        我们在设计FirstApp这个示范应用的时候,在Form1上增加一个panel对象,我们设置了这个控件的anchor属性,这个对象,运行时产生了变化,取决于如下描述:

            <panel1 id="mainworkclient">
                <default>
                    <winNucleus>
                        <xobj style="39" activepage="1">
                            <xobj caption="Cloudx Application" id='Splitter1' rows='1' cols='2' height='250,' width='350,350,' borderwidth='0' splitterwidth='6'>
                                <xobj objid="nucleus">
                                </xobj>
                                <xobj objid="" id="Sunny_ntpctrl">
                                </xobj>
                            </xobj>
                            <xobj caption="Common Web Runtime for Application" url="host"></xobj>
                        </xobj>
                    </winNucleus>
                </default>
            </panel1>

事实上,WebRuntime的基本要求是:这里只需要一个dock属性为“dockfill”或者“none”的任何一个控件,未必一定是panel。WebRuntime将每一个Form对象看做是动态Form,如果Form上包含一个或者一组dock属性为“dockfill”或者“none”的控件,那么如上的描述都是成立的,复杂度取决于winNucleus元素的具体结构,我们将这类Form称之为“Cloud WinForm”,我们在后续的介绍之中,会详细的给予解释,WinForm的这种动态描述能力,不限于体现在Web页面之中,然而由于Javascript的缘故,页面之中的这类元素,使得.Net Framework的GUI对象在应用系统的Web模型之中体现出强大的创造力。

(Cloud WinForm以及面向应用的Web页面将使得您的应用系统
基于Web技术变得比原始系统拥有更加强大的动态表现力)
 

总结

我们看到了WebRuntime给一个普通桌面应用带来的几个基本变化:

  1. 每个.NET应用在完整保留原有结构的基础上,用最简明的途径给每个应用提供内置的全功能Chromium-Based互联网浏览器;
  2. 每个浏览器都可以将.NET GUI元素当作Web页面的DOM元素,Javascript可以响应这些GUI元素的事件;
  3. 提供基于目录的部署机制,使得没有文件夹之下,应用都有完全不同的Web配置、部署;
  4. 当用户工程之中,Application.Run被Cosmos.Run替换之后,用户的系统就完全实现基于Web技术的应用扩展机制,拥有自己的Web生态,每一个WinForm窗体都可以基于Web技术实现Web页面类似的动态表现力,在FirstApp.exe之中,我们看到了panel1表现出的动态性;
  5. 事实上,如FirstApp.exe所展示的每一款.NET桌面应用如同标准浏览器一样,都是一个Web内容引擎,也就是说,WebRuntime揭示出桌面应用的双重性,其一是本地特性、其二是Web特性。
  6. 当WebRuntime被应用系统引用之后,扩展性就是应用系统的基本属性,应用系统的原有模型被Web技术无限扩大了,这一点与原有系统形成本质的差异;
  7. FirstApp是一个极简的WinForm示范,事实上互联网时代,.NET桌面应用的潜力应该是“极为广阔“,如果浏览器是最小的应用,那么WebRuntime就会给开发者带来无限的创造力……

以上几个方面的变化,足以确保.NET应用系统拥有完整的“新Web应用生态”,WebRuntime允许存在独立的浏览器窗口以及动态Cloud WinForm,这一切使得原始模型得到极大的外延扩展能力,这一点确保互联网环境下,应用系统可以满足“应用内容“在运营过程之中适应不断增长的需求,也可以确保应用系统有足够的技术资源、人力资源以适应不断变化的网络环境。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AIGC Browser

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值