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

Commit

Permalink
New Title Bar UI, Update CefSharp to v69.
Browse files Browse the repository at this point in the history
  • Loading branch information
qwqcode committed Dec 30, 2018
1 parent 3b91206 commit db0b527
Show file tree
Hide file tree
Showing 25 changed files with 1,359 additions and 222 deletions.
14 changes: 7 additions & 7 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
《Nacollector 用户使用许可协议》

Copyright (C) 2018 Zneiat <https://qwqaq.com/>
Copyright (C) 2018 qwqcode <https://qwqaq.com/>

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

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

一、【许可使用】

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

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

二、【禁止使用】

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

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

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

三、【许可终止】

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

四、【权利保留】

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

五、【责任限度】

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

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

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

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

Expand Down
40 changes: 38 additions & 2 deletions Nacollector/Browser/CrBrowser.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using CefSharp;
using CefSharp.WinForms;
using Nacollector.Browser.Handler;
using Nacollector.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
Expand All @@ -14,10 +15,13 @@ namespace Nacollector.Browser
{
public class CrBrowser
{
private MainForm form;
private ChromiumWebBrowser browser;

public CrBrowser(string address)
public CrBrowser(MainForm form, string address)
{
this.form = form;

// 初始化浏览器
browser = new ChromiumWebBrowser(address);

Expand All @@ -33,6 +37,7 @@ public CrBrowser(string address)
browser.MenuHandler = new MenuHandler();
browser.LifeSpanHandler = new LifeSpanHandler();
browser.LoadHandler = new LoadHandler();
browser.DragHandler = new DragDropHandler();

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

// 浏览器初始化完毕时执行
private void Browser_onIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e)
private void Browser_onIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs args)
{
if (args.IsBrowserInitialized)
{
// 设置鼠标按下操作
ChromeWidgetMessageInterceptor.SetupLoop(browser, (message) =>
{
Point point = new Point(message.LParam.ToInt32());
if (((DragDropHandler)browser.DragHandler).draggableRegion.IsVisible(point))
{
// 若现在鼠标指针在可拖动区域内
if (message.Msg == (int)WindowMessages.WM_LBUTTONDBLCLK) // 鼠标左键双击
{
form.Invoke((MethodInvoker)delegate
{
form.ToggleMaximize();
});
}
else if (message.Msg == (int)WindowMessages.WM_LBUTTONDOWN) // 鼠标左键按下
{
NativeMethods.ReleaseCapture();
form.SendHandleMessage(); // 执行 模拟标题栏拖动
}
else if (message.Msg == (int)WindowMessages.WM_RBUTTONDOWN) // 鼠标右键按下
{
form.Invoke((MethodInvoker)delegate
{
form.ShowSystemMenu(point);
});
}
}
});
}
}

/// <summary>
Expand Down
150 changes: 150 additions & 0 deletions Nacollector/Browser/Handler/ChromeWidgetMessageInterceptor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using CefSharp.WinForms;
using Nacollector.Util;
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Nacollector.Browser.Handler
{
/// <summary>
/// Intercepts Windows messages sent to the ChromiumWebBrowser control's widget sub-window.
///
/// It is necessary to listen to the widget sub-window because it receives all Windows messages
/// and forwards them to CEF, rather than the ChromiumWebBrowser.Handle.
///
/// The supplied Action delegate is fired upon each message.
/// </summary>
class ChromeWidgetMessageInterceptor : NativeWindow
{
private readonly ChromiumWebBrowser browser;
private Action<Message> forwardAction;

private ChromeWidgetMessageInterceptor(ChromiumWebBrowser browser, IntPtr chromeWidgetHostHandle, Action<Message> forwardAction)
{
AssignHandle(chromeWidgetHostHandle);

this.browser = browser;
browser.HandleDestroyed += BrowserHandleDestroyed;

this.forwardAction = forwardAction;
}

/// <summary>
/// Asynchronously wait for the Chromium widget window to be created for the given ChromiumWebBrowser,
/// and when created hook into its Windows message loop.
/// </summary>
/// <param name="browser">The browser to intercept Windows messages for.</param>
/// <param name="forwardAction">This action will be called whenever a Windows message is received.</param>
internal static void SetupLoop(ChromiumWebBrowser browser, Action<Message> forwardAction)
{
Task.Factory.StartNew(() =>
{
try
{
bool foundWidget = false;
while (!foundWidget)
{
browser.Invoke((Action)(() =>
{
IntPtr chromeWidgetHostHandle;
if (ChromeWidgetHandleFinder.TryFindHandle(browser, out chromeWidgetHostHandle))
{
foundWidget = true;
new ChromeWidgetMessageInterceptor(browser, chromeWidgetHostHandle, forwardAction);
}
else
{
// Chrome hasn't yet set up its message-loop window.
Thread.Sleep(10);
}
}));
}
}
catch
{
// Errors are likely to occur if browser is disposed, and no good way to check from another thread
}
});
}

private void BrowserHandleDestroyed(object sender, EventArgs e)
{
ReleaseHandle();

browser.HandleDestroyed -= BrowserHandleDestroyed;
forwardAction = null;
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);

if (forwardAction != null)
{
forwardAction(m);
}
}
}

class ChromeWidgetHandleFinder
{
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);

private readonly IntPtr mainHandle;
private string seekClassName;
private IntPtr descendantFound;

private ChromeWidgetHandleFinder(IntPtr handle)
{
this.mainHandle = handle;
}

private IntPtr FindDescendantByClassName(string className)
{
descendantFound = IntPtr.Zero;
seekClassName = className;

EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(this.mainHandle, childProc, IntPtr.Zero);

return descendantFound;
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
{
StringBuilder buffer = new StringBuilder(128);
GetClassName(hWnd, buffer, buffer.Capacity);

if (buffer.ToString() == seekClassName)
{
descendantFound = hWnd;
return false;
}

return true;
}

/// <summary>
/// Chrome's message-loop Window isn't created synchronously, so this may not find it.
/// If so, you need to wait and try again later.
/// </summary>
public static bool TryFindHandle(ChromiumWebBrowser browser, out IntPtr chromeWidgetHostHandle)
{
var browserHandle = browser.Handle;
var windowHandleInfo = new ChromeWidgetHandleFinder(browserHandle);
const string chromeWidgetHostClassName = "Chrome_RenderWidgetHostHWND";
chromeWidgetHostHandle = windowHandleInfo.FindDescendantByClassName(chromeWidgetHostClassName);
return chromeWidgetHostHandle != IntPtr.Zero;
}
}
}
4 changes: 2 additions & 2 deletions Nacollector/Browser/Handler/DownloadHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class DownloadHandler : IDownloadHandler
public event EventHandler<DownloadUpdatedEventArgs> OnDownloadUpdatedFired;

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

