2012-04-12 47 views
2

我希望能夠確定屏幕上特定點處的Winform的背景顏色,因此我可以根據該特定顏色採取一些操作。可悲的是,System.Drawing庫似乎沒有指定一種方法,使我能夠這樣做。確定WinForms應用程序中像素的顏色

我應該如何確定某一點的顏色?

+0

可能的重複http://stackoverflow.com/questions/1483928/how-to-read-the-color-of-a-screen-pixel – Marco 2012-04-12 09:17:25

回答

5

使用:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.Drawing; 

namespace ColorUnderCursor 
{ 
    class CursorColor 
    { 
     [DllImport("gdi32")] 
     public static extern uint GetPixel(IntPtr hDC, int XPos, int YPos); 

     [DllImport("user32.dll", CharSet = CharSet.Auto)] 
     public static extern bool GetCursorPos(out POINT pt); 

     [DllImport("User32.dll", CharSet = CharSet.Auto)] 
     public static extern IntPtr GetWindowDC(IntPtr hWnd); 

     /// <summary> 
     /// Gets the System.Drawing.Color from under the mouse cursor. 
     /// </summary> 
     /// <returns>The color value.</returns> 
     public static Color Get() 
     { 
      IntPtr dc = GetWindowDC(IntPtr.Zero); 

      POINT p; 
      GetCursorPos(out p); 

      long color = GetPixel(dc, p.X, p.Y); 
      Color cc = Color.FromArgb((int)color); 
      return Color.FromArgb(cc.B, cc.G, cc.R); 
     } 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct POINT 
    { 
     public int X; 
     public int Y; 
     public POINT(int x, int y) 
     { 
      X = x; 
      Y = y; 
     } 
    } 
} 
+0

這是不完整的,其中是你定義的'dc'變量致電GetPixel? – fuaaark 2012-04-12 09:27:51

+0

檢查更新... – 2012-04-12 09:28:35

+0

+1,歡迎 – 2012-04-12 11:42:05

4

假設您想要遠離Win32 API,可以使用Graphics.CopyFromScreen()將屏幕的內容繪製到Bitmap對象。從那裏,您只需使用Bitmap.GetPixel()即可檢索具有正確顏色的Color對象。

下面是一些代碼,你可以用它來獲取完整的桌面(多顯示器的工作原理):

public Image GetScreenshot() 
{ 
    int screenWidth = Convert.ToInt32(System.Windows.SystemParameters.VirtualScreenWidth); 
    int screenHeight = Convert.ToInt32(SystemParameters.VirtualScreenHeight); 
    int screenLeft = Convert.ToInt32(SystemParameters.VirtualScreenLeft); 
    int screenTop = Convert.ToInt32(SystemParameters.VirtualScreenTop); 

    Image imgScreen = new Bitmap(screenWidth, screenHeight); 
    using (Bitmap bmp = new Bitmap(screenWidth, screenHeight, PixelFormat.Format32bppArgb)) 
    using (Graphics g = Graphics.FromImage(bmp)) 
    using (Graphics gr = Graphics.FromImage(imgScreen)) 
    { 
     g.CopyFromScreen(screenLeft, screenTop, 0, 0, new Size(screenWidth, screenHeight)); 
     gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 
     gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 
     gr.DrawImage(bmp, new Rectangle(0, 0, screenWidth, screenHeight)); 
    } 

    return imgScreen; 
} 
2

這是一個稍微不同的看法在另一已經提供的答案,因爲你只說明你想確定「顏色」,但沒有明確說明你想要RGB值。

這種區分是必要的,因爲人眼可能感覺不到顏色的變化。例如,假設您對檢測顏色「藍色」感興趣。值(5,5,240)和(10,10,255)僅與(0,0,255)非常微妙地不同。實際上,差異非常微妙,您需要並排比較色板以區分它們,即使如此也取決於顯示器的質量。它們在我的臺式機顯示器上略有不同,但在我的筆記本電腦上無法區分。長話短說,RGB值是確定顏色的一個壞方法。

有很多方法可以幫助計算顏色之間的差異,最常見的是Delta-E方法。然而,如果你只是想要一個快速和骯髒的方法,這可能會被殺死。將RGB空間轉換爲HSV,並使用色調差異來確定顏色。修改阿門的例子,你會得到如下:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.Drawing; 

class CursorHue 
    { 
     [DllImport("gdi32")] 
     public static extern uint GetPixel(IntPtr hDC, int XPos, int YPos); 

     public static float GetHue(Point p) 
     {   
      long color = GetPixel(dc, p.X, p.Y); 
      Color cc = Color.FromArgb((int)color); 
      return cc.GetHue(); 
     } 
    } 

純藍色有240色調值前面的例子(5,5,... 240)和(10,10,255)都具有240的色調。這是一個好消息,因爲它意味着色相是對RGB差異相當寬容的衡量標準,並且差異也很快計算(即只需在色調值上進行絕對差異)。在這一點上,我們還應該引入另一個管理色差容差的參數。 15度的色調容差將使系統相當健壯。

這裏是一個比較兩種顏色,以確定它們是否是可接受類似

public static bool AreSimilar(Color c1, Color c2, float tolerance = 15f) 
{ 
    return Math.Abs(c1.GetHue() - c2.GetHue() <= tolerance; 
} 

有關爲何工作的更深入的解釋示例代碼,請參見HSV色彩空間這個維基百科article

相關問題