Tcler's Wikiには以下のページで2通りの方法が紹介されています。
1つ目はキャンバスアイテムがimageの場合は、中身の画像に対してgetコマンドを使用してピクセルのRGB値を取得し、それ以外のアイテムに対してはitemcget -fillの値を取得するという方法で、2つ目はウィンドウのキャプチャを取得して、それに対してgetコマンドを発行する方法になっています。
が、いずれもいまいちでした。
まず、1つ目の方法ではimage以外の図形のフチの色が取得できません。
2つ目の方法はめちゃくちゃ遅いので実用的ではありません。
以下を参考にして、GDIを使う方法にしました。
http://www.csharp411.com/c-getpixel-and-setpixel/
この方法だと別にcanvasに限らず色が取得できます。
ただし、Windows専用になります。Tkのウィンドウの外に出るとマウスの動きをキャプチャできなくなるので一般的なカラーピッカーみたいなのを作りたければ、そこのところを作りこむ必要があります。
本当はそこまでやりたかったけど、TclでWM_MOUSEMOVEメッセージを処理する方法が分からないので保留。
SetPixelはおまけです。
Ffidlはこちらからダウンロードできます。
package require Tk package require Ffidl namespace eval Win32 { variable HWND_DESKTOP 0 ffidl::callout GetDC {pointer} pointer [ffidl::symbol user32.dll GetDC] ffidl::callout ReleaseDC {pointer pointer} int [ffidl::symbol user32.dll ReleaseDC] } namespace eval Gdi32 { ffidl::callout GetPixel {pointer int int} int [ffidl::symbol gdi32.dll GetPixel] ffidl::callout SetPixel {pointer int int int} int [ffidl::symbol gdi32.dll SetPixel] } proc GetPixel {hdc x y} { set c [Gdi32::GetPixel $hdc $x $y] set R [expr {($c & 0x000000FF)}] set G [expr {($c & 0x0000FF00) >> 8}] set B [expr {($c & 0x00FF0000) >> 16}] return [list $R $G $B] } proc SetPixel {hdc x y r g b} { set c [expr {(int($r & 0x00FF0000) >> 16) | (int($g & 0x0000FF00)) | (int($b & 0x000000FF) << 16) }] Gdi32::SetPixel $hdc $x $y $c } # demo set c [canvas .c] pack $c $c create text 55 95 -text "ABC" -fill white $c create rect 125 25 145 45 -fill red $c create oval 25 125 45 145 -fill green $c create line 15 100 70 125 -fill blue $c create poly 100 65 130 65 100 20 -fill cyan -outline black bind $c <Motion> { set x [winfo pointerx .] set y [winfo pointery .] set hdc [Win32::GetDC $::Win32::HWND_DESKTOP] foreach {R G B} [GetPixel $hdc $x $y] break Win32::ReleaseDC $::Win32::HWND_DESKTOP $hdc wm title . "(x, y) = ($x, $y) : ($R, $G, $B)" } console show |