// 当下载任务信息更新
public void OnDownloadUpdated(IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
{
var handler = OnDownloadUpdatedFired;
if (handler != null)
Expand Down
67 changes: 67 additions & 0 deletions Nacollector/Browser/Handler/DragDropHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using CefSharp;
using CefSharp.Enums;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Nacollector.Browser.Handler
{
/**
* 获取可拖拽区域
*/
public class DragDropHandler : IDragHandler
{
public Region draggableRegion = new Region();
public event Action<Region> RegionsChanged;

public bool OnDragEnter(IWebBrowser browserControl, IBrowser browser, IDragData dragData, DragOperationsMask mask)
{
return false;
}

public void OnDraggableRegionsChanged(IWebBrowser browserControl, IBrowser browser, IList<DraggableRegion> regions)
{
if (browser.IsPopup == false)
{
draggableRegion = null;
if (regions.Count > 0)
{
foreach (var region in regions)
{
// Console.WriteLine(region.X + " - " + region.Y + " - " + region.Width + " - " + region.Height);
var rect = new Rectangle(region.X, region.Y, region.Width, region.Height);

if (draggableRegion == null)
{
draggableRegion = new Region(rect);
}
else
{
if (region.Draggable)
{
draggableRegion.Union(rect);
}
else
{
//In the scenario where we have an outer region, that is draggable and it has
// an inner region that's not, we must exclude the non draggable.
// Not all scenarios are covered in this example.
draggableRegion.Exclude(rect);
}
}
}
}

RegionsChanged?.Invoke(draggableRegion);
}
}

public void Dispose()
{
RegionsChanged = null;
}
}
}
4 changes: 3 additions & 1 deletion Nacollector/Browser/Handler/MenuHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ void IContextMenuHandler.OnBeforeContextMenu(IWebBrowser browserControl, IBrowse
model.AddItem(CefMenuCommand.ReloadNoCache, "刷新 (ReloadNoCache)");
model.AddItem((CefMenuCommand)FeedbackProject, "反馈问题");
model.AddItem((CefMenuCommand)LinkToZneiatProject, "开源项目");
// model.AddItem((CefMenuCommand)ShowDevTools, "检查 (ShowDevTools)");
# if DEBUG
model.AddItem((CefMenuCommand)ShowDevTools, "检查 (ShowDevTools)");
# endif
}
}

Expand Down
2 changes: 2 additions & 0 deletions Nacollector/ClassDiagram1.cd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram />
Loading

0 comments on commit db0b527

Please sign in to comment.