WPF写的取色器

2024-08-13 18:58:53 浏览数 (2)

昨天有个小伙子,在找取色器工具。我说,这个应该开发起来很简单,于是,摸了大约半个钟的鱼,开发了一个。现在我把源码和操作案例发出来,供有需要的大佬们玩。(功能过于单一和简单,但是能用)

先创建GlobalMouseHook类,用于实现全局钩子

代码语言:javascript复制
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类,用于获取鼠标点击屏幕区域的颜色

代码语言:javascript复制
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主页代码:

代码语言:javascript复制
 <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代码:

代码语言:javascript复制
 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里面,可以人工复制出去使用;矩形框可以复现鼠标刚才点击区域的颜色,进行预览。

就这么简单,没了。这个文章当做水一下了,如果有帮助,欢迎点赞、转发和再看,谢谢各位大佬围观。

0 人点赞