昨天有个小伙子,在找取色器工具。我说,这个应该开发起来很简单,于是,摸了大约半个钟的鱼,开发了一个。现在我把源码和操作案例发出来,供有需要的大佬们玩。(功能过于单一和简单,但是能用)
先创建GlobalMouseHook类,用于实现全局钩子
public class GlobalMouseHook
{
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONDOWN = 0x0201;
private const int WM_LBUTTONUP = 0x0202;
public event EventHandler<Point> MouseReleased;
private LowLevelMouseProc _proc;
private IntPtr _hookID = IntPtr.Zero;
public GlobalMouseHook()
{
_proc = HookCallback;
}
public void SetHook()
{
_hookID = SetWindowsHookEx(WH_MOUSE_LL, _proc, IntPtr.Zero, 0);
}
public void ReleaseHook()
{
UnhookWindowsHookEx(_hookID);
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
if (wParam == (IntPtr)WM_LBUTTONUP)
{
MSLLHOOKSTRUCT hookStruct = Marshal.PtrToStructure<MSLLHOOKSTRUCT>(lParam);
MouseReleased?.Invoke(this, new Point(hookStruct.pt.x, hookStruct.pt.y));
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
}
再创建ScreenColorPicker类,用于获取鼠标点击屏幕区域的颜色
public class ScreenColorPicker
{
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")]
static extern uint GetPixel(IntPtr hDC, int x, int y);
public static Color GetColorAt(int x, int y)
{
IntPtr deskDC = GetDC(IntPtr.Zero);
uint colorCode = GetPixel(deskDC, x, y);
ReleaseDC(IntPtr.Zero, deskDC);
Color color = Color.FromArgb(255,
(byte)(colorCode & 0x000000FF),
(byte)((colorCode & 0x0000FF00) >> 8),
(byte)((colorCode & 0x00FF0000) >> 16));
return color;
}
}
xaml主页代码:
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<Label/>
<Button Content="开始取色" Width="80" Background="AntiqueWhite" Click="Button_Click"></Button>
<Label/>
<TextBox x:Name="colorCodeLabel" Text="Color Code" HorizontalAlignment="Center" IsReadOnly="True" IsEnabled="True"/>
<Label/>
<Rectangle x:Name="colorDisplay" Height="100" Width="100" Stroke="Black" HorizontalAlignment="Center"/>
<Label>点击按钮以后,鼠标点击任意地方,即可进行取色。</Label>
</StackPanel>
效果图:
xaml.cs代码:
public partial class MainWindow : Window
{
private GlobalMouseHook _mouseHook;
public MainWindow()
{
InitializeComponent();
}
private void MouseHook_MouseReleased(object sender, Point point)
{
Color color = ScreenColorPicker.GetColorAt((int)point.X, (int)point.Y);
Dispatcher.Invoke(() =>
{
// 显示颜色代码
string colorCode = $"#{color.A:X2}{color.R:X2}{color.G:X2}{color.B:X2}";
// TextBox用来显示颜色代码
colorCodeLabel.Text = colorCode;
// 用来展示颜色的Rectangle
colorDisplay.Fill = new SolidColorBrush(color);
if (_mouseHook != null)
{
_mouseHook.ReleaseHook();
_mouseHook.MouseReleased -= MouseHook_MouseReleased;
_mouseHook = null;
}
});
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (_mouseHook != null)
{
_mouseHook.ReleaseHook();
_mouseHook.MouseReleased -= MouseHook_MouseReleased;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_mouseHook = new GlobalMouseHook();
_mouseHook.MouseReleased += MouseHook_MouseReleased;
_mouseHook.SetHook();
}
}
演示效果:
点击按钮,我点击VS这个都沙绿背景,试验效果:
豆沙绿颜色代码就显示到textbox里面,可以人工复制出去使用;矩形框可以复现鼠标刚才点击区域的颜色,进行预览。
就这么简单,没了。这个文章当做水一下了,如果有帮助,欢迎点赞、转发和再看,谢谢各位大佬围观。