#内容
C#でウィンドウのハンドルを取得する検討しています。
参考ソース
EnumWindows
C#
1using System; 2using System.Runtime.InteropServices; 3 4public delegate bool CallBack(int hwnd, int lParam); 5 6public class EnumReportApp 7{ 8 [DllImport("user32")] 9 public static extern int EnumWindows(CallBack x, int y); 10 11 public static void Main() 12 { 13 CallBack myCallBack = new CallBack(EnumReportApp.Report); 14 EnumWindows(myCallBack, 0); 15 } 16 17 public static bool Report(int hwnd, int lParam) 18 { 19 Console.Write("Window handle is "); 20 Console.WriteLine(hwnd); 21 return true; 22 } 23}
リストを見ると、コールバック関数を使っているのですが、
EnumWindows関数の戻り値は、常にBOOLしか戻ってこない状態で、
取得したいハンドル名を、WINDOWSコンソールに吐き出されています。
#知りたいこと
最終的にはDLLとして、配列変数にして戻したいと思っています。
方法としては
1)コンソールの出力をテキストにして戻す
→ DLLを呼ぶ側に解読するソースをつけないと行けないので、不細工です。
2)メインの外にグローバル配列変数を作る
→ そもそも関数の戻り値として、DLLの呼び出し側に返信できるのか疑問。
C#の使い方としては、もっとスマートな方法は無いものでしょうか?
他の言語では、
サンプル: "列挙(コールバック)時の情報を列挙後へ渡す"
の例がありましたが、C#のソースがあれば紹介いただきたいです。
リンク内容
#現在のコード
もちろん、呼び出しのエントリポイントの外にクラス宣言があり
このまま走らせても、「インデックスが配列の境界外」というエラーになってしまいます。
VBA
1Sub Vba() 2 3Set DLL = New ExcelVbaExt.WindowWhnd 4Dim com As Variant 5Set com = DLL.WindowTitleList 6c = com.Interface 7 8End Sub 9
C#
1using System; 2using System.Runtime.InteropServices; 3using System.Text; 4 5namespace ExcelVbaExt 6{ 7 [ComVisible(true)] 8 [ClassInterface(ClassInterfaceType.AutoDual)] 9 public class InnerClass 10 { 11 public int WHnd; 12 public string APPName; 13 public int Left; 14 public int Top; 15 public int Right; 16 public int Bottom; 17 } 18 19 [ComVisible(true)] 20 [ClassInterface(ClassInterfaceType.AutoDual)] 21 public class ClassApp 22 { 23 public InnerClass[] Interface; 24 } 25 26 [ComVisible(true)] 27 [InterfaceType(ComInterfaceType.InterfaceIsDual)] 28 public interface IWindowWhnd 29 { 30 ClassApp WindowTitleList(); 31 } 32 33 [ClassInterface(ClassInterfaceType.None)] 34 public class WindowWhnd : IWindowWhnd 35 { 36 public static ClassApp _hWndList = new ClassApp(); 37 public static int count; 38 39 [DllImport("user32.dll")] 40 private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); 41 42 [StructLayout(LayoutKind.Sequential)] 43 private struct RECT 44 { 45 public int left; 46 public int top; 47 public int right; 48 public int bottom; 49 } 50 51 [DllImport("user32.dll")] 52 [return: MarshalAs(UnmanagedType.Bool)] 53 private extern static bool EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr lparam); 54 55 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 56 private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); 57 58 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 59 private static extern int GetWindowTextLength(IntPtr hWnd); 60 61 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 62 private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 63 64 private delegate bool EnumWindowsDelegate(IntPtr hWnd, IntPtr lparam); 65 66 public ClassApp WindowTitleList() 67 { 68 count = 1; 69 _hWndList = new ClassApp(); 70 _hWndList.Interface = new InnerClass[1]; 71 72 EnumWindows(new EnumWindowsDelegate(EnumWindowCallBack), IntPtr.Zero); 73 74 return _hWndList; 75 } 76 77 private static bool EnumWindowCallBack(IntPtr hWnd, IntPtr lparam) 78 { 79 int textLen = GetWindowTextLength(hWnd); 80 if (0 < textLen) 81 { 82 StringBuilder tsb = new StringBuilder(textLen + 1); 83 GetWindowText(hWnd, tsb, tsb.Capacity); 84 85 RECT rect; 86 bool flag = GetWindowRect(hWnd, out rect); 87 88 count += 1; 89 Array.Resize(ref _hWndList.Interface, count); 90 _hWndList.Interface[count] = new InnerClass(); 91 _hWndList.Interface[count].WHnd = (int)hWnd; 92 _hWndList.Interface[count].APPName = tsb.ToString(); 93 _hWndList.Interface[count].Left = rect.left; 94 _hWndList.Interface[count].Top = rect.top; 95 _hWndList.Interface[count].Right = rect.right; 96 _hWndList.Interface[count].Bottom = rect.bottom; 97 } 98 return true; 99 } 100 } 101}
回答2件
あなたの回答
tips
プレビュー