Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit db0b527

Browse files
committed
New Title Bar UI, Update CefSharp to v69.
1 parent 3b91206 commit db0b527

25 files changed

+1359
-222
lines changed

LICENSE

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
《Nacollector 用户使用许可协议》
22

3-
Copyright (C) 2018 Zneiat <https://qwqaq.com/>
3+
Copyright (C) 2018 qwqcode <https://qwqaq.com/>
44

55
本协议保存于 GitHub 仓库和您本地 Nacollector 运行目录中。
66

@@ -16,9 +16,9 @@ Copyright (C) 2018 Zneiat <https://qwqaq.com/>
1616

1717
一、【许可使用】
1818

19-
1.1 通过任何途径下载 Nacollector 原版程序(原版程序是指在 https://github.com/Zneiat/Nacollector/releases 上发布的程序),在不违反本协议的前提下可自行使用。
19+
1.1 通过任何途径下载 Nacollector 原版程序(原版程序是指在 https://github.com/qwqcode/Nacollector/releases 上发布的程序),在不违反本协议的前提下可自行使用。
2020

21-
1.2 其它参考 Nacollector 及其衍生品的源代码的程序,须征 Nacollector 原作者 Zneiat <https://qwqaq.com/> 同意后,在标示原有版权信息的情况下使用。
21+
1.2 其它参考 Nacollector 及其衍生品的源代码的程序,须征 Nacollector 原作者 qwqcode <https://qwqaq.com/> 同意后,在标示原有版权信息的情况下使用。
2222

2323
二、【禁止使用】
2424

@@ -30,7 +30,7 @@ Copyright (C) 2018 Zneiat <https://qwqaq.com/>
3030

3131
2.4 禁止未经作者允许,私自将 Nacollector 及其衍生品的源代码闭源。
3232

33-
2.5 Nacollector 的软件图标(app_ico.ico)版权归 Zneiat <https://qwqaq.com/> 所有,禁止未经作者允许,私自用于除 Nacollector 之外的任何地方。
33+
2.5 Nacollector 的软件图标(app_ico.ico)版权归 qwqcode <https://qwqaq.com/> 所有,禁止未经作者允许,私自用于除 Nacollector 之外的任何地方。
3434

3535
三、【许可终止】
3636

@@ -40,15 +40,15 @@ Copyright (C) 2018 Zneiat <https://qwqaq.com/>
4040

4141
四、【权利保留】
4242

43-
未明确声明的一切其它权利均为 Zneiat <https://qwqaq.com/> 所保留,对本协议的一切解释权归 Zneiat <https://qwqaq.com/> 所有。
43+
未明确声明的一切其它权利均为 qwqcode <https://qwqaq.com/> 所保留,对本协议的一切解释权归 qwqcode <https://qwqaq.com/> 所有。
4444

4545
五、【责任限度】
4646

47-
在适用法律所允许的最大范围内,Nacollector 作者 Zneiat <https://qwqaq.com/> 绝不就因使用 Nacollector 造成的任何特殊、意外、非直接或间接的损害承担任何责任。
47+
在适用法律所允许的最大范围内,Nacollector 作者 qwqcode <https://qwqaq.com/> 绝不就因使用 Nacollector 造成的任何特殊、意外、非直接或间接的损害承担任何责任。
4848

4949
六、【协议的生效与变更】
5050

51-
6.1 作者 Zneiat <https://qwqaq.com/> 有权在必要时修改本协议条款。您可以在相关页面(如:https://github.com/Zneiat/Nacollector)查阅最新版本的协议条款。
51+
6.1 作者 qwqcode <https://qwqaq.com/> 有权在必要时修改本协议条款。您可以在相关页面(如:https://github.com/qwqcode/Nacollector)查阅最新版本的协议条款。
5252

5353
6.2 本协议条款变更后,如果您继续使用 Nacollector 及其衍生品,即视为您已接受修改后的协议。如果您不接受修改后的协议,那么视为您放弃一切许可(参见 3.1)。
5454

Nacollector/Browser/CrBrowser.cs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using CefSharp;
22
using CefSharp.WinForms;
33
using Nacollector.Browser.Handler;
4+
using Nacollector.Util;
45
using System;
56
using System.Collections.Generic;
67
using System.Drawing;
@@ -14,10 +15,13 @@ namespace Nacollector.Browser
1415
{
1516
public class CrBrowser
1617
{
18+
private MainForm form;
1719
private ChromiumWebBrowser browser;
1820

19-
public CrBrowser(string address)
21+
public CrBrowser(MainForm form, string address)
2022
{
23+
this.form = form;
24+
2125
// 初始化浏览器
2226
browser = new ChromiumWebBrowser(address);
2327

@@ -33,6 +37,7 @@ public CrBrowser(string address)
3337
browser.MenuHandler = new MenuHandler();
3438
browser.LifeSpanHandler = new LifeSpanHandler();
3539
browser.LoadHandler = new LoadHandler();
40+
browser.DragHandler = new DragDropHandler();
3641

3742
browser.FrameLoadEnd += new EventHandler<FrameLoadEndEventArgs>(Browser_onFrameLoadEnd);
3843
browser.IsBrowserInitializedChanged += new EventHandler<IsBrowserInitializedChangedEventArgs>(Browser_onIsBrowserInitializedChanged);
@@ -45,8 +50,39 @@ private void Browser_onFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
4550
}
4651

4752
// 浏览器初始化完毕时执行
48-
private void Browser_onIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e)
53+
private void Browser_onIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs args)
4954
{
55+
if (args.IsBrowserInitialized)
56+
{
57+
// 设置鼠标按下操作
58+
ChromeWidgetMessageInterceptor.SetupLoop(browser, (message) =>
59+
{
60+
Point point = new Point(message.LParam.ToInt32());
61+
if (((DragDropHandler)browser.DragHandler).draggableRegion.IsVisible(point))
62+
{
63+
// 若现在鼠标指针在可拖动区域内
64+
if (message.Msg == (int)WindowMessages.WM_LBUTTONDBLCLK) // 鼠标左键双击
65+
{
66+
form.Invoke((MethodInvoker)delegate
67+
{
68+
form.ToggleMaximize();
69+
});
70+
}
71+
else if (message.Msg == (int)WindowMessages.WM_LBUTTONDOWN) // 鼠标左键按下
72+
{
73+
NativeMethods.ReleaseCapture();
74+
form.SendHandleMessage(); // 执行 模拟标题栏拖动
75+
}
76+
else if (message.Msg == (int)WindowMessages.WM_RBUTTONDOWN) // 鼠标右键按下
77+
{
78+
form.Invoke((MethodInvoker)delegate
79+
{
80+
form.ShowSystemMenu(point);
81+
});
82+
}
83+
}
84+
});
85+
}
5086
}
5187

5288
/// <summary>
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using CefSharp.WinForms;
2+
using Nacollector.Util;
3+
using System;
4+
using System.Runtime.InteropServices;
5+
using System.Text;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using System.Windows.Forms;
9+
10+
namespace Nacollector.Browser.Handler
11+
{
12+
/// <summary>
13+
/// Intercepts Windows messages sent to the ChromiumWebBrowser control's widget sub-window.
14+
///
15+
/// It is necessary to listen to the widget sub-window because it receives all Windows messages
16+
/// and forwards them to CEF, rather than the ChromiumWebBrowser.Handle.
17+
///
18+
/// The supplied Action delegate is fired upon each message.
19+
/// </summary>
20+
class ChromeWidgetMessageInterceptor : NativeWindow
21+
{
22+
private readonly ChromiumWebBrowser browser;
23+
private Action<Message> forwardAction;
24+
25+
private ChromeWidgetMessageInterceptor(ChromiumWebBrowser browser, IntPtr chromeWidgetHostHandle, Action<Message> forwardAction)
26+
{
27+
AssignHandle(chromeWidgetHostHandle);
28+
29+
this.browser = browser;
30+
browser.HandleDestroyed += BrowserHandleDestroyed;
31+
32+
this.forwardAction = forwardAction;
33+
}
34+
35+
/// <summary>
36+
/// Asynchronously wait for the Chromium widget window to be created for the given ChromiumWebBrowser,
37+
/// and when created hook into its Windows message loop.
38+
/// </summary>
39+
/// <param name="browser">The browser to intercept Windows messages for.</param>
40+
/// <param name="forwardAction">This action will be called whenever a Windows message is received.</param>
41+
internal static void SetupLoop(ChromiumWebBrowser browser, Action<Message> forwardAction)
42+
{
43+
Task.Factory.StartNew(() =>
44+
{
45+
try
46+
{
47+
bool foundWidget = false;
48+
while (!foundWidget)
49+
{
50+
browser.Invoke((Action)(() =>
51+
{
52+
IntPtr chromeWidgetHostHandle;
53+
if (ChromeWidgetHandleFinder.TryFindHandle(browser, out chromeWidgetHostHandle))
54+
{
55+
foundWidget = true;
56+
new ChromeWidgetMessageInterceptor(browser, chromeWidgetHostHandle, forwardAction);
57+
}
58+
else
59+
{
60+
// Chrome hasn't yet set up its message-loop window.
61+
Thread.Sleep(10);
62+
}
63+
}));
64+
}
65+
}
66+
catch
67+
{
68+
// Errors are likely to occur if browser is disposed, and no good way to check from another thread
69+
}
70+
});
71+
}
72+
73+
private void BrowserHandleDestroyed(object sender, EventArgs e)
74+
{
75+
ReleaseHandle();
76+
77+
browser.HandleDestroyed -= BrowserHandleDestroyed;
78+
forwardAction = null;
79+
}
80+
81+
protected override void WndProc(ref Message m)
82+
{
83+
base.WndProc(ref m);
84+
85+
if (forwardAction != null)
86+
{
87+
forwardAction(m);
88+
}
89+
}
90+
}
91+
92+
class ChromeWidgetHandleFinder
93+
{
94+
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
95+
96+
[DllImport("user32")]
97+
[return: MarshalAs(UnmanagedType.Bool)]
98+
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
99+
100+
private readonly IntPtr mainHandle;
101+
private string seekClassName;
102+
private IntPtr descendantFound;
103+
104+
private ChromeWidgetHandleFinder(IntPtr handle)
105+
{
106+
this.mainHandle = handle;
107+
}
108+
109+
private IntPtr FindDescendantByClassName(string className)
110+
{
111+
descendantFound = IntPtr.Zero;
112+
seekClassName = className;
113+
114+
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
115+
EnumChildWindows(this.mainHandle, childProc, IntPtr.Zero);
116+
117+
return descendantFound;
118+
}
119+
120+
[DllImport("user32.dll", CharSet = CharSet.Auto)]
121+
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
122+
123+
private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
124+
{
125+
StringBuilder buffer = new StringBuilder(128);
126+
GetClassName(hWnd, buffer, buffer.Capacity);
127+
128+
if (buffer.ToString() == seekClassName)
129+
{
130+
descendantFound = hWnd;
131+
return false;
132+
}
133+
134+
return true;
135+
}
136+
137+
/// <summary>
138+
/// Chrome's message-loop Window isn't created synchronously, so this may not find it.
139+
/// If so, you need to wait and try again later.
140+
/// </summary>
141+
public static bool TryFindHandle(ChromiumWebBrowser browser, out IntPtr chromeWidgetHostHandle)
142+
{
143+
var browserHandle = browser.Handle;
144+
var windowHandleInfo = new ChromeWidgetHandleFinder(browserHandle);
145+
const string chromeWidgetHostClassName = "Chrome_RenderWidgetHostHWND";
146+
chromeWidgetHostHandle = windowHandleInfo.FindDescendantByClassName(chromeWidgetHostClassName);
147+
return chromeWidgetHostHandle != IntPtr.Zero;
148+
}
149+
}
150+
}

Nacollector/Browser/Handler/DownloadHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class DownloadHandler : IDownloadHandler
1515
public event EventHandler<DownloadUpdatedEventArgs> OnDownloadUpdatedFired;
1616

1717
// 下载之前(单个下载任务 只会执行一次,从这里获取 downloadItem.SuggestedFileName)
18-
public void OnBeforeDownload(IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
18+
public void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
1919
{
2020
var handler = OnBeforeDownloadFired;
2121
if (handler != null)
@@ -39,7 +39,7 @@ public void OnBeforeDownload(IBrowser browser, DownloadItem downloadItem, IBefor
3939
}
4040

4141
// 当下载任务信息更新
42-
public void OnDownloadUpdated(IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
42+
public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
4343
{
4444
var handler = OnDownloadUpdatedFired;
4545
if (handler != null)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using CefSharp;
2+
using CefSharp.Enums;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Drawing;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace Nacollector.Browser.Handler
11+
{
12+
/**
13+
* 获取可拖拽区域
14+
*/
15+
public class DragDropHandler : IDragHandler
16+
{
17+
public Region draggableRegion = new Region();
18+
public event Action<Region> RegionsChanged;
19+
20+
public bool OnDragEnter(IWebBrowser browserControl, IBrowser browser, IDragData dragData, DragOperationsMask mask)
21+
{
22+
return false;
23+
}
24+
25+
public void OnDraggableRegionsChanged(IWebBrowser browserControl, IBrowser browser, IList<DraggableRegion> regions)
26+
{
27+
if (browser.IsPopup == false)
28+
{
29+
draggableRegion = null;
30+
if (regions.Count > 0)
31+
{
32+
foreach (var region in regions)
33+
{
34+
// Console.WriteLine(region.X + " - " + region.Y + " - " + region.Width + " - " + region.Height);
35+
var rect = new Rectangle(region.X, region.Y, region.Width, region.Height);
36+
37+
if (draggableRegion == null)
38+
{
39+
draggableRegion = new Region(rect);
40+
}
41+
else
42+
{
43+
if (region.Draggable)
44+
{
45+
draggableRegion.Union(rect);
46+
}
47+
else
48+
{
49+
//In the scenario where we have an outer region, that is draggable and it has
50+
// an inner region that's not, we must exclude the non draggable.
51+
// Not all scenarios are covered in this example.
52+
draggableRegion.Exclude(rect);
53+
}
54+
}
55+
}
56+
}
57+
58+
RegionsChanged?.Invoke(draggableRegion);
59+
}
60+
}
61+
62+
public void Dispose()
63+
{
64+
RegionsChanged = null;
65+
}
66+
}
67+
}

Nacollector/Browser/Handler/MenuHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ void IContextMenuHandler.OnBeforeContextMenu(IWebBrowser browserControl, IBrowse
8181
model.AddItem(CefMenuCommand.ReloadNoCache, "刷新 (ReloadNoCache)");
8282
model.AddItem((CefMenuCommand)FeedbackProject, "反馈问题");
8383
model.AddItem((CefMenuCommand)LinkToZneiatProject, "开源项目");
84-
// model.AddItem((CefMenuCommand)ShowDevTools, "检查 (ShowDevTools)");
84+
# if DEBUG
85+
model.AddItem((CefMenuCommand)ShowDevTools, "检查 (ShowDevTools)");
86+
# endif
8587
}
8688
}
8789

Nacollector/ClassDiagram1.cd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<ClassDiagram />

0 commit comments

Comments
 (0)