蛙蛙推荐:蛙蛙浏览器
摘要:google推出了自己的网页浏览器,现在web浏览器的竞争更激烈了,各有各的用户群。其实有另一个领域没有多少竞争,那就是应用程序浏览器,今天给大家演示的蛙蛙浏览器,不仅可以浏览网页,还可以浏览.net应用程序,通信方面你可以使用webservice,remoting,本地存储你可以使用用户隔离存储区,本地数据库,要想播放多媒体也可以,总之比一般网页浏览器NB。

【概述】
用户刚安装完蛙蛙浏览器后什么都不能用,就像一个清空了本地缓存的IE。用户要想使用某些应用,可以通过一个web服务来获取应用描述,这个web服务是一个应用目录列表,相当于互联网的站点导航网站,你对哪个应用感兴趣就可以打开这个应用,相当于用网页浏览器打开网页。当然用户可以定制自己的应用列表,不必每次都去应用目录去加载所有的应用列表。
应用目录会提供应用程序集的地址、类型等其它一些信息,这些程序集是保存在远程服务器上的,地址类似于http://www.fetionmm.com/dllcache/application.dll这样的地址,.net的反射功能可以从远程加载程序集,并缓存到本地的C:/WINDOWS/assembly/download目录下,默认从网络上下载缓存的程序集权限是很低的,可以用代码安全工具设置来完全信任某一公钥或者某一网站上下载的程序集,这样你浏览的应用就可以访问本地网络,打印机等资源了,关于CAS的概念及配置,大家参考MSDN。然后网络上下载的程序集,如果远程的程序集版本更新,应该会自动加载缓存到本地,所以自动更新的问题也解决了。
远程的程序集其实主要是一些用户控件,而应用程序浏览器保留了一些面板和菜单占位符让这些应用来使用,子应用要和浏览器交互,所以子应用和浏览器应该各有一个接口,能互相调用,比如说子应用要在应用浏览器的菜单项里添加合并自己应用的特有菜单,要改变浏览器的标题,状态栏,要通过应用浏览器的统一异常处理程序来处理子应用内的异常等。这就相当于javascript能访问浏览器的BOM对象一样,我们的浏览器也有一些API供子应用来调用。还有就是浏览器也应该能访问子应用的一个公共接口,比如说在在应用框架切换应用的时候通知当前的 应用保存自己的应用状态等。
我们是接着上一篇帖子来做这个应用浏览器的,我们会在获取应用列表的时候填充“转到”菜单的下拉菜单项,并动态添加左下角的手风琴功能菜单条,我们会在子应用加载的时候动态合并菜单,并且在工具栏的新建按钮里添加子应用的新建类型菜单,并在手风琴工具条的上方添加子应用的左侧功能导航条,就像outlook在邮件应用的时候左边是个邮件文件夹的树,在联系人应用的时候左边是一些联系人视图切换的按钮条。我们也一样,不同的应用有不同的功能导航条。
另外MDI风格的桌面应用已经过时,现在都是全窗口应用,比如word,你新建一个word文档,新的文档在一个独立的主窗口里,有所有word的菜单,而不是在一个MDI的子窗口里,我们也顺应时代潮流,比如本例,有一个“我的RSS订阅”和“我的收藏”应用,你完全可以在主窗口里打开RSS订阅来看RSS新闻,然后新建窗口里来浏览“我的收藏”应用,来看自己收藏的网页。

【项目介绍】
WawaAppCommon:里面有应用浏览器和子应用的的接口定义以及一些XML序列化和图片序列化的帮助类。
WawaAppWebService:这是个web服务,用来给用户进行身份验证和返回应用目录列表,前者目前是假的,直接返回一个guid字符串作为登录令牌。
WawaAppClient:这是应用程序浏览器,包括一个登录窗体,主浏览器窗体和关于窗体。
WawaApplications:示例了两个子应用,一个是RSS订阅,一个是我的收藏。

