How to Access ANY Window
Unfortunately, you can't use .NET to access other application windows. But you can use in your .NET application more lower-level library - Windows API (WinAPI).
Absolutely any window on Windows creating and managing by a set of libraries WinAPI. High-level object-oriented libraries, such as Winforms, MFC, Qt (in Windows version) are just high-level covers for WinAPI. No matter what framework you use. In any case, you can access windows using WinAPI.
WinAPI isn't an object-oriented library. Therefore, it uses numerical identifiers for "objects", e.g. windows and others. Any window has a unique numerical identifier (handle) which is generated by the system accidentally when it creates. This identifier is hWnd
(handle of window) and represents a certain long
value (or, what equivalent in .NET, a IntPtr
value). This identifier does not change throughout all life of the window - until it is closed and a new window created.
You can import from WinAPI
library "user32.dll" any function to work with windows and access ANY window by using its hWnd
.
For example (SetWindowText()
function changes window title to custom text):
C#
using System.Runtime.InteropServices;
...
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetWindowText(IntPtr hWnd, String lpString);
...
...
IntPtr hWnd = ...;
SetWindowText(hWnd, "Lorem ipsum");
VB.NET
Imports System.Runtime.InteropServices
...
<DllImport("user32.dll", SetLastError := True, CharSet := CharSet.Auto)> _
Public Shared Function SetWindowText(hWnd As IntPtr, lpString As String) As Boolean
End Function
...
...
Dim hWnd As IntPtr = ...
//or Dim hWnd As Long = ...
SetWindowText(hWnd, "Lorem ipsum")
Optionally, you can use your form's hWnd
:
C#
IntPtr hWnd = this.Handle;
VB.NET
Dim hWnd As IntPtr = Me.Handle
How to Get hWnd of Needed Window?
There are at least 3 methods - and all also using WinAPI:
1. Get hWnd by window's title text using WinAPI FindWindow function.
C#
using System.Runtime.InteropServices;
...
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
..
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
...
IntPtr hWnd = FindWindow(null, "Calculator");
MoveWindow(hWnd, 100, 200, 300, 400, true);
VB.NET
Imports System.Runtime.InteropServices
...
<DllImport("user32.dll", SetLastError := True)> _
Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
...
<DllImport("user32.dll", SetLastError := True)> _
Private Shared Function MoveWindow(hWnd As IntPtr, X As Integer, Y As Integer, _
nWidth As Integer, nHeight As Integer, bRepaint As Boolean) As Boolean
End Function
...
Dim hWnd As IntPtr = FindWindow(Nothing, "Calculator")
MoveWindow(hWnd, 100, 200, 300, 400, True)
2. Get hWnd by window at point of screen using WinAPI WindowFromPoint function.
Warning: Point coordinates must compare with window's frame, not client area!
C#
using System.Runtime.InteropServices;
...
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
...
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
...
IntPtr hWnd = WindowFromPoint(100, 100);
SetForegroundWindow(hWnd);
VB.NET
Imports System.Runtime.InteropServices
...
<DllImport("user32.dll")> _
Private Shared Function WindowFromPoint(xPoint As Integer, yPoint As Integer) As IntPtr
End Function
...
<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(hWnd As IntPtr) As Boolean
End Function
...
Dim hWnd As IntPtr = WindowFromPoint(100, 100)
SetForegroundWindow(hWnd)
3. Get hWnd by window's class name using WinAPI FindWindow function.
Window does not have hWnd
(long
) identifier only. It also has a string
identifier, class name. Class name (class) is a permanent identifier. It does not change when window recreates. It is not generated randomly, it is not given by programmer.
First, you can get any window class name by using WinAPI GetClassName
function.
Next, you can use this class name in your application to accurately identify this window.
C#
using System.Runtime.InteropServices;
...
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
...
[DllImport("user32.dll")]
static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
...
IntPtr hWnd = FindWindow("Notepad", null);
EnableWindow(hWnd, false);
VB.NET
Imports System.Runtime.InteropServices
...
<DllImport("user32.dll", SetLastError := True)> _
Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
...
<DllImport("user32.dll")> _
Private Shared Function EnableWindow(hWnd As IntPtr, bEnable As Boolean) As Boolean
End Function
...
Dim hWnd As IntPtr = FindWindow("Notepad", Nothing)
EnableWindow(hWnd, False)
References for Other WinAPI Functions and Interfaces