博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 封装miniblink 使用HTML/CSS/JS来构建.Net 应用程序界面和简易浏览器
阅读量:4570 次
发布时间:2019-06-08

本文共 23855 字,大约阅读时间需要 79 分钟。

MiniBlink的作者是 龙泉寺扫地僧

miniblink是什么?   (抄了一下 龙泉寺扫地僧 写的简洁)

Miniblink是一个全新的、追求极致小巧的浏览器内核项目,

其基于chromium最新版内核,去除了chromium所有多余的部件,只保留最基本的排版引擎blink。
Miniblink保持了10M左右的极简大小,是所有同类产品最小的体积,同时支持windows xp、npapi。

为什么要做miniblink?

市面上作为嵌入的组件的可用的浏览器内核,不外乎这几个:webkit、cef、nwjs、electron。

cef:优点是由于集成的chromium内核,所以对H5支持的很全,同时因为使用的人也多,各种教程、示例,资源很多。但缺点很明显,太大了。最新的cef已经夸张到了100多M,还要带一堆的文件。同时新的cef已经不支持xp了(chromium对应版本是M49)。而且由于是多进程架构,对资源的消耗也很夸张。如果只是想做个小软件,一坨文件需要带上、超大的安装包,显然不能忍受。

nwjs,或者最近大火的electron:和cef内核类似,都是chromium内核。缺点和cef一模一样。优点是由于可以使用nodejs的资源,同时又自带了各种api的绑定,所以可以用的周边资源非常丰富;而基于js的开发方案,使得前端很容易上手。所以最近N多项目都是基于nwjs或electron来实现。例如vscode,atom等等。

原版webkit:现在官网还在更新windows port,但显然漫不在心,而且最新的webkit也很大了,超过20几M。最关键的是,周边资源很少,几乎没人再基于webkit来做开发。同时由于windows版的saferi已经停止开发了,所以用webkit就用不了他的dev tools了。这是个大遗憾。

WKE:这是个很老的webkit内核的裁剪版了。小是小,但bug太多了。

那么关键点来了,使用miniblink有啥好处呢??

首先,miniblink对大小要求非常严格。原版chromium、blink里对排版渲染没啥大用的如音视频全都被砍了,只专注于网页的排版和渲染。甚至为了裁剪大小,我不惜使用vc6的crt来跑mininblink。这个也算前无古人后无来者了。

其次,miniblink紧跟最新chromium,这意味着chromium相关的资源都可以利用。在未来的规划里,我是打算把electron的接口也加上的,这样可以无缝替换electron。使用miniblink的话,开发调试时用原版electron,发布的时候再替换掉那些dll,直接可以无缝切换,非常方便。

 

miniblink如何裁剪到这么小?

这个比较复杂了。主要就是把blink从chromium抽离了出来,同时补上了cc层(硬件渲染层)。现在的blink,已经不是当年的那个webkit了,渲染部分全走cc层,复杂无比。我这大半年都在重写他那个蛋疼又复杂的cc层。

和webkit比,miniblink架构有什么优势

现在的webkit版本,已经比miniblink落后太多了。blink一直在加入各种极富创造力和想象力的功能、组件。例如,blink早就加入多线程解析html token、blink gc回收器、多线程录制回放渲染机制。这些能让blink的解析渲染速度极大提升。下一次,我会先开源出blink gc组件,这东西很有意思,在c++里硬是搞出了一个垃圾回收机制,能让你像写java一样写c++。

 

miniblink 开源地址:https://github.com/weolar/miniblink49

 

我们可以通过miniblink做桌面应用的UI,超小的附加dll,压缩之后大约5M,比起Cefsharp 小太多了。VSCode也是用  Electron 网页开发的

Html开发UI和WPF对比有什么优势?

1、 Html 前端资源丰富,各种框架

2、 会Html的人比会WPF的人多太多了,入门简单

3、.Net2.0照样可以用

4、网站和桌面程序界面可以统一,甚至大部分前端代码复用

 

资源消耗方面,和WPF差不多,毕竟浏览器也是内存消耗大户

 

不过对比electron 这种纯 Html CSS + js的,我更喜欢 用C# 代替JS 做业务逻辑,我感觉JS写大项目 代码比较乱,维护比C#麻烦。所以 JS做前端辅助比较合适,业务逻辑用C#实现

 

 

 

