add ColorDropper
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user