• 締切済み

特定座標のRGB値取得について

kimarioと申します。 実行中の、あるアプリケーションの任意座標位置のRGB値を取得し、その結果を メッセージボックスにて表示させたいと考えております。 しかし下記のプログラムを実行すると、どの座標位置でもすべて(-1)で返ってき てしまいます。 getDCの戻り値が(0)ではないことを確認しているので、デバイスコンテキストの ハンドルは取得できているものと思われます。 API初心者です。よろしくお願いいたします。 補足) アプリケーションのウィンドウタイトルが「XXYYZZ」 色を特定したい座標を(60, 60)としています。 ############################################################################ public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hWnd); [DllImport( "user32.dll" )] static extern int ReleaseDC( IntPtr hWnd, IntPtr hDC ); [DllImport( "gdi32.dll" )] static extern int GetPixel( IntPtr hDC, int x, int y ); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { foreach (Process p in Process.GetProcesses()) { if (p.MainWindowHandle != IntPtr.Zero) { if (p.MainWindowTitle == "XXYYZZ") { IntPtr dc = GetDC(p.MainWindowHandle); MessageBox.Show(GetPixel(dc, 60, 60).ToString()); } } } } }

みんなの回答

  • norachlo
  • ベストアンサー率100% (10/10)
回答No.2

すいません、 どうやら私の方が先入観で書いてしまっていたようです。 MSDN によると―― >現在のクリッピング領域の外側の座標が指定されたときは、 CLR_INVALID が返ります。 CLR_INVALID は wingdi.h をみるに 0xFFFFFFFF = -1 なので、 おそらく上記のエラーが報告されているのだと思われます。 描画範囲の外側を指定していないかどうか、 誤ったクリッピング領域の設定を行っていないかどうか、 などをチェックしてみてはいかがでしょうか。 ……ドキュメントくらい確認しておくべきでした。

kimario
質問者

お礼

norachlo様 本日無事結果を得ることができました。 getDCでは相変わらず(-1)の結果しか返って来ませんでしたが getWindowDCで試したところ無事期待値が返ってきました。 先日、getWindowDCを用いてテストしたが駄目だったと報告しましたが、 おそらく座標上に何らかのウィンドウが重なっていたためと思われます。 検証方法が雑だったためであり反省しております。 >描画範囲の外側を指定していないかどうか が解決のヒントとなりました。 ありがとうございました。

  • norachlo
  • ベストアンサー率100% (10/10)
回答No.1

こんばんは。 (60, 60)の座標は何色でしょうか。もし白なら (r,g,b,a) = (FF,FF,FF,FF) = 0xffffffff = -1 で正常なのだと思います(バイトの並び順は BGRA だったかもしれませんが……)。

kimario
質問者

補足

norachlo様 こんにちは なるほど、固定観念からか(-1)は異常値であると思い込んでいました。 お恥ずかしい限りです。 (60, 60)の色は白ではありません、また別座標(当然白以外)を指定し ても常に(-1)が返ってくるのです。 その後もgetDCをgetWindowDCでやってみたりと試行錯誤してみまし たが未だ結果が得られていません。