接下来,我写个简单的MiniBlink封装案例!更多功能你们可以自行封装 或者 看看 

 

采用 PInvoke 和Winform封装方式,MiniBlink对外提供的接口主要在 wke.h ,miniblink 的dll可以通过GitHub源码编译出来。具体封装规则,你们可以百度查查看

 

1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Runtime.InteropServices;  6 //by:DSkin  7   8 namespace MiniBlink  9 { 10     public static class MiniblinkPInvoke 11     { 12         const string miniblinkdll = "node.dll"; 13  14  15         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 16         public static extern void wkeSetHandle(IntPtr webView, IntPtr wnd); 17  18         [DllImport(miniblinkdll, CharSet = CharSet.Unicode)] 19         public static extern IntPtr wkeGetStringW(IntPtr @string); 20  21         [DllImport(miniblinkdll, CharSet = CharSet.Unicode)] 22         public static extern IntPtr wkeToStringW(IntPtr @string); 23  24         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 25         public static extern IntPtr wkeGetString(IntPtr @string); 26  27         [DllImport(miniblinkdll)] 28         public static extern void wkeSetDebugConfig(IntPtr webView, string debugString, IntPtr param); 29  30         [DllImport(miniblinkdll)] 31         public static extern Int64 wkeRunJSW(IntPtr webView, [In] [MarshalAs(UnmanagedType.LPWStr)] string script); 32  33         [return: MarshalAs(UnmanagedType.I1)] 34         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 35         public static extern bool wkeFireMouseEvent(IntPtr webView, uint message, int x, int y, uint flags); 36  37         [return: MarshalAs(UnmanagedType.I1)] 38         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 39         public static extern bool wkeFireMouseWheelEvent(IntPtr webView, int x, int y, int delta, uint flags); 40  41         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 42         [return: MarshalAs(UnmanagedType.I1)] 43         public static extern bool wkeFireKeyUpEvent(IntPtr webView, uint virtualKeyCode, uint flags, [MarshalAs(UnmanagedType.I1)] bool systemKey); 44  45         [return: MarshalAs(UnmanagedType.I1)] 46         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 47         public static extern bool wkeFireKeyDownEvent(IntPtr webView, uint virtualKeyCode, uint flags, [MarshalAs(UnmanagedType.I1)] bool systemKey); 48  49         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 50         [return: MarshalAs(UnmanagedType.I1)] 51         public static extern bool wkeFireKeyPressEvent(IntPtr webView, uint charCode, uint flags, [MarshalAs(UnmanagedType.I1)] bool systemKey); 52  53         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 54         public static extern void wkeSetFocus(IntPtr webView); 55  56         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 57         public static extern void wkeKillFocus(IntPtr webView); 58  59         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 60         public static extern void wkeResize(IntPtr webView, int w, int h); 61  62         [DllImport(miniblinkdll)] 63         public static extern IntPtr wkeCreateWebView(); 64  65         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 66         public static extern void wkeDestroyWebView(IntPtr webView); 67  68         [DllImport(miniblinkdll)] 69         public static extern void wkeInitialize(); 70  71         [DllImport(miniblinkdll)] 72         public static extern void wkeLoadFile(IntPtr webView, [In, MarshalAs(UnmanagedType.LPWStr)] string filename); 73  74         [DllImport(miniblinkdll)] 75         public static extern void wkeLoadHTML(System.IntPtr webView, [In()] [MarshalAs(UnmanagedType.LPStr)] string html); 76  77         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 78         public static extern void wkeOnURLChanged2(IntPtr webView, UrlChangedCallback2 callback, IntPtr callbackParam); 79  80         [DllImport(miniblinkdll, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] 81         public static extern void wkeLoadURLW(IntPtr webView, [In, MarshalAs(UnmanagedType.LPWStr)] string url); 82  83         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 84         public static extern void wkeOnPaintUpdated(IntPtr webView, wkePaintUpdatedCallback callback, IntPtr callbackParam); 85  86         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 87         public static extern void wkePaint(IntPtr webView, IntPtr bits, int pitch); 88         [DllImport(miniblinkdll, CallingConvention = CallingConvention.Cdecl)] 89         public static extern WkeCursorInfo wkeGetCursorInfoType(IntPtr webView); 90  91         public static string Utf8IntptrToString(this IntPtr ptr) 92         { 93             var data = new List
(); 94 var off = 0; 95 while (true) 96 { 97 var ch = Marshal.ReadByte(ptr, off++); 98 if (ch == 0) 99 {100 break;101 }102 data.Add(ch);103 }104 return Encoding.UTF8.GetString(data.ToArray());105 }106      //调用这个之后要手动调用  Marshal.FreeHGlobal(ptr);107 public static IntPtr Utf8StringToIntptr(this string str)108 {109 byte[] utf8bytes = Encoding.UTF8.GetBytes(str);110 IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);111 Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);112 Marshal.WriteByte(ptr, utf8bytes.Length, 0);113 return ptr;114 }115 116 117 public enum WkeCursorInfo118 {119 WkeCursorInfoPointer = 0,120 WkeCursorInfoCross = 1,121 WkeCursorInfoHand = 2,122 WkeCursorInfoIBeam = 3,123 WkeCursorInfoWait = 4,124 WkeCursorInfoHelp = 5,125 WkeCursorInfoEastResize = 6,126 WkeCursorInfoNorthResize = 7,127 WkeCursorInfoNorthEastResize = 8,128 WkeCursorInfoNorthWestResize = 9,129 WkeCursorInfoSouthResize = 10,130 WkeCursorInfoSouthEastResize = 11,131 WkeCursorInfoSouthWestResize = 12,132 WkeCursorInfoWestResize = 13,133 WkeCursorInfoNorthSouthResize = 14,134 WkeCursorInfoEastWestResize = 15,135 WkeCursorInfoNorthEastSouthWestResize = 16,136 WkeCursorInfoNorthWestSouthEastResize = 17,137 WkeCursorInfoColumnResize = 18,138 WkeCursorInfoRowResize = 19,139 }140 public enum wkeMouseMessage : uint141 {142 WKE_MSG_MOUSEMOVE = 0x0200,143 WKE_MSG_LBUTTONDOWN = 0x0201,144 WKE_MSG_LBUTTONUP = 0x0202,145 WKE_MSG_LBUTTONDBLCLK = 0x0203,146 WKE_MSG_RBUTTONDOWN = 0x0204,147 WKE_MSG_RBUTTONUP = 0x0205,148 WKE_MSG_RBUTTONDBLCLK = 0x0206,149 WKE_MSG_MBUTTONDOWN = 0x0207,150 WKE_MSG_MBUTTONUP = 0x0208,151 WKE_MSG_MBUTTONDBLCLK = 0x0209,152 WKE_MSG_MOUSEWHEEL = 0x020A,153 }154 public enum wkeMouseFlags155 {156 WKE_LBUTTON = 0x01,157 WKE_RBUTTON = 0x02,158 WKE_SHIFT = 0x04,159 WKE_CONTROL = 0x08,160 WKE_MBUTTON = 0x10,161 }162 163 164 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]165 public delegate void wkePaintUpdatedCallback(IntPtr webView, IntPtr param, IntPtr hdc, int x, int y, int cx, int cy);166 167 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]168 public delegate void UrlChangedCallback2(IntPtr webView, IntPtr param, IntPtr frameId, IntPtr url);169 }170 }

 