【web服务】
public class AppFunctionality
{
    public string Name;
    public string MenuText;
    public string ToolbarIconString;
    public string TooltipText;
    public string AssemlyUrl;
    public string TypeName;
}
[WebMethod]
public AppFunctionality[] GetFunctionalityCatalog(string token)
{
    List<AppFunctionality> list = new List<AppFunctionality>();

AppFunctionality app = new AppFunctionality();
    app.Name = "我的RSS订阅";
    app.MenuText = "我的RSS订阅";
    app.ToolbarIconString = ImageSerializationHelper.Image2String(Resource.Folder24);
    app.TooltipText = "可以订阅RSS新闻";
    app.AssemlyUrl = @"E:/huhao/workfloder/src/WawaAppBrowser/WawaApplications/bin/Debug/WawaApplications.dll";
    app.TypeName = "WawaSoft.WawaApp.Applications.RssReaderApp";
    list.Add(app);

app = new AppFunctionality();
    app.Name = "我的收藏";
    app.MenuText = "我的收藏";
    app.ToolbarIconString = ImageSerializationHelper.Image2String(Resource.Tasks24);
    app.TooltipText = "可以收藏网页链接";
    app.AssemlyUrl = @"E:/huhao/workfloder/src/WawaAppBrowser/WawaApplications/bin/Debug/WawaApplications.dll";
    app.TypeName = "WawaSoft.WawaApp.Applications.UserControl1";
    list.Add(app);

return list.ToArray();
}
客户端通过调用以上的web服务来获取应用列表,然后才加载到“转到”表菜的子菜单单和手风琴功能条。
【接口定义】
public interface IBrowser
{
    string Caption { get; set;}
    string Status { get; set;}
    void HandleException(Exception ex);
    DialogResult Alert(string message);
    DialogResult Alert(string message, MessageBoxIcon icon);
    DialogResult Alert(string message, MessageBoxButtons buttons, MessageBoxIcon icon);
    void AddMenuItem(ISubApplication subApplication,string path, ToolStripMenuItem item);
    void AddNewMenuItem(string Text,Image image, EventHandler handler);
    void SetLeftControl(Control leftControl);
}
public interface ISubApplication
{
    void SetBrowser(IBrowser browser);
}
【浏览器接口实现】
  #region IBrowser 成员

public string Caption
  {
      get { return _caption; }
      set
      {
          _caption = value;
          Text = value != "" ? string.Format("{0}-{1}", _caption, BaseCaption) : BaseCaption;
      }
  }

public string Status
  {
      get
      {
          return lblStatus.Text;
      }
      set { lblStatus.Text = value != "" ? value : "就绪"; }
  }

public void HandleException(Exception ex)
  {
      Alert(string.Format("{0}-{1}:{2}",
          ex.GetType(), ex.Message, ex.StackTrace));
  }

