add ColorDropper

This commit is contained in:
NaBian committed 2019-05-14 23:03:14 +08:00
1 parent d920bf678e
commit a8aa1a4525
7 files changed
+180 -25

No files matched your search

@@ -1,9 +1,69 @@
using System.Windows.Controls;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
namespace HandyControl.Controls
{
public class ColorDropper : Control
internal class ColorDropper : Control
{
private Cursor _dropperCursor;
private readonly ColorPicker _colorPicker;
public ColorDropper(ColorPicker colorPicker)
{
_colorPicker = colorPicker;
}
public void Update(bool isShow)
{
if (isShow)
{
if (_dropperCursor == null)
{
var info = Application.GetResourceStream(
new Uri("pack://application:,,,/HandyControl;Component/Resources/dropper.cur"));
if (info != null)
{
_dropperCursor = new Cursor(info.Stream);
}
}
if (_dropperCursor == null) return;
Mouse.OverrideCursor = _dropperCursor;
MouseHook.Start();
MouseHook.StatusChanged += MouseHook_StatusChanged;
}
else
{
Mouse.OverrideCursor = Cursors.Arrow;
}
}
private void MouseHook_StatusChanged(object sender, MouseHookEventArgs e)
{
if (!_colorPicker.IsMouseOver && e.Message == MouseHookMessageType.LeftButtonDown)
{
var brush = new SolidColorBrush(GetColorAt(e.Point.X, e.Point.Y));
_colorPicker.SelectedBrush = brush;
//MouseHook.Stop();
//MouseHook.StatusChanged -= MouseHook_StatusChanged;
}
}
public static Color GetColorAt(int x, int y)
{
var desk = UnsafeNativeMethods.GetDesktopWindow();
var dc = UnsafeNativeMethods.GetWindowDC(desk);
var a = (int)UnsafeNativeMethods.GetPixel(dc, x, y);
UnsafeNativeMethods.ReleaseDC(desk, dc);
return Color.FromArgb(255, (byte) ((a >> 0) & 0xff), (byte) ((a >> 8) & 0xff), (byte) ((a >> 16) & 0xff));
}
}
}
@@ -41,7 +41,7 @@ namespace HandyControl.Controls
#region Data
private Cursor _dropperCursor;
private ColorDropper _colorDropper;
private ToggleButton _toggleButtonDropper;
@@ -696,25 +696,12 @@ namespace HandyControl.Controls
private void ToggleButtonDropper_Click(object sender, RoutedEventArgs e)
{
if (_toggleButtonDropper.IsChecked == true)
if (_colorDropper == null)
{
if (_dropperCursor == null)
{
var info = Application.GetResourceStream(new Uri("pack://application:,,,/HandyControl;Component/Resources/dropper.cur"));
if (info != null)
{
_dropperCursor = new Cursor(info.Stream);
}
}
if (_dropperCursor == null) return;
Mouse.OverrideCursor = _dropperCursor;
}
else
{
Mouse.OverrideCursor = Cursors.Arrow;
_colorDropper = new ColorDropper(this);
}
// ReSharper disable once PossibleInvalidOperationException
_colorDropper.Update(_toggleButtonDropper.IsChecked.Value);
}
public void Dispose() => System.Windows.Window.GetWindow(this)?.Close();
@@ -0,0 +1,12 @@
using System;
using HandyControl.Tools.Interop;
namespace HandyControl.Data
{
internal class MouseHookEventArgs : EventArgs
{
public MouseHookMessageType Message { get; set; }
public NativeMethods.POINT Point { get; set; }
}
}
@@ -0,0 +1,12 @@
namespace HandyControl.Data
{
public enum MouseHookMessageType
{
LeftButtonDown = 0x0201,
LeftButtonUp = 0x0202,
MouseMove = 0x0200,
MouseWheel = 0x020A,
RightButtonDown = 0x0204,
RightButtonUp = 0x0205
}
}
@@ -113,6 +113,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\Window\Window.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Args\CancelRoutedEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Args\FunctionEventArgs!1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Args\MouseHookEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\ColorRange.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\BadgeStatus.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\ChatMessageType.cs" />
@@ -136,6 +137,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Data\GrowlInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\HandyControlConfig.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\MessageBoxInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\MouseHookMessageType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Operation\OperationResult!1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Operation\OperationResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\ResourceToken.cs" />
@@ -244,6 +246,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\SingleOpenHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\ValidateHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\VisualHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Hook\MouseHook.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Interop\BitmapHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Interop\BITMAPINFO.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Interop\CommonHandles.cs" />
@@ -1,7 +1,48 @@
namespace HandyControl.Tools
{
public class MouseHook
{
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using HandyControl.Data;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
{
internal class MouseHook
{
public static event EventHandler<MouseHookEventArgs> StatusChanged;
private static IntPtr HookId = IntPtr.Zero;
private static readonly UnsafeNativeMethods.HookProc Proc = HookCallback;
public static void Start() => HookId = SetHook(Proc);
public static void Stop() => UnsafeNativeMethods.UnhookWindowsHookEx(HookId);
private static IntPtr SetHook(UnsafeNativeMethods.HookProc proc)
{
using (var curProcess = Process.GetCurrentProcess())
using (var curModule = curProcess.MainModule)
{
if (curModule != null)
{
return UnsafeNativeMethods.SetWindowsHookEx((int) UnsafeNativeMethods.HookType.WH_MOUSE_LL, proc,
UnsafeNativeMethods.GetModuleHandle(curModule.ModuleName), 0);
}
return IntPtr.Zero;
}
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0) return UnsafeNativeMethods.CallNextHookEx(HookId, nCode, wParam, lParam);
var hookStruct = (UnsafeNativeMethods.MOUSEHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(UnsafeNativeMethods.MOUSEHOOKSTRUCT));
StatusChanged?.Invoke(null, new MouseHookEventArgs
{
Message = (MouseHookMessageType)wParam,
Point = new NativeMethods.POINT(hookStruct.pt.X, hookStruct.pt.Y)
});
return UnsafeNativeMethods.CallNextHookEx(HookId, nCode, wParam, lParam);
}
}
}
@@ -174,5 +174,45 @@ namespace HandyControl.Tools.Interop
[DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport(ExternDll.Kernel32, CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
public enum HookType
{
WH_MOUSE_LL = 14,
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEHOOKSTRUCT
{
public NativeMethods.POINT pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
}
public delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport(ExternDll.User32, SetLastError = true)]
public static extern IntPtr GetDesktopWindow();
[DllImport(ExternDll.User32, SetLastError = true)]
public static extern IntPtr GetWindowDC(IntPtr window);
[DllImport(ExternDll.Gdi32, SetLastError = true)]
public static extern uint GetPixel(IntPtr dc, int x, int y);
[DllImport(ExternDll.User32, SetLastError = true)]
public static extern int ReleaseDC(IntPtr window, IntPtr dc);
}
}