1 using System;  2 using System.Collections;  3 using System.Collections.Generic;  4 using System.ComponentModel;  5 using System.Drawing;  6 using System.Drawing.Imaging;  7 using System.IO;  8 using System.Linq;  9 using System.Reflection; 10 using System.Runtime.InteropServices; 11 using System.Text; 12 using System.Text.RegularExpressions; 13 using System.Windows.Forms; 14 //by:DSkin 15  16 namespace MiniBlink 17 { 18     public class TestControl : Control 19     { 20         IntPtr handle = IntPtr.Zero; 21         string url = string.Empty; 22  23         IntPtr bits = IntPtr.Zero; 24         Size oldSize; 25         MiniblinkPInvoke.UrlChangedCallback2 UrlChangedCallback2; 26         MiniblinkPInvoke.wkePaintUpdatedCallback wkePaintUpdatedCallback; 27  28         public TestControl() 29         { 30             SetStyle(ControlStyles.OptimizedDoubleBuffer | 31             ControlStyles.DoubleBuffer | 32             ControlStyles.AllPaintingInWmPaint | 33             ControlStyles.ResizeRedraw | 34             ControlStyles.UserPaint, true); 35         } 36  37         public string Url 38         { 39             get 40             { 41                 return url; 42             } 43  44             set 45             { 46                 url = value; 47                 if (handle != IntPtr.Zero) 48                 { 49                     MiniblinkPInvoke.wkeLoadURLW(handle, value); 50                 } 51             } 52         } 53  54         protected override void OnCreateControl() 55         { 56             base.OnCreateControl(); 57             if (!DesignMode) 58             { 59                 MiniblinkPInvoke.wkeInitialize(); 60                 handle = MiniblinkPInvoke.wkeCreateWebView();//创建 WebView 61                 MiniblinkPInvoke.wkeSetHandle(handle, this.Handle); 62                 MiniblinkPInvoke.wkeResize(handle, Width, Height); 63  64                 UrlChangedCallback2 = (webView, param, frameId, url) => 65                 { 66                     this.url = MiniblinkPInvoke.wkeGetString(url).Utf8IntptrToString(); 67                     OnUrlChanged(EventArgs.Empty); 68                 }; 69                 MiniblinkPInvoke.wkeOnURLChanged2(handle, UrlChangedCallback2, IntPtr.Zero); 70  71                 wkePaintUpdatedCallback = (IntPtr webView, IntPtr param, IntPtr hdc, int x, int y, int cx, int cy) => 72                 { 73                     Invalidate(); 74                 }; 75                 MiniblinkPInvoke.wkeOnPaintUpdated(handle, wkePaintUpdatedCallback, IntPtr.Zero); 76  77                 Url = url; 78             } 79         } 80  81         protected override void OnPaint(PaintEventArgs e) 82         { 83             if (handle != IntPtr.Zero) 84             { 85                 if (bits == IntPtr.Zero || oldSize != Size) 86                 { 87                     if (bits != IntPtr.Zero) 88                     { 89                         Marshal.FreeHGlobal(bits); 90                     } 91                     oldSize = Size; 92                     bits = Marshal.AllocHGlobal(Width * Height * 4); 93                 } 94  95                 MiniblinkPInvoke.wkePaint(handle, bits, 0); 96                 using (Bitmap bmp = new Bitmap(Width, Height, Width * 4, PixelFormat.Format32bppPArgb, bits)) 97                 { 98                     e.Graphics.DrawImage(bmp, 0, 0); 99                 }100             }101             base.OnPaint(e);102             if (DesignMode)103             {104                 e.Graphics.DrawString("MiniBlinkBrowser", this.Font, Brushes.Red, new Point());105                 e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0, Width - 1, Height - 1));106             }107         }108 109         protected override void OnSizeChanged(EventArgs e)110         {111             base.OnSizeChanged(e);112             if (handle != IntPtr.Zero && Width > 1 && Height > 1)113             {114                 MiniblinkPInvoke.wkeResize(handle, Width, Height);115             }116         }117 118         protected override void OnMouseWheel(MouseEventArgs e)119         {120             base.OnMouseWheel(e);121             if (handle != IntPtr.Zero)122             {123                 uint flags = GetMouseFlags(e);124                 MiniblinkPInvoke.wkeFireMouseWheelEvent(handle, e.X, e.Y, e.Delta, flags);125             }126         }127         protected override void OnMouseDown(MouseEventArgs e)128         {129             base.OnMouseDown(e);130             uint msg = 0;131             if (e.Button == MouseButtons.Left)132             {133                 msg = (uint)MiniblinkPInvoke.wkeMouseMessage.WKE_MSG_LBUTTONDOWN;134             }135             else if (e.Button == MouseButtons.Middle)136             {137                 msg = (uint)MiniblinkPInvoke.wkeMouseMessage.WKE_MSG_MBUTTONDOWN;138             }139             else if (e.Button == MouseButtons.Right)140             {141                 msg = (uint)MiniblinkPInvoke.wkeMouseMessage.WKE_MSG_RBUTTONDOWN;142             }143             uint flags = GetMouseFlags(e);144             if (handle != IntPtr.Zero)145             {146                 MiniblinkPInvoke.wkeFireMouseEvent(handle, msg, e.X, e.Y, flags);147             }148         }149         protected override void OnMouseUp(MouseEventArgs e)150         {151             base.OnMouseUp(e);152             uint msg = 0;153             if (e.Button == MouseButtons.Left)154             {155                 msg = (uint)MiniblinkPInvoke.wkeMouseMessage.WKE_MSG_LBUTTONUP;156             }157             else if (e.Button == MouseButtons.Middle)158             {159                 msg = (uint)MiniblinkPInvoke.wkeMouseMessage.WKE_MSG_MBUTTONUP;160             }161             else if (e.Button == MouseButtons.Right)162             {163                 msg = (uint)MiniblinkPInvoke.wkeMouseMessage.WKE_MSG_RBUTTONUP;164             }165             uint flags = GetMouseFlags(e);166             if (handle != IntPtr.Zero)167             {168                 MiniblinkPInvoke.wkeFireMouseEvent(handle, msg, e.X, e.Y, flags);169             }170         }171         protected override void OnMouseMove(MouseEventArgs e)172         {173             base.OnMouseMove(e);174             if (this.handle != IntPtr.Zero)175             {176                 uint flags = GetMouseFlags(e);177                 MiniblinkPInvoke.wkeFireMouseEvent(this.handle, 0x200, e.X, e.Y, flags);178 179                 switch (MiniblinkPInvoke.wkeGetCursorInfoType(handle))180                 {181                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoPointer:182                         Cursor = Cursors.Default;183                         break;184                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoCross:185                         Cursor = Cursors.Cross;186                         break;187                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoHand:188                         Cursor = Cursors.Hand;189                         break;190                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoIBeam:191                         Cursor = Cursors.IBeam;192                         break;193                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoWait:194                         Cursor = Cursors.WaitCursor;195                         break;196                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoHelp:197                         Cursor = Cursors.Help;198                         break;199                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoEastResize:200                         Cursor = Cursors.SizeWE;201                         break;202                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoNorthResize:203                         Cursor = Cursors.SizeNS;204                         break;205                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoNorthEastResize:206                         Cursor = Cursors.SizeNESW;207                         break;208                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoNorthWestResize:209                         Cursor = Cursors.SizeNWSE;210                         break;211                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoSouthResize:212                         Cursor = Cursors.SizeNS;213                         break;214                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoSouthEastResize:215                         Cursor = Cursors.SizeNWSE;216                         break;217                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoSouthWestResize:218                         Cursor = Cursors.SizeNESW;219                         break;220                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoWestResize:221                         Cursor = Cursors.SizeWE;222                         break;223                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoNorthSouthResize:224                         Cursor = Cursors.SizeNS;225                         break;226                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoEastWestResize:227                         Cursor = Cursors.SizeWE;228                         break;229                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoNorthEastSouthWestResize:230                         Cursor = Cursors.SizeAll;231                         break;232                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoNorthWestSouthEastResize:233                         Cursor = Cursors.SizeAll;234                         break;235                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoColumnResize:236                         Cursor = Cursors.Default;237                         break;238                     case MiniblinkPInvoke.WkeCursorInfo.WkeCursorInfoRowResize:239                         Cursor = Cursors.Default;240                         break;241                     default:242                         Cursor = Cursors.Default;243                         break;244                 }245             }246         }247         protected override void OnKeyDown(KeyEventArgs e)248         {249             base.OnKeyDown(e);250             if (handle != IntPtr.Zero)251             {252                 MiniblinkPInvoke.wkeFireKeyDownEvent(handle, (uint)e.KeyValue, 0, false);253             }254         }255         protected override void OnKeyPress(KeyPressEventArgs e)256         {257             base.OnKeyPress(e);258             if (handle != IntPtr.Zero)259             {260                 e.Handled = true;261                 MiniblinkPInvoke.wkeFireKeyPressEvent(handle, (uint)e.KeyChar, 0, false);262             }263         }264         protected override void OnKeyUp(KeyEventArgs e)265         {266             base.OnKeyUp(e);267             if (handle != IntPtr.Zero)268             {269                 MiniblinkPInvoke.wkeFireKeyUpEvent(handle, (uint)e.KeyValue, 0, false);270             }271         }272 273         protected override void OnGotFocus(EventArgs e)274         {275             base.OnGotFocus(e);276             if (handle != IntPtr.Zero)277             {278                 MiniblinkPInvoke.wkeSetFocus(handle);279             }280         }281 282         protected override void OnLostFocus(EventArgs e)283         {284             base.OnLostFocus(e);285             if (handle != IntPtr.Zero)286             {287                 MiniblinkPInvoke.wkeKillFocus(handle);288             }289         }290 291         protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)292         {293             base.OnPreviewKeyDown(e);294             switch (e.KeyCode)295             {296                 case Keys.Down:297                 case Keys.Up:298                 case Keys.Left:299                 case Keys.Right:300                 case Keys.Tab:301                     e.IsInputKey = true;302                     break;303             }304         }305         private static uint GetMouseFlags(MouseEventArgs e)306         {307             uint flags = 0;308             if (e.Button == MouseButtons.Left)309             {310                 flags = flags | (uint)MiniblinkPInvoke.wkeMouseFlags.WKE_LBUTTON;311             }312             if (e.Button == MouseButtons.Middle)313             {314                 flags = flags | (uint)MiniblinkPInvoke.wkeMouseFlags.WKE_MBUTTON;315             }316             if (e.Button == MouseButtons.Right)317             {318                 flags = flags | (uint)MiniblinkPInvoke.wkeMouseFlags.WKE_RBUTTON;319             }320             if (Control.ModifierKeys == Keys.Control)321             {322                 flags = flags | (uint)MiniblinkPInvoke.wkeMouseFlags.WKE_CONTROL;323             }324             if (Control.ModifierKeys == Keys.Shift)325             {326                 flags = flags | (uint)MiniblinkPInvoke.wkeMouseFlags.WKE_SHIFT;327             }328             return flags;329         }330 331 332         protected override void Dispose(bool disposing)333         {334             base.Dispose(disposing);335             if (handle != IntPtr.Zero)336             {//资源释放337                 MiniblinkPInvoke.wkeDestroyWebView(handle);338                 handle = IntPtr.Zero;339             }340             if (bits != IntPtr.Zero)341             {342                 Marshal.FreeHGlobal(bits);343                 bits = IntPtr.Zero;344             }345         }346 347         public event EventHandler UrlChanged;348 349         protected virtual void OnUrlChanged(EventArgs e)350         {351             if (UrlChanged != null)352             {353                 UrlChanged(this, e);354             }355         }356 357     }358 }

 

