首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 取得滑鼠指標下像素顏色

     編輯:關於C語言

核心技術:GDI API 截取桌面畫面

透過 gdi32.dll / user32.dll 建立相容裝置內容(DC)、位圖,複製桌面像素到記憶體位圖,再用 Bitmap.GetPixel 讀取指定座標顏色。

Win32 API 封裝類別


public static class Win32Api
{
    [DllImport("gdi32.dll")] public static extern IntPtr DeleteDC(IntPtr hdc);
    [DllImport("gdi32.dll")] public static extern IntPtr DeleteObject(IntPtr hObject);
    [DllImport("gdi32.dll")] public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest,
        int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
    [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
    [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
    [DllImport("gdi32.dll")] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobjBmp);
    [DllImport("user32.dll")] public static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll")] public static extern IntPtr GetDC(IntPtr hWnd);
    [DllImport("user32.dll")] public static extern int GetSystemMetrics(int nIndex);
    [DllImport("user32.dll")] public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

    public static Bitmap CaptureDesktop()
    {
        int screenX = GetSystemMetrics(0); // SM_CXSCREEN
        int screenY = GetSystemMetrics(1); // SM_CYSCREEN

        IntPtr hdcScreen = GetDC(GetDesktopWindow());
        IntPtr hdcCompat = CreateCompatibleDC(hdcScreen);
        IntPtr hBmp = CreateCompatibleBitmap(hdcScreen, screenX, screenY);

        if (hBmp == IntPtr.Zero) return null;

        IntPtr hOldBmp = SelectObject(hdcCompat, hBmp);
        const int SRCCOPY = 0x00CC0020; // 13369376
        BitBlt(hdcCompat, 0, 0, screenX, screenY, hdcScreen, 0, 0, SRCCOPY);
        SelectObject(hdcCompat, hOldBmp);

        DeleteDC(hdcCompat);
        ReleaseDC(GetDesktopWindow(), hdcScreen);

        Bitmap bmp = Image.FromHbitmap(hBmp);
        DeleteObject(hBmp);
        GC.Collect(); // 釋放非受控資源
        return bmp;
    }
}

表單實作


public partial class MainForm : Form
{
    private Bitmap _desktopBmp;
    private Label _lblColor;

    public MainForm()
    {
        InitializeComponent();
        _lblColor = new Label
        {
            BorderStyle = BorderStyle.FixedSingle,
            Text = "",
            Dock = DockStyle.Top,
            Height = 50,
            BackColor = Color.White
        };
        Controls.Add(_lblColor);
        _lblColor.MouseDown += (s, e) => _desktopBmp = Win32Api.CaptureDesktop();
        _lblColor.MouseUp += (s, e) =>
        {
            if (_desktopBmp != null)
            {
                Color c = _desktopBmp.GetPixel(Cursor.Position.X, Cursor.Position.Y);
                _lblColor.BackColor = c;
                _lblColor.Text = $"R={c.R}, G={c.G}, B={c.B}";
            }
        };
    }
}

關鍵點解析

  • BitBlt + SRCCOPY:高速像素複製
  • CreateCompatibleBitmap/DC:建立螢幕相容的記憶體位圖
  • Image.FromHbitmap:將 HBITMAP 轉為 .NET Bitmap
  • Cursor.Position:取得螢幕座標(非客戶區座標)
  • GC.Collect():確保非受控 GDI 物件及時釋放

現代替代方案


// .NET 6+ 可用 Graphics.CopyFromScreen(無需 P/Invoke)
public static Bitmap CaptureDesktopModern()
{
    var bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    using (var g = Graphics.FromImage(bmp))
        g.CopyFromScreen(Point.Empty, Point.Empty, bmp.Size);
    return bmp;
}

但 GetPixel 仍較慢,高頻取色建議鎖定位圖記憶體 (Bitmap.LockBits) 直接讀取陣列。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved