שאלה:
איך ניתן לדעת מה הצבע של פיקסל שהעכבר עומד עליו בזמן מסוים?
תשובה:
אני מניח שהשאלה מתייחסת לתזוזת עכבר בתוך הדוט-נט פריימוורק ולא תנועות עכבר ברמת מערכת ההפעלה.
הפתרון הוא אחד יחסית פשוט אך עקום ומסתמך על זה שאין באמת פתרון.
המתודה היחידה בכל הפריימוורק שמאפשרת באמת להשיג את הצבע של פיקסל מסויים היא Bitmap.GetPixel שמקבלת נקודה (קורדינטות X ו-Y). זה מסתדר נהדר עם זה שהמתודה היחידה בכל הפריימוורק שמאפשרת לדגום את המסך היא Graphics.CopyFromScreen שמעתיקה חלק מהמסך לתוך אובייקט Graphics. למה זה מסתדר? כי אפשר לבסס אובייקט Graphics על אובייקט Bitmap ככה שההעתקה לתוך Graphics תשפיע בחזרה על ה-Bitmap שלנו.
using(Bitmap tempBitmapToGetPointOnScreen = new Bitmap(1, 1, PixelFormat.Format24bppRgb))
{
using(Graphics graphicsOfTempBitmap = Graphics.FromImage(tempBitmapToGetPointOnScreen))
{
}
}
עכשיו יש לנו אובייקט Graphics שתלוי באובייקט Bitmap.
הגודל של ה-Bitmap שלנו הוא 1,1 כי אנחנו רוצים להעתיק לנקודה 0,0 בתוכו את בדיוק פיסקל אחד מהמסך בגודל 1,1 לתוך נקודה 0,0. השאלה המעניינת היא מה בדיוק אנחנו רוצים להעתיק. כלומר, איזה קורדינטה בפועל נעתיק מהמסך.
נניח כי אנחנו נרשמים לאירוע Control.MouseMove (אפשר למשל לרשום את כל הפקדים על הטופס בזה שבחר את כל הפקדים עם Ctrl+A, ניכנס ל-Properties, ניכנס לאירועים ונלחץ פעמים על MouseMove). בתוך כל מתודה שנרשמת לאירוע MouseMove נקבל קורדינטות X ו-Y של מיקום העכבר הנוכחי. אבל מיקום העכבר הנוכחי אינו מיקום אבסולוטי ביחס למסך, אלא גם צריך להוסיף את הסטיית ציר X ו-Y של המסך עצמו (ביחס לנקודה השמאלית עליונה). כלומר, נחבר את ציר ה-X של המיקום הנוכחי של העכבר + הציר X של המסך שהוא המרחק האופקי מצד שמאל של המסך ונקבל את ציר ה-X שאנחנו צריכים. כנ"ל על ציר Y.
אחרי שחישבנו את הקורדניטה נדגום את הנקודה בפועל:
private void Form7_MouseMove(object sender, MouseEventArgs e)
{
using(Bitmap tempBitmapToGetPointOnScreen = new Bitmap(1, 1, PixelFormat.Format24bppRgb))
{
using(Graphics graphicsOfTempBitmap = Graphics.FromImage(tempBitmapToGetPointOnScreen))
{
Point LocationOfPointOnFormToCopy = new Point(e.X + this.Location.X, e.Y + this.Location.Y);
graphicsOfTempBitmap.CopyFromScreen(LocationOfPointOnFormToCopy, new Point(0, 0), new Size(1, 1));
Color ResultColor = tempBitmapToGetPointOnScreen.GetPixel(0, 0);
label1.Text = ResultColor.ToArgb().ToString("X8");
panel1.BackColor = ResultColor;
}
}
}
(בדוגמה הזו הצגתי את צבע התוצאה ב-Label וב-Panel).
החישובים יכולים להיות מוטעים יחסית (למשל צריך להוסיף את גודל השוליים של הטופס במרבית המקרים), אבל זאת התחלה טובה.
אם צריך שהתוכנית תגיב לשינויי מיקום עכבר בכל מקום על המסך צריך כבר להירשם לאירוע WM_MOUSEMOVE ברמת מערכת ההפעלה (שימוש כבד ב-pinvoke ו-Win32) כדי לעלות אירוע שיקרה לשינוי המיקום של העכבר (מחוץ לחלונות דוט נטיים) ולהשיג את קורדינטות X ו-Y של העכבר, אבל המתודות שראינו למעלה עדיין מתאימות כדי להשיג את הצבע של הפיסקל.
יאיר אובל מוסיף כי הפתרון עובד בדוט נט 2.0 בלבד ולדוט נט 1.1 קיים פתרון הבא העובד בכבדות עם Interop מול מערכת ההפעלה:
How to use Visual C# to obtain the color of the pixel that is referenced by the mouse pointer
קישור: http://www.tapuz.co.il/tapuzforum/main/forumpage.asp?forum=831&firstmsg=12255&archive=1