C# 如何访问窗口?

C# 如何访问窗口?,c#,.net,windows,handle,C#,.net,Windows,Handle,我正在尝试使用其句柄(即System.IntPtrvalue)访问特定窗口: 我还尝试访问另一个演示.net winforms应用程序的主窗口,这是我为此制作的(即,我运行演示应用程序,并试图通过此应用程序访问其主窗口),但也失败了,尽管演示和此应用程序都是.net应用程序。然而,这种成功: var process2 = Process.GetCurrentProcess(); MessageBox.Show(this, process2.MainWindowHa

我正在尝试使用其句柄(即
System.IntPtr
value)访问特定窗口:

我还尝试访问另一个演示.net winforms应用程序的主窗口,这是我为此制作的(即,我运行演示应用程序,并试图通过此应用程序访问其主窗口),但也失败了,尽管演示和此应用程序都是.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++
工作,方法是使用头文件
,然后使用P\invoke

如果不能,是否有其他方法访问窗口(即,而不是使用句柄)

=================== 编辑


我想处理整个窗口对象和它自己的控件

没有得到您真正想要做的,但是如果您尝试

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);
如果不是很抱歉,我没有很好地理解这个问题。

的文档解释了为什么该函数总是为您返回
null

句柄必须已由中的另一个NativeWindow拥有 当前流程;否则,返回null

但是,您所针对的窗口处于不同的过程中。因此,您不能在此处使用
NativeWindow
。您必须将窗口句柄作为
IntPtr
处理

在“编辑”对话框中,您可以声明:

我想处理整个窗口对象及其自己的控件


这不会改变什么。您不能使用
NativeWindow
。您必须处理原始Win32 API。

您希望访问什么?您可以在windows中获取窗口的标题和文本。但是您无法获取另一个应用程序的NativeWindow对象。您需要使用windows API与其他应用程序交互。我曾经在另一个应用程序中劫持过一个对象,但通过了解它的类并发现一个黑客来找到它的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钩子,在我的示例中就是这样。

那么,正如雷蒙德所建议的,为什么不尝试自动化呢?添加一个控制台项目,其中引用了
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();
        }
    }
}

您不能使用user32.dll并调用FindWindow(null,“窗口标题”)?这是另一个.NET应用程序windowsforms应用程序吗?我猜,第一个示例从另一个线程调用一个表单的ui,第二个示例从同一个线程调用。尝试使用BeginInvoke为什么不使用
System.Windows.Automation
命名空间?它的目的是操纵其他应用程序的控件-1如果你不明白这个问题,而且看起来确实如此,那么最好通过评论寻求澄清。这个答案真的没有帮助。顺便说一句,我想帮助您理解如何在这里提供更好的答案,而不是让您失望。谢谢David,首先我需要澄清;)这不是我想要的,但没问题
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();
        }
    }
}