質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

1回答

19433閲覧

【C#】画面上のクリックされた地点のRGB値を取得したい

aridai1221

総合スコア45

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

1クリップ

投稿2016/01/26 14:15

編集2016/01/28 10:11

C#のフォームアプリケーションで
クリックした座標の地点のRGB値を取得したいと思っています。
イメージ説明
イメージ画像はAviUtlの拡張編集プラグインです。
このソフトはクリックしたあらゆる画面上の地点のRGB値を取得する機能を持っています。
これと同じものを私のソフトでも実装したいということです。

方法としては
Graphics::CopyFromScreenで画面のスクリーンショットを撮り、
Bitmap::GetPixelで生成したスクリーンショット上の指定した地点の色から
Colorクラスのインスタンスを生成する
というのを考えています。
しかし、最初の画面のスクリーンショットを撮るという処理ができません。
フォーム外にマウスがあるときにマウスの座標を取得することができないからです。

どのようにすれば実装することができるのでしょうか。

追記
コード載せておきます

C#

1// てきとーにusing文 2using System; 3using System.Drawing; 4using System.Windows.Forms; 5 6// Win32APIを使用するのに必要 7using System.Runtime.InteropServices; 8 9// てきとーに省略 10// (てきとーなクラス内に記述) 11private int R, G, B; 12private Timer timer = null; 13 14private void hoge() 15{ 16 // タイマー 17 timer = new Timer(); 18 timer.Interval = 50; 19 20 // てきとーなタイミングでタイマースタート 21 timer.Start(); 22 23 // 定期的に呼ばれる処理 24 timer.Tick += (object sender, EventArgs e) => 25 { 26 // マウスの左ボタンがクリックされたら 27 if (isLButtonDown()) 28 { 29 // マウスカーソルの絶対座標 30 int x = Control.MousePosition.X; 31 int y = Control.MousePosition.Y; 32 33 // RGB値を抜き出す処理 34 pickupPixelColor(x, y); 35 36 /* 37 処理が完了したので 38 タイマーをStopするなり、 39 他の処理を書くなり 40 てきとーにする 41 */ 42 } 43 } 44} 45 46// Win32APIの使用 (catsforepawさんのコード) 47[DllImport("user32.dll")] 48private static extern short GetKeyState(int nVirtKey); 49 50// マウス左ボタンが押されているかどうかをチェック 51private bool isLButtonDown() 52{ 53 // 押された状態だと最上位ビットが1になるので、負数かどうかで判定可能 54 return GetKeyState(0x01) < 0; 55} 56 57// 指定した画面上の座標のRGB値を取得する 58private void pickupPixelColor(int x, int y) 59{ 60 // 1x1のサイズのBitmapを生成する 61 Bitmap bitmap = new Bitmap(1, 1); 62 63 // 先ほどのBitmapを元にGraphicsを生成する 64 Graphics graphics = Graphics.FromImage(bitmap); 65 66 // Bitmapに指定座標のスクリーンショットをコピーする 67 graphics.CopyFromScreen(new Point(x, y), new Point(0, 0), new Size(1, 1)); 68 69 // BitmapからColorのインスタンスを取得する 70 Color color = bitmap.GetPixel(0, 0); 71 72 // RGB値を保存する 73 R = color.R; 74 G = color.G; 75 B = color.B; 76}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

方法としては3種類くらい思いつきます。

①現在のマウスカーソル位置を示すプロパティ値を取得
②全画面を取り込んで全画面サイズの縁なしフォームで最前面に表示
③自分のフォームでマウスをキャプチャーし、フォーム外のマウスイベントも拾えるようにする

①は単純にCursor.Positionの値を使えば良いですが、クリックイベントなどが拾えないので使いづらいですね。
却下。

②はなんとなくいけそうな気がしますが、別ウインドウでの操作になってしまい、マウスドラッグ中の色をどうやって表示させるのかという問題が出てきますね。
却下。

this.Capture = true;とやると、それ以降のマウスイベントがすべてthisフォームに送られます。これだとフォーム外のマウスイベントを拾うことができます。その間のMouseMoveイベントで渡される座標は当然クライアント座標なので、スクリーン座標に変換するかCursor.Positionでスクリーン座標を取得します。
解除はthis.Capture = false;です。
おそらく、AviUtlもこの方法を使っていると思われます。

※マウスキャプチャーはボタンを押している間しか効果がないので、操作方法としては、スポイトアイコンを押したらそのままボタンを離さずに画面をなぞって色を取り込み、ボタンを離したらその位置で確定させる、というような感じになると思います。


追記
参考にしているAviUtlがどのような挙動なのかインストールして確かめてみました。
どうやら当初考えていたのとは違ったようです。スポイトボタンを押したらボタンを離した状態でデスクトップ上の任意の場所をポイントしてクリックで取り込んでいますね。

なんとなく判りました。おそらく、マウスイベントをハンドリングするのではなく、Win32 APIのGetKeyState関数でリアルタイムにマウスボタンの状態を監視し、押された時点でその場所の色を取り込む、ということをしていますね。

ちょっと面倒です。

C#

1[DllImport("user32.dll")] 2private static extern short GetKeyState(int nVirtKey); 3 4private static const int VK_LBUTTON = 0x01; // マウス左ボタンの仮想キーコード 5 6// マウス左ボタンが押されているかどうかをチェック 7private static bool isLButtonDown() 8{ 9 return GetKeyState(VK_LBUTTON) < 0; // 押された状態だと最上位ビットが1になるので、負数かどうかで判定可能 10}

10~20ミリ秒間隔のタイマーイベントで上記メソッドを使ってマウス左ボタンが押されているかどうかを監視し、押されたらその時点のマウスカーソル座標を取得してその場所をスクリーンキャプチャして取り込む、という方法でできます。

投稿2016/01/26 15:18

編集2016/01/27 23:06
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aridai1221

2016/01/27 21:09

クリックし続けるとマウスの座標を取得できることを確認しました。 しかし、クリックし続けなければいけないのは不便ですね。 これをどうにかしたいです。
catsforepaw

2016/01/27 22:54

AviUtlをインストールして確認してみましたが、動きが予想と違っていましたね。 長くなるので回答の方に追記します。
aridai1221

2016/01/28 10:10 編集

ありがとうございます!! できました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問