2012-05-22 2 views
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!!"); 

Я попытался также получить доступ к главному окну другого демонстрационного .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++, используя заголовочный файл <windows.h>, а затем используя P \ invoke.

Если я не могу, есть ли другой способ доступа к окну (т. Е. Вместо использования ручек)?

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

Я хочу иметь дело со всем оконного объекта и его собственных элементов управления

+0

не могли бы вы использовать user32.dll и вызвать FindWindow (NULL, "Window Title")? –

+0

- это другое приложение приложений Windows .NET? – Tigran

+0

@Tigran Да, это –

ответ

2

Затем, как предложил Раймонд, почему бы вам не попробовать Automation? Добавить консольный проект со ссылками на 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(); 
     } 
    } 
} 

reference

+0

Это не то, что я хочу точно, но это не проблема –

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

Если не извините, у вас не получилось ответить на все вопросы.

+1

-1 Если вы не зададите вопрос, и это действительно так, то лучше всего искать разъяснения с помощью комментариев. Этот ответ действительно не помогает. Кстати, я пытаюсь помочь вам понять, как лучше давать ответы здесь, а не делать это. –

+0

где enum 'ShowWindowCommand' существует? –

+0

Извините ShowWindowCommand - это всего лишь int, попробуйте 1. – danielQ

2

Документация NativeWindow.FromHandle объясняет, почему эта функция всегда возвращает null для вас:

Ручка должна быть уже принадлежит другому NativeWindow в текущем процессе ; в противном случае возвращается null.

Но окно, на которое вы нацеливаетесь, находится в другом процессе. Таким образом, вы просто не можете использовать NativeWindow здесь. Вам нужно будет сделать с ручкой окна как IntPtr.

В вашем редактирования вы заявляете:

Я хочу иметь дело со всем оконного объекта и его собственных элементов управления

Это ничего не меняет. Вы не можете использовать NativeWindow. Вам придется иметь дело с необработанным API Win32.

1

Для чего вы хотите получить? Вы можете получить заголовок и текст окон в Windows. Но вы не можете получить объект NativeWindow другого приложения. Вам необходимо использовать API окон для взаимодействия с другими приложениями. Я однажды угнал объект в другом приложении, но сделал это, зная его класс и обнаружив взломать его указатель Idispatch, вы можете посмотреть на него here. Ниже показано, как получить заголовок окна переднего плана, надеюсь, что это поможет.

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-инъекции и крючки для окон, приведенные в моем примере here.

Смежные вопросы