This repository has been archived by the owner on Jan 6, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New Title Bar UI, Update CefSharp to v69.
- Loading branch information
Showing
25 changed files
with
1,359 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
Nacollector/Browser/Handler/ChromeWidgetMessageInterceptor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<ClassDiagram /> |
Oops, something went wrong.