前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF写的取色器

WPF写的取色器

作者头像
Wesky
发布2024-08-13 18:58:53
690
发布2024-08-13 18:58:53
举报
文章被收录于专栏:Dotnet Dancer

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Dotnet Dancer 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档