Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access a window?

I'm trying to access a specific window using its handle (that is System.IntPtr value):

        // 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!!");

I have tried also to access another demo .net winforms application's main window, that I have made for this purpose, (i.e. I run the demo application, and attempted to access its main window by this application), and failed, too, although both the demo and this application are .NET applications. However, this successes:

        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");

I think this works because it is invoked from the same application. So, how can I access some another program's window object by its handle? I thought it can work using C\C++ by using header file <windows.h> and then using a P\invoke.

If I can't, is there another way to access a window (i.e. rather than using handles)?

=================== EDIT

I want to deal with the entire window object and its own controls


2 Answers

Then, as Raymond suggested, why don't you try with Automation? Add a console project with references to UIAutomationClient and 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();
        }
    }
}

reference

like image 161
danielQ Avatar answered Oct 22 '25 05:10

danielQ


The documentation for NativeWindow.FromHandle explains why that function always returns null for you:

The handle must already be owned by another NativeWindow in the current process; otherwise, null is returned.

But the window that you are targeting is in a different process. So you simply cannot use NativeWindow here. You will have to make do with the window handle as an IntPtr.

In your edit you state:

I want to deal with the entire window object and its own controls

That changes nothing. You can't use NativeWindow. You will have to deal with the raw Win32 API.

like image 20
David Heffernan Avatar answered Oct 22 '25 06:10

David Heffernan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!