Inside Windows, applications use "Windows". You can only access these Windows using API's and lots and lots of documentation.
I implemented all useful and working Window API's into a single class. You can do the following with it:
- Return all active Windows on the OS
- Get the process of a Window (handle)
- Set/Get text, location, size, enabled, visible, exstyles, font, window order
- Perform commands: cut, copy, close, destroy, bringtofront,sendtoback etc.
- Capture the Window into a bitmap
- Set transperancy
- Get window parent and children using a built-in Enumerator
Code is in the attachment. It consists of 2 files:
- API.vb: contains direct SendMessage, DefWindowProc, SendInput and key API's
- Window.vb: the main class to use for windows. Contains API's that are used internally
The Window class only holds a pointer (hwnd), it is not storing any background information about Children or states.
When using the same Property more than once at the same time, it is wise to store it in a new Variable:
Note: a window is not a form, a window is everything you see. This includes textboxes, buttons, pictureboxes, labels, everything.Code:Dim w As New Window("Form1") 'Good: Dim s As Size = w.Size w.Location = New Point(s.Width, s.Height) 'Bad: w.Location = New Point(w.Size.Width, w.Size.Height)
It is pretty cool to enable a disabled button and move on in an app while you are actually not allowed to.
Simple usage examples:
Getting a window
- 'Get the Foreground window
- Dim w As Window = Window.GetForeGround
- 'Find a window or child:
- Dim w As Window = Window.Find("notepad")
- Dim c As Window = w.FindChild("edit")
- 'Window children
- Dim children() As Window = w.Children()
- Dim childbyname As Window = w.Children("name")
- Dim childbypoint As Window = w.Children(Cursor.Position)
- Dim childbyindex As Window = w.Children(2)
- 'Get all windows on the current Desktop (OS):
- Dim windows() As Window = Window.All
- 'Get all windows on the current Desktop (OS) using the running Processes:
- Dim windows() As Window = Window.AllFromProcessList()
- 'Get all windows belonging to a certain process:
- Dim p As Process = Process.GetProcessesByName("notepad").First
- Dim windows() As Window = Window.All(p)
- 'Get the Window of one of your own Controls or Forms:
- Dim MyWindow As Window = Window.FromControl(Me)
- 'Get the Next sibling Window above this Window:
- Dim nextwindow As Window = w.NextSibling
- 'Get the Desktop Window on which all other Windows are drawn:
- Dim desktop As Window = Window.GetDesktop()
- 'Get the currently focused window control:
- Dim focusedwindow As Window = Window.GetFocused()
- 'Get the currently focused window inside another Window:
- 'Note that it uses the Thread ID, only one control is focused in each program.
- Dim focusedwindow As Window = w.FocusedWindow
- 'Change the text:
- w.Text &= vbNewLine & "New line"
- 'Kill the process owner:
- Dim p As Process = w.Process
- If Not IsNothing(p) Then p.Kill()
- 'Toggle the enabled state:
- w.Enabled = w.Enabled = False
- 'Move it around and resize
- w.Location = New Point(100, 100)
- w.Size = New Size(300, 200)
- w.Bounds = New Rectangle(100, 100, 300, 200)
- 'Set the Window outside of the screen:
- w.Location = New Point(-w.Size.Width - 50, -w.Size.Height - 50)
- 'Change the WindowState:
- w.WindowState = Window.State.Minimized
- w.WindowState = Window.State.Maximized
- w.WindowState = Window.State.Normal
- 'Perform commands:
- 'Set transparency(key):
- w.Opacity = 128 '50%
- w.TransparencyKey = Color.FromKnownColor(KnownColor.Control)
- 'Change (Ex)Styles:
- w.ExStyle(Window.ExStyles.TopMost) = True
- w.Style(Window.Styles.MaximizeBox) = False
- 'Update (redraw) a Window after you performed a Layout change:
- Dim imgw As Image = w.CaptureWindow()
- Dim imgc As Image = w.CaptureClient()
- Dim screenshot As Image = Window.GetDesktop().CaptureClient()
- 'Device Context operations (using the HDC of a window):
- Dim DC As API.DC = w.GetDC()
- Dim c1 As Color = DC.GetPixel(10, 10)
- Dim c2 As Color = DC.GetPixel(11, 11)
- Dim screenshot As Bitmap = DC.ToBitmap()
- DC.SetPixel(5, 5, Color.Black)
- DC.Pixel(5, 5) = DC.Pixel(10, 10)
- DC.Graphics.FillRectangle(Brushes.Red, 0, 0, 100, 100)
- 'Drawing on other Windows using CreateGraphics:
- Dim g As Graphics = w.CreateGraphics()
- g.FillRectangle(Brushes.Red, 10, 10, 100, 100)
- 'Sending keys (no focus required):
- w.SendKey(Keys.Control And Keys.A, Window.KeyCommand.KeyEvent.Down)
- w.SendKey(Keys.Control And Keys.A, Window.KeyCommand.KeyEvent.Up)
- w.SendChars("All text is now this")
<15th March 2011>
Had to update Window.vb, ExStyle enum was set on Integer while it should've been Long. Also, made sure the handle was passed as HandleRef to either 32 or 64 version of GetWindowLongPtr.
Note: This class has been in development and is still under development, so it *could* contain some bugs here and there.
<19th March 2011>
Got "TransparencyKey" and "Opacity" with internal "AWL" style setting working. Also added "Name" property.
Updated the files, no additional functions are used. They are replaced by shared functions inside the Window class. (GetWindows => Window.All)
Might get rid of the API class as well, just keeping it since it holds non-window related messages.
Good news: I managed to send keys, characters and Control + commands to an external minimized window using PostMessage. Only two arguments will be needed: the key code and the key state (down/up).
<23th March 2011>
Added "SendKey", "SendChar" and "SendString" functions to send input to other windows. Also added "Find" functions for children and all windows on the OS. API now contains an INPUT structure as well that uses SendInput.
<28th March 2011>
Added GetPixel, Client capture and Client bounds, plus the functions "Next/Previous/Top/BottomChild" for returning Window siblings in the Z-order.
<3th April 2011>
Added Input attaching, Focus functions, a DC class for handling Device Context operations, both a Window and Client DC attribute and simply added a lot of classes/functions inside the API class.