public DialogResult Alert(string message)
  {
      return Alert(message, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  }

public DialogResult Alert(string message, MessageBoxIcon icon)
  {
      return Alert(message, MessageBoxButtons.OK, icon);
  }

public DialogResult Alert(string message, MessageBoxButtons buttons, MessageBoxIcon icon)
  {
      return MessageBox.Show(this, message, BaseCaption, buttons, icon);
  }

public void AddMenuItem(ISubApplication subApplication, string path, ToolStripMenuItem item)
  {
      string lookForPath = path.Replace("&", "");
      ToolStripMenuItem addTo = null;
      foreach (ToolStripMenuItem topLevel in menuStrip1.Items)
      {
          if (string.Compare(topLevel.Text.Replace("&", ""), lookForPath) == 0)
          {
              addTo = topLevel;
              break;
          }
      }
      if (addTo == null)
      {

addTo = new ToolStripMenuItem(path);
          menuStrip1.Items.Insert(5, addTo); //添加在工具菜单后面
          _subApplicationMenus.Add(addTo);
      }
      else
      {
          ToolStripItem toolStripItem = addTo.DropDownItems[addTo.DropDownItems.Count - 1];

bool needSep = !(_subApplicationMenus.Contains(toolStripItem));
          if (needSep)
          {
              ToolStripSeparator sep = new ToolStripSeparator();
              addTo.DropDownItems.Add(sep);
              _subApplicationMenus.Add(sep);
          }
      }
      addTo.DropDownItems.Add(item);
      _subApplicationMenus.Add(item);
  }
  public void AddNewMenuItem(string text,Image image, EventHandler handler)
  {
      ToolStripMenuItem toolStripMenuItem =
          new ToolStripMenuItem(text,image);
      toolStripMenuItem.Click += handler;
      menubtnNew.Visible = true;
      menubtnNew.DropDownItems.Add(toolStripMenuItem);
      toolStripMenuItem =
          new ToolStripMenuItem(text,image);
      toolStripMenuItem.Click += handler;
      tsbNew.DropDownItems.Add(toolStripMenuItem);
  }

public void SetLeftControl(Control leftControl)
  {
      leftControl.Dock = DockStyle.Fill;
      menuStrip1.Focus();
      splitContainer2.Panel1.Controls.Add(leftControl);
  }

#endregion
【子应用接口实现示例】
#region ISubApplication 成员
public void SetBrowser(IBrowser browser)
{
    _browser = browser;
    ToolStripMenuItem item = new ToolStripMenuItem("新建订阅");
    item.Click += delegate { AddRss(); };
    Browser.AddMenuItem(this, "RSS订阅", item);

browser.AddNewMenuItem("订阅", Resource.Shortcut24, delegate { AddRss(); });

item = new ToolStripMenuItem("更新订阅");
    item.Click += delegate { RefreshRss(); };
    Browser.AddMenuItem(this, "操作", item);

LeftRssReaderPanel leftRssReaderPanel = new LeftRssReaderPanel(this);
    Browser.SetLeftControl(leftRssReaderPanel);
    _leftRssPanel = leftRssReaderPanel;
}
#endregion 
其它主要的代码都在MainForm里面,比如动态加载控件,如何防止获取焦点的控件的父控件的控件集清空早晨整个窗体无法获取焦点的问题,如何在合适的地方加载合并菜单,如何添加菜单分割条,如果根据应用个数动态设置手风琴的toolstrip的高度等。
【截图如下】

【小节】
微软给咱们的只是工具,得用好才能赚到钱,winform,webform微软都给你了,就是给你多一些选择的机会,至于用户的选择,有时候要靠用户教育的,如果整个企业都是基于微软的管理,那么做一个应用程序浏览器,利用域脚本分发给每一个员工是很简单的事情,以后程序更新可以用到.net的Clickonece技术来达到自动部署,根本不费什么力,企业内的所有应用不可能都弄成web的,比如本地打印,尤其是套打,你用web来实现很麻烦的,定位你可以用css精确定位,可你能控制的了浏览器的打印页边距吗,那个得修改注册表才可以,你浏览器又没有相关的API去修改windows的注册表,winform做这个就很方便了,当然你web上弄一些报表控件也能实现,但那就不是web了。再说了windows支持无人值守安装,在无人值守安装里可以默认装一些初始化的员工软件的,所以我的结论是winform在企业内还是很有优势的,关键得大家去推广。

下载地址如下:
http://files.cnblogs.com/onlytiancai/WawaAppBrowser.7z

测试的时候注意修改functionality.xml文件的程序集的路径,另外app.config文件里的UseLocalAppCategory配置表示使用functionality.xml文件来加载应用列表,如果设置为false,必须得设置一个可用的获取应用目录的web服务地址,也在app.config里设置。
【参考】
windows企业应用高级编程

蛙蛙推荐:蛙蛙浏览器相关推荐

  1. 蛙蛙推荐:蛙蛙牌网页捕捉器

    蛙蛙推荐:蛙蛙牌网页捕捉器 摘要:你有没有看到一篇好文章想保存到本地,有没有想过只保存网页选中的部分而不要那些不必要的导航和广告,本贴告诉你达到这个目的的思路及主要代码. 思路:首先我们要获取到所有I ...

  2. 蛙蛙推荐:蛙蛙教你文本聚类 - 蛙蛙王子 - 博客园

    蛙蛙推荐:蛙蛙教你文本聚类 - 蛙蛙王子 - 博客园 蛙蛙推荐:蛙蛙教你文本聚类 - 蛙蛙王子 - 博客园 蛙蛙推荐:蛙蛙教你文本聚类 摘要:文本聚类是搜索引擎和语义web的基本技术,这次本蛙和大家一 ...

  3. 蛙蛙推荐:蛙蛙教你文本聚类

    蛙蛙推荐:蛙蛙教你文本聚类 摘要:文本聚类是搜索引擎和语义web的基本技术,这次本蛙和大家一起学习一下简单的文本聚类算法,可能不能直接用于实际应用中,但对于想学搜索技术的初学者还是有一定入门作用的.这 ...

  4. 蛙蛙推荐:蛙蛙牌软件注册码算法

    蛙蛙推荐:蛙蛙牌软件注册码算法 摘要:辛辛苦苦写个共享软件,又怕被人破解,所以就会想到用注册码的方式来激活软件.本蛙给大家一个简单的思路来实现软件注册码算法,当然.net做的东西很容易被人破解,反编译 ...

  5. 强烈推荐!CSDN浏览器助手,让你的浏览器上10个档次!

    文章目录 前言 1. 初体验 2. 下载安装 3. 强大的功能 1. 浏览器门面,换肤功能 2. 便捷的操作,个性化网站入口 3. 超懂我的操作,快速搜索 4. 超方便的操作,常用工具 5. 极致的用 ...

  6. 蛙蛙推荐:蛙蛙学习asp.net总结(之一)

    认识Microsoft公司的Asp.net有一段时间了,感觉asp.net确实在功能方面和性能方面比asp有了很大的改进(之前,我一直在写asp程序),并总结了一些内容,这里和大家分享一下.由于笔者经 ...

  7. 蛙蛙推荐:蛙蛙教你解析网络包

    蛙蛙教你解析网络包 摘要:做网络应用,封包,解包是家常便饭,但如何做到准确.稳定而且性能好,却不太容易做到,这次和大家分享一下我在解析网络包上的经验. 思路:设计一个网络协议,一般都会分包,一个包就相 ...

  8. 蛙蛙推荐:蛙蛙牌广告鼓励算法

    摘要:不知道有多少人去研究google,阿里妈妈的广告作弊算法,抓包.分析http头,分析参数,分析cookies,甚至分析鼠标的点击序列,写钩子用程序去点广告,或者去模仿用户行为,我说这太麻烦了.不 ...

  9. 蛙蛙推荐:蛙蛙教你发明一种新语言之二--代码生成

    摘要 上一篇里我们构建了语法树,但他并不能执行,还要把它转换成可执行的代码.语法树是抽象的,可以把它转换到各种平台的执行文件,但我们现在只关注它是如何生成一个CLR的可执行文件. IL指令介绍 书接上 ...

最新文章

  1. 基于.NET平台常用的框架整理(转)
  2. 软银准备以超400亿美元向英伟达出售Arm,交易最快下周达成
  3. java bufferedwriter会自动创建文件吗_Java中为什么会有包装类?自动拆装箱必要吗?关于Wrapping Class这是重点!...
  4. 如何生成随机的字母数字字符串?
  5. c语言在线读程序,用C语言编写简单程序.doc
  6. android开发之嵌入广告
  7. 竖着的seekbar_自定义竖着的SeekBar | 学步园
  8. openg 通用扫描画线算法
  9. (原创)巧用通道作颜色网
  10. 户外运动手持GPS设备常识汇总
  11. 基于C# winform实现随机点名小工具(支持csv导入)
  12. 服务器数据恢复过程(服务器数据恢复通用方法)
  13. Android Studio 一个工程打包多个不同包名的APK
  14. 第三集 怪物学院 第十八章
  15. linux设备的uuid,Linux设备中的UUID
  16. L1-034 点赞 (20分)
  17. 蓝桥杯 历届试题 小数第n位(C语言)
  18. python seo cms_巧用帝国CMS系统变量提升网站用户体验 完善SEO优化
  19. jmeter压测指标
  20. echarts中配置图例形状、图标宽高、图标和文字间距、图例位置、文字颜色、字体大小等基础配置

热门文章

  1. 从源码看ANDROID中SQLITE是怎么通过CURSORWINDOW读DB的
  2. 一步一步实现WPF透明化窗口
  3. 计算机考研代码854,哈工大计算机考研考纲854计算机基础
  4. 考计算机854的学校,2020年哈尔滨工业大学854计算机基础硕士研究生入学考试科目大纲...
  5. 空间点过程与随机测度(一):从数星星说起
  6. SDX55如何使用adb命令读写AT指令
  7. dell G7 7588安装ubuntu双系统
  8. AMD XILINX宣布2023年产品涨价8%
  9. 数据库高并发的解决方案
  10. OpenCV提取图像中的垂直线(或者水平线)