関連するQ&A

  • C#のDllImportでuint型をどう指定すればいいのでしょうか?

    [DllImport("User32.dll")] public static extern IntPtr GetNextWindow(IntPtr hWnd,uint wCmd);の uint wCmdに GW_HWNDNEXTを指定したいのですがどのような 書き方で指定したらいいのでしょうか? よろしくお願いいたします

  • C# 他のアプリケーションから複数行取得

    C#で外部のアプリケーションのリッチテキストコントロールの複数行の文字列を取得したいです。 自分は下のコードを書いたのですが、これだと1行しか取得できませんでした。 どこが悪いでしょうか。 ここでは対象のアプリケーションをA、リッチテキストのコントロールをRichEditとします。 button1をクリックしたら、textbox1にRichEditの内容が表示されるようなものを作ろうとしています。 //ここから [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, StringBuilder lParam); private const int WM_GETTEXT = 0x000D; private void button1_Click(object sender, EventArgs e) { IntPtr hWnd = FindWindow("A", ""); if (hWnd != null) { IntPtr hWndChild = FindWindowEx(hWnd, IntPtr.Zero, "RichEdit", ""); StringBuilder strBuilder = new StringBuilder(); SendMessage(hWndChild, WM_GETTEXT, strBuilder.Capacity, strBuilder); StringReader strReader = new StringReader(strBuilder.ToString()); string stResult = string.Empty; while (strReader.Peek() >= 0) { string stBuffer = strReader.ReadLine(); stResult += stBuffer + System.Environment.NewLine; } strReader.Close(); textbox1.Text = stResult; } }

  • VC#2005でエクスプローラを起動後のリサイズ処理

    Visual C# 2005 Express Edition の質問です。OSはXPです。 エクスプローラを起動後、サイズを変更したいので下記のように組んでみたのですが、上手く動きません。   static class Program   {     [DllImport("user32.dll")]     private static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, int bRepaint);     [STAThread]     static void Main()     {       Process p;       p = Process.Start("explorer.exe");       p.WaitForInputIdle();       MoveWindow(p.MainWindowHandle, 50, 50, 1400, 1000, 1);     }   } メモ帳(notepad.exe)でなら問題なく動作するのですが、エクスプローラの場合エクスプローラを起動後 「プロセスは終了しているため、要求された情報は利用できません。」 とエラー表示されてしまいリサイズできません。起動したエクスプローラは終了していません。 原因や解決案などありましたら、よろしくお願いします。

  • C#でウィンドウのアイコン取得する方法

    タスクマネージャのアプリケーションタブに 起動しているアプリケーション名とアイコンが一覧で表示されている部分のように 小さいアイコンを取得したいんですがなかなかうまくいきません。 ファイルに紐付くアイコンと解釈していただいても構いません。 とりあえず、下記のWin32 APIの処理を利用してみましたが SHGetFileInfoだけしかうまくいきませんでした。 しかし、SHGetFileInfoも、アイコンは取得できますがこれはファイルに紐付くアイコンではなく 実行体(EXE)に紐付くアイコンで表示されてしまいました。 開いているウィンドウ情報からだと実行プロセスのEXEのパスしか分からないからです。 ★質問★: ファイルに紐付く小さいアイコンの取得方法を教えてください!できればサンプルソース込みだと助かります。 #region 小さいアイコンを取得するためのWin32 API(ファイルパスから) // SHGetFileInfo関数 [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); // SHGetFileInfo関数で使用するフラグ private const uint SHGFI_ICON = 0x100; // アイコン・リソースの取得 private const uint SHGFI_LARGEICON = 0x0; // 大きいアイコン private const uint SHGFI_SMALLICON = 0x1; // 小さいアイコン private const uint SHGFI_TYPENAME = 0x400;//ファイルの種類 // SHGetFileInfo関数で使用する構造体 private struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその1) [DllImport("user32.dll", EntryPoint = "GetClassLong")] public static extern IntPtr GetClassLongPtr32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")] public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); const int GCL_HICON = (-14); const int GCL_HICONSM = (-34); #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその2) [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); public const int WM_GETICON = 0x7F; public const int WM_SETICON = 0x80; public const int ICON_SMALL = 0; public const int ICON_BIG = 1; #endregion

  • 【C#】FindWindowExの使い方を教えてください

    はじめまして Visual Studio 2005を使用しています。 C#.NETは、いじり初めて1週間の超初心者です。 C#.NETでのFindWindowExの使い方を教えてください。 まずはじめに、vb.netで作ったアプリAの"Form1"があり、その中にテキストボックス"TextBox1"があります。 "TextBox1"のテキスト(キャプション?)には同じく"TextBox1"と入力されています。 そこで、C#側のアプリBでVBのアプリAの"Form1"のハンドルをFindWindowで取得します。 ここまでは出来ました。 次に、FindWindowExを使って"TextBox1"のハンドルを取得したいのですが、どうしてもうまく取得できません(0が返ってきます) 以下、C#のソースです。 (textBox1のMultilineはTrueです) ================================================================== using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern IntPtr FindWindowEx(IntPtr hWnd, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); public IntPtr hWnd = (IntPtr)0; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { IntPtr hWnd; IntPtr hWndTest; string sClassName = null; string sWindowText = "AppA"; // アプリAのウインドウハンドルを取得 hWnd = FindWindow(sClassName, sWindowText); textBox1.Text = "ウインドウのハンドル " + hWnd + "\r\n"; // アプリAのウインドウ内のTextBox1のハンドルを取得 hWndTest = hWnd; sClassName = null; sWindowText = "TextBox1"; hWnd = FindWindowEx(hWndTest, IntPtr.Zero, sClassName, sWindowText); textBox1.Text += "テキストボックスのハンドル " + hWnd; } } } ================================================================== Spy++で覗くとテキストボックスにもハンドルが割り与えられているので取得できるはずだと思っているのですが、どうしてもいまくいきません。 どうか、よろしくご享受願います。 ちなみに、アプリAのテキストボックスのクラス名が”WindowsForms10.EDIT.app.0.378734a”となっているのですが、これはどの環境でビルド(コンパイル)しても不変なのでしょうか? 不変だとしたら、クラス名を使えば悩まずに取得できると思うのですが・・・(実験済み)

  • C# タスクバーを隠したフォーム固定の方法

    前略 ・C#の初心者です。 ・先日このMSN相談箱でtsukasa-12rさんからタスクバーを非表示する下記のプログラムをおしえていだきました。 このプログラムでウィンドウフォームを固定しようとして this.FormBorderStyle = FormBorderStyle.FixedSingle; のコードを1行だけ追加しましたがウィンドウフォームを固定できませんでした。  タスクバーを隠して かつウィンドウフォームを固定したいのですが tsukasa-12rさん以外の方でもかまいませんのでどなたか教えてください。  以上、よろしくお願いします //----------------------------------- using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private const int SW_HIDE = 0; private const int SW_NORMAL = 1; [StructLayout(LayoutKind.Sequential)] struct APPBARDATA { public int cbSize; public IntPtr hwnd; public uint uCallbackMessage; public uint uEdge; public Rectangle rc; public int lParam; }; private const int ABM_SETSTATE = 10; private const int ABS_AUTOHIDE = 1; private const int ABS_ALWAYSONTOP = 2; [DllImport("shell32.dll")] static extern int SHAppBarMessage(int msg, ref APPBARDATA pbd ); public Form1() { InitializeComponent(); // 「タスクバーを自動的に隠す」 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_AUTOHIDE; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを非表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_HIDE); // コントロールボックスを非表示 this.ControlBox = false; // 最大表示 this.WindowState = FormWindowState.Maximized; this.FormBorderStyle = FormBorderStyle.FixedSingle;// ← ウィンドウサイズを固定しようとして追加 → 固定できず } private void button1_Click(object sender, EventArgs e) { // タスクバーを常に表示 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_ALWAYSONTOP; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_NORMAL); // フォームを閉じる this.Close(); } } }

  • VS2010C#からのDLL使用について

    VS2010 C#からVC6で作成したDLLへint配列を引数として渡したい。 VC++6で作成されたDLLがあります。 ここで定義されている int test(char*fname,int* x,int* y); ファイルのフルパスを渡すと 返り値が関数の成否のコードを返す。 処理内で x,y にファイルから読み込んだ値が それぞれ上限100個としてセットして返す といったような関数を C#から呼び出したいのですが 1 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref int* x,ref int* y); 2 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref IntPtr x,ref IntPtr y); と2種類の呼び出し方法をこころみました。 ファイルのフルパスは IntPtr fnamePtr = Marshal.StringToHGlobalAnsi(string型ファイルフルパス); としております。 1の場合は int[] resX = new int[100]; int[] resY = new int[100]; fixed(int* x= resX) fixed(int* x= resY) として呼び出そうとすると : エラー CS1657: '固定変数' であるため、'x' を ref または out 引数として渡せません となり失敗してしまいます。 2 で試みた場合 int size = sizeof(int)*100; IntPtr x = Marshal.AllocHGlobal(size); IntPtr y = Marshal.AllocHGlobal(size); と引き渡したところ ビルドは通りますが 実行時に System.AccessViolationException' のハンドルされていない例外が 発生しました。 追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 となってしまいます。 どのようにすれば思惑通りの結果を得られますでしょうか。

  • dllの呼び出しで引数が渡らないらしい

    dllの呼び出しで引数が渡らないらしい 50間近になって.NETにチャレンジ。日々?!?の毎日です。 ネットに転がっていた「静的にdllを引用する」コードは動きました。が、「動的にdllを引用」するコードをネットからかき集めてくみ上げましたが引数が旨く渡らないのか、思うように動きません。当該dllはgogo.dllで有名だと思います。 正直、ManagedとUnmanagedのメモリ管理とか、呼び出しの引数の渡し方も理解していません。見よう見まね状態ですが、どうしても当該dllを使いたいので掲載してしまいました。(^_^; 下記の問題が2つ 1)引数に「ref」を付けないと「保護されたメモリ…」のエラーが発生してしまう。  たぶん、このような現象が出ること自体に呼び出し方の問題がある? 2)最終的にファイル名fnがdll側に旨く渡っていないように思える。  Marshal…を使うのかも知れませんが、よくわかりません。 素人質問で恐縮ですが、下記のような動的なdllの引用で、静的な引用と同じように動くコードの書き方を教えて下さい。言語はc#です。 下記がコードですが、文字数削るためかなり行を削っています。初期化とかはちゃんとコーディングしています。 [静的にdll引用=>正常終了] [DllImport("gogo.dll", EntryPoint = "MPGE_setConfigure")] static extern int MPGE_setConfigureStrings(int mode, int dwPara1, string dwPara2); (中略) string fn = "D:\\test.wav"; i = MPGE_setConfigureStrings(1, 0, fn); =>この後、test.wavに対しての処理で正常終了が返る(^_^) [動的にdllを引用=>ダメ] [DllImport("kernel32")] static extern int LoadLibrary(string lpLibFileName); [DllImport("kernel32")] static extern IntPtr GetProcAddress(int hModule, string lpProcName); [UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true, CharSet = CharSet.Ansi)] delegate int d_MPGE_setConfigure(ulong mode, ref ulong dwPara1, string dwPara2); [MarshalAs(UnmanagedType.FunctionPtr)] static d_MPGE_setConfigure e_MPGE_setConfigure; (中略) IntPtr p_MPGE_setConfigure = GetProcAddress(dllHandle, "MPGE_setConfigure"); e_MPGE_setConfigure = (d_MPGE_setConfigure)Marshal.GetDelegateForFunctionPointer(p_MPGE_setConfigure, typeof(d_MPGE_setConfigure)); string fn = "D:\\test.wav"; ulong p1 = 0; i = e_MPGE_setConfigure(1, ref p1, fn); =>この後、dllからtest.wavが読み込めない旨のメッセージが吐かれる(T.T) 以上です。

  • GetPixelに使うHDCの作り方

    ビットマップハンドルhBitmap の(x,y)の画素の色を読み取るプログラムに使うデバイスコンテキストとして、  hDC = CreateCompatibleDC(NULL);  SelectObject(hDC, hBitmap);  rgb = GetPixel(hDC, x,y);  DeleteDC(hDC); のように、NULL を指定して、画面と互換性のあるメモリデバイスコンテキストを指定したのですが、正しい色が読み出せません。hDC = GetDC(NULL);でも同じく駄目でした。hDCはどのように作ったらよいのでしょう。 なお、関数の中でGetPixel()を使いたいので、hWnd などは使えません。

  • C#でWin32 MFC DLLが呼び出せない

    C#で以下のエラーが発生し、非常に困ってます。 色々とサイトを見たのですが、DLLが本当にないのでは?という意見が多かったです。 しかし、私の方はDLLファイルはbin->debugフォルダ , obj->debugフォルダ、System32に置いてます。 問題が分かる方、是非教えてください! using System.Runtime.InteropServices; namespace WindowsFormsApplication { public partial class Form1 : Form { [DllImport("Win32DLL_TEST.dll")] private extern static int func(int x, int y); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int n = func3(5, 7);//ここでエラー! } } } エラー内容 'System.DllNotFoundException' のハンドルされていない例外が WindowsFormsApplication.exe で発生しました。 追加情報: DLL 'Win32DLL_TEST.dll' を読み込めません: 指定されたモジュールが見つかりません。 (HRESULT からの例外: 0x8007007E) 備考 DLLは自作のWin32 DLL です。 extern "C"{ __declspec(dllexport) int __cdecl func(int x, int y) } と宣言し、VC++のMFC dialog上では呼び出しを成功しています。

専門家に質問してみよう