Isn't there a nice class I could get from somewhere that encapsulates all the dirty work and provides a humanisitic collection of all windows on the screen just like, for example, the controls collection of a VB form?
Well, I couldn't think of one (Merrion later provided a link to EventVB.dll) so I decided to write this. It has two classes and a module and wraps a lot of common windows-related API functions.
CWindows
This is a collection class which contains all the top-level windows returned through the EnumWindows() API. Just call .GetWindows() to populate the collection. You can enumerate all the windows by using a For Each syntax (thanks brucevde).
VB Code:
Dim objWindows As CWindows
Dim objWindow As CWindow
objWindows.GetWindows
For Each objWindow In objWindows
' do something
Next objWindow
It contains some other functions also:
WindowFromHWND - Returns a CWindow object for the hWnd provided, from the collection (so you need to call .GetWindows() first).
WindowFromCaption - Returns a CWindow object for the window caption provided, from a call to FindWindow() (no need to call .GetWindows() first).
WindowFromClass - Same as WindowFromCaption, but with class name instead.
WindowFromClassAndCaption - Both (duh).
HWNDs - Returns an array of hWnds for all top-level windows.
DesktopWindow - Returns the hWnd of the desktop window.
ForegroundWindow - Returns the hWnd of the current foreground window.
ShellWindow - Returns the hWnd of the "shell" window, from GetShellWindow() - I don't actually know what this is.
CWindow
This class contains all the window-related properties etc. A CWindow object returned by a function in CWindows will have its information populated already. One you create yourself will need to be "attached" to a window by calling .GetInfo(hWnd), e.g.:
VB Code:
' From within a form
Dim objWindow As CWindow
objWindow.GetInfo Me.hWnd
' Now you can use objWindow to access extended properties/methods of the form, described below.
' Don't forget to Set it to Nothing when you've finished.
Set objWindow = Nothing
It contains the following properties (read/write unless marked otherwise):
AlphaEnabled - Boolean, whether alpha-blending is enabled.
AlphaLevel - Byte, level of opacity from 0 to 255 where 255 is opaque and 0 is transparent.
AlwaysOnTop - Boolean, whether the window is currently set as always on top.
Ancestor - Returns a CWindow object of the window's root ancestor (from GetAncestor() which walks the chain of windows by calling GetParent() until it finds the root window).
Left, Top, Right, Bottom, Width, Height - Longs, window coordinates and size (in pixels).
Caption - String, window caption.
Children - A collection of CWindow objects for each of the window's child windows. Must be populated first by a call to .GetChildren().
ChildWindow - Returns a CWindow object from the collection of child windows, for an index supplied. Must call .GetChildren() first.
Classname - String, class name of the window.
CloseButton - Boolean (read-only), whether the window has a close button.
ColourKey - Long, RGB value for the alpha colour key of the window. This is a colour that is made transparent (if you use it).
ColourKeyEnabled - Boolean, whether colour key transparency is enabled or not.
hAppInstance - Handle to the application instance of the window. Read-only.
hWnd - Window handle, read-only.
Layered - Boolean, whether the window is a "layered" window or not (WS_EX_LAYERED). This must be True, if you want to use alpha blending (with or without a colour key).
MaxButton - Boolean (read-only), whether the window has a maximize button.
MinButton - Same, for the minimize button.
ModuleFileName - This is supposed to return a string containing the file name of the application the window belongs to. However, in practice, it doesn't work very often. Read-only.
Parent - Returns a CWindow object of the window's parent (hWnd from a call to GetParent()).
Subclassed - Boolean, whether the window has been subclassed or not by using .Subclass/.Unsubclass. Read-only.
TopMostChild - Returns a CWindow object of the window's top-most child window.
It also contains the following methods:
Activate - Sets the window as the foreground window (gives it focus).
CloseWindow - Attempts to close the window, by sending a WM_CLOSE message.
FindChildByCaption - If succesful, returns a CWindow object for the child window with the caption passed.
FindChildByClassName - Same, but with class name instead.
GetChildren - Call this to populate the .Children collection of child CWindow objects.
GetClientDCHandle - Returns a handle to the DC of the window's client area. You must release this when you have finished by using the ReleaseDC() API.
GetWindowDCHandle - Returns a handle to the DC of the window (including the non-client area). You have to release this too.
Hide - Hides the window (would you believe).
PostWindowMessage - Posts a message to the window by using PostMessage().
QuitAppplication - Posts a WM_QUIT message to try to get the application to quit.
Refresh - Refreshes the client area of the window by calling UpdateWindow().
SendWindowMessage - Send a message to the window using SendMessage().
SetText - Sends a WM_SETTEXT message. Useful for textboxes.
Show - Show the window, you can optionally pass a show state as well.
Subclass - Subclass the window using a WndProc address you supply. For this to work, the window needs to be in the calling thread.
Unsubclass - Undoes the work of .Subclass().
ZOrder - Just like a VB control's .ZOrder method, you can vbBringToFront or you can vbSendToBack.
MCallbacks
Just a small module containing the EnumWindowsProc function (which incidentally contains a demo of how to create an collection object reference from a pointer).
Attachment
The attachment contains the two classes, the module, in a project Test.vbp, which doesn't do much, but has a form with a bit of code demonstrating how to use the classes. It also has some commented out code that you can try in the Immediate window, mainly working with a Notepad window.
I hope this is useful for someone If you spot any bugs, or think of anything you'd like me to add to this, just post here, or PM me, and I will do my best
Last edited by penagate; Aug 20th, 2005 at 03:16 AM.
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
Updated with a bunch of new methods to CWindow, property let procedures for a lot of the read-only properties (coordinates + height, caption), and some new property get procedures (MinButton, MaxButton, CloseButton).
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
penagate,
I was going to play around with the subclass method of the CWindow class. Obviously this method will only work for Windows in my process, so I needed to set the class to one of my windows. I thought that the GetWindowFromhWnd would work, but no. Also there is no Add method to the collection so I could just add it.
How is the subclass method meant to be used? I have some good ideas about how to implement it so that it raises an event in the user's class whenever a message arrives.
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
Well it was meant to be just a wrapper for SetWindowLong, so you still need to provide your own WndProc and pass the address to the .Subclass method.
However, I originally intended it to raise an event in the class, so that the user doesn't need to mess around with the WndProc code at all. I tried that, but ran into an issue where I was maintaining a collection of subclassed windows and calling their events from the WndProc, but I kept getting messages for windows I hadn't added to the collection (obviously child windows) and so it didn't work. As yet I haven't figured out a way to fix that. Maybe you have some better ideas?
What do you mean by GetWindowFromhWnd not working? Did it return a class containing correct data, or was it just that the Subclass method didn't work?
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
I've changed the WindowFromhWnd() method so that it doesn't require calling GetWindows() first. I'll post an updated version sometime (will wait for you on the subclassing one).
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
OK,
Here is my subclassing idea. I illustrate it in the example. Command2 now subclasses the form and a new button I added.
The Cwindows Class now has an Event
VB Code:
WMArrival(hWnd As Long, uMsg As Long, wParam As Long, lParam As Long, lRetVal As Long)
This is where the messages will arrive for each class. The lRetVal is used to return a value for the Window Procedure function, since I can't return a value from an Event. So you do something like this
VB Code:
Private Sub objButton_WMArrival(hWnd As Long, uMsg As Long, _
Oh, I added a callWindProc property to the class also.
You can ignore the compiler directives I added they don't do anything unless you change the line
VB Code:
#Const DEBUGWINDOWPROC = -1
If you do that you'll have to add a reference to DbgWProc.dll which can be downloaded from several sites. It helps debug subclassed programs and has no effect when compiled.
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
Cheers
I'll be uploading a newer version later tonight that includes moeur's subclassing code, so stick around for that. I may also try adding more advanced stuff like, hooking, modifying menus, etc.
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
Now, I hope you can help me out on this one as well.
Could you For Heaven's Sake please explain in "HUMAN" what sending messages, hooking are subclassing are. Don't you have a reference to an article that explains all these API issues very clearly and nicely? Man, I'll be really grateful.
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
Haha, ok. Sorry about not uploading it yet BTW. I'll get around to it later tonight I promise
For the authoritive word on windows in the Win32 API, including messages and hooking, have a look here, straight from the horse's mouth
As for subclassing, all that is is replacing the WndProc of a window within your thread with one you provide yourself. You need to store the pointer to the old window procedure (from the point at which you started subclassing) and call that from your replacement WndProc, so that the previous code can execute also. But the best part is, you get to muck with the messages and their parameters as they come through, and achieve what you want that way.
You'll hopefully understand that last paragraph, once you've read through the link above it
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
I just discovered a problem with part of my subclassing technique. The current technique uses the SetWindowLongPtr API Function to store a pointer to the current instance of the class in the subclassed window's user data area. Unfortunately, some VB controls use that area and will crash if you change this data value. RichTextBox is one example.
So, a better way to store that data is to add a new window property to the subclassed window using the SetProp API function
VB Code:
'store handle to this class in UserData section of subclassed window
Re: [VB] CWindows+CWindow - classes wrapping windows-related API functions
Ive just looked through a couple of these files and they have just boggled my mind, what Ive done is created a form in VB6 and i want it to stay on top of any other programs I have running on my pc eg. microsoft word. its a small form that will sit up in the top-right corner. if u could help me out with this it would be much appreciated
thanks in advance!!
dont believe in all that you've been told!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!