3

ハンドル(つまりSystem.IntPtr値)を使用して特定のウィンドウにアクセスしようとしています:

        // Getting the process of Visual Studio program
        var process = Process.GetProcessesByName("devenv")[0];

        // Showing the handle we've got, we've no problem
        MessageBox.Show(this, process.MainWindowHandle.ToString());

        // Attempting to get the main window object by its handle
        var wnd = NativeWindow.FromHandle(process.MainWindowHandle);

        // always fails
        if (wnd == null)
            MessageBox.Show("Failed");
        else
            MessageBox.Show(wnd.ToString(), "Yeeeeees!!");

この目的のために作成した別のデモ.netwinformsアプリケーションのメインウィンドウにもアクセスしようとしましたが(つまり、デモアプリケーションを実行し、このアプリケーションでメインウィンドウにアクセスしようとしました)、失敗しましたが、両方ともデモとこのアプリケーションは.NETアプリケーションです。ただし、これは成功します。

        var process2 = Process.GetCurrentProcess();
        MessageBox.Show(this, process2.MainWindowHandle.ToString());

        var wnd2 = NativeWindow.FromHandle(process2.MainWindowHandle);
        if (wnd2 == null)
            MessageBox.Show("Failed");
        else
            MessageBox.Show(wnd2.ToString(), "Yes");

同じアプリケーションから呼び出されるので、これは機能すると思います。では、ハンドルを使用して別のプログラムのウィンドウオブジェクトにアクセスするにはどうすればよいですか?C\C++ヘッダーファイル<windows.h>を使用してからP\invokeを使用することで機能すると思いました。

できない場合、ウィンドウにアクセスする別の方法はありますか(つまり、ハンドルを使用するのではなく)?

=================== 編集

ウィンドウオブジェクト全体と独自のコントロールを処理したい

4

4 に答える 4

2

のドキュメントでNativeWindow.FromHandleは、その関数が常に返さnullれる理由を説明しています。

ハンドルは、現在のプロセスで別のNativeWindowによってすでに所有されている必要があります。それ以外の場合は、nullが返されます。

ただし、ターゲットにしているウィンドウは別のプロセスにあります。したがって、ここでは使用できませんNativeWindow。あなたはとしてウィンドウハンドルでやらなければならないでしょうIntPtr

あなたの編集であなたは述べます:

ウィンドウオブジェクト全体と独自のコントロールを処理したい

それは何も変わりません。使用できませんNativeWindow。生のWin32APIを処理する必要があります。

于 2012-05-22T15:54:54.463 に答える
2

次に、レイモンドが提案したように、自動化を試してみませんか?UIAutomationClientおよびへの参照を含むコンソールプロジェクトを追加します UIAutomationTypes

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Automation;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var pInfo = new ProcessStartInfo("notepad");

            var p = Process.Start(pInfo);

            p.WaitForInputIdle();

            AutomationElement installerEditorForm = AutomationElement.FromHandle(p.MainWindowHandle);

            // menus
            AutomationElementCollection menuBars = installerEditorForm.FindAll(TreeScope.Children, new PropertyCondition(
                AutomationElement.ControlTypeProperty, ControlType.MenuBar));

            var mainMenuItem = menuBars[0];

            AutomationElementCollection menus = mainMenuItem.FindAll(TreeScope.Children, new PropertyCondition(
                AutomationElement.ControlTypeProperty, ControlType.MenuItem));

            var fileMenuItem = menus[0];

            ExpandCollapsePattern fileMenuItemOpenPattern = (ExpandCollapsePattern)fileMenuItem.GetCurrentPattern(
                ExpandCollapsePattern.Pattern);

            fileMenuItemOpenPattern.Expand();

            AutomationElement fileMenuItemNew = fileMenuItem.FindFirst(TreeScope.Children,
                new AndCondition(
                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuItem),
                    new PropertyCondition(AutomationElement.NameProperty, "New")));

            Console.Read();
        }
    }
}

参照

于 2012-05-23T21:51:04.237 に答える
1

何にアクセスしたいですか?Windowsのウィンドウのタイトルとテキストを取得できます。ただし、別のアプリケーションのNativeWindowオブジェクトを取得することはできません。他のアプリケーションと対話するには、WindowsAPIを使用する必要があります。私はかつて別のアプリでオブジェクトをハイジャックしましたが、そのクラスを知り、そのIdispatchポインターを見つけるためのハックを発見することで、ここでオブジェクトを調べることができます。以下は、フォアグラウンドウィンドウのタイトルを取得する方法です。これがお役に立てば幸いです。

using System.Runtime.InteropServices;

using System.Text;

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

private string GetActiveWindowTitle()
{
    const int nChars = 256;
    IntPtr handle = IntPtr.Zero;
    StringBuilder Buff = new StringBuilder(nChars);
    handle = GetForegroundWindow();

    if (GetWindowText(handle, Buff, nChars) > 0)
    {
        return Buff.ToString();
    }
    return null;
}

追加するかもしれませんが、別のアプリケーションのウィンドウをサブクラス化しようとしている場合は、上記の私のリンクを参照してください。これを行う唯一の方法は、DLLインジェクションとWindowsフックを使用することだと思います。これは、ここにある私の例で例示されています。

于 2012-05-22T15:56:27.347 に答える
0

あなたが本当にやろうとしていることを理解できませんでしたが、多分あなたがしようとしたら...

public class ApiUtils
{
    [DllImport("user32")]
    public static extern int SetForegroundWindow(IntPtr hwnd);

    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommand nCmdShow);

    [DllImport("user32.dll")]

    public static extern int GetForegroundWindow();

    public static void ActiveWindow(IntPtr hwnd)
    {
        if ((IntPtr)GetForegroundWindow() != hwnd)
        {
            ShowWindow(hwnd, ShowWindowCommand.ShowMaximized);
        }
    }


}

今それを呼んでいます...

Process p = Process.Start(new ProcessStartInfo() { FileName = "someApp.exe"});

ApiUtils.ShowWindow(p.MainWindowHandle, WindowShowStyle.ShowNormal);

申し訳ありませんが、質問はあまりうまくいきませんでした。

于 2012-05-22T15:49:32.963 に答える