代码写好之后,生成一下,工具箱里就有控件了,然后拖到界面,设置Url,运行就有效果了

 

 

如果你想偷懒,要更完整的功能你可以看看 

DSkin已经封装好 Html构建桌面UI的快捷开发方式,资源内嵌,C#和JS互相调用,无需写麻烦的参数数据转换,通过Vue实现C#属性和页面双向绑定,页面和C#类对应等等,就像WebForm开发。 窗体阴影、系统按钮那些都是Html+CSS定义的

 

转载于:https://www.cnblogs.com/Jeely/p/10784573.html

你可能感兴趣的文章
SQL Server 2008 教程
查看>>
docker安装
查看>>
JAVA boolean 类型
查看>>
MYSQL进阶学习笔记七:MySQL触发器的创建,应用及管理!(视频序号:进阶_16,17)...
查看>>
hdu 4069 福州赛区网络赛I DLC ***
查看>>
java web 方面
查看>>
Spring 源码学习(2) —— FactoryBean 的使用
查看>>
wiki 3143 二叉树的前序、中序及后序遍历
查看>>
一位创业者创业失败后,成功的做了一个创业孵化器!
查看>>
程序猿打新总结 6月份 新股申购秘籍
查看>>
导出文本pdf文件
查看>>
C. Table Decorations(Codeforces Round 273)
查看>>
LayoutInflater和inflate()方法的使用方法
查看>>
TsFltMgr.sys系统蓝屏的原因就在于QQ电脑管家!
查看>>
Luogu P4306 JSOI2010 连通数
查看>>
爬取音悦台MV信息(requests,BeautifulSoup,xlwt)----待完善
查看>>
asp.net gridview 控件如何根据一列内容显示另一列的内容
查看>>
应用开发之Linq和EF
查看>>
EF架构~终于自己架构了一个相对完整的EF方案
查看>>
js-位置问题
查看>>