Moving other application's windows

Posted on 2003-11-05
Last Modified: 2010-05-01
I have an application that's a Shell App bar that runs at the top of the screen.

We have a poorly written app that we use for our customer database... problem is, this application slowly moves upwards in increments at screen resolutions of 1024x768 or higher for some reason. Eventually, it works its way underneath my app bar.

So, I want my app bar to "bump" windows down X pixels if they take over (or under technically) its space. I'll probably fire it when a user moves their mouse over my App Bar or even clicks it; I think I'd need to scan for all open windows, and if their window hwnd is within the top X pixels, bump them down Y pixels...

Here's the abstract code of what I'm trying to do:

Sub MoveWindowsAtTheTop()
    For Each Window that's not maximized
        If The Top Position of the Window is within X pixels of the top of the screen Then
            Move this window down Y pixels
        End If
End Sub

I'm no API expert and I can't get past Enumerating Unmaximized, open windows. I would think I would need to use EnumWindows ; IsWindowVisible() ; GetWindowText ; GetWindowRect ; ClientToScreen ; ScreenToClient ; MoveWindow ; SetWindowPos.

Can anyone convert this to real, working VB6 code (NOT using .NET!)?
Question by:TWCMIL
LVL 17

Expert Comment

Comment Utility
When you create an AppBar, the desktop "space" is reserved so nothing can get in the way. You need to set the window position (SetWindowPos) of your AppBar window to z-order top so nothing is able to go above the window.

>> this application slowly moves upwards in increments at screen resolutions of 1024x768 or higher for some reason

I suggest you resolve that issue instead of looking for a solution such as what you asked for. If you'd still like an example of enumerating through all maximized windows, I can come up with something.

Accepted Solution

lmckenzie earned 300 total points
Comment Utility
I'm no API expert by any means either but I tried this and it seems to work on my system.  Assuming you have a list of window handles, pass each one to the MoveUnderlappedWindow function.  If the top of the window is less than the limit you set, it will be moved by the amount you specify in lngOffset.  If it's only the DB app's window that causes problems, use the FindWindow api call to get it's handle rather than enumerating all of them.  You could also use the GetWindowRect on your own appiication's window to get it's bottom position and use that instead of the top of screen offset

Option Explicit

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function IsZoomed Lib "user32" (ByVal hwnd As Long) As Long

Private Function MoveUnderlappedWindow(lngHandle as long)

Dim lngHandle As Long
Dim AppRect As RECT
Dim lngTop As Long
Dim lngHeight As Long
Dim lngLeft As Long
Dim lngWidth As Long
Dim lngResult As Long
Dim lngOffset As Long
Dim lngUpperLimit as long

lngUpperLimit = 'Whatever position you want to keep windows below
lngOffset = 10 'Choose how far below you want to move them

    If CBool(IsZoomed(lngHandle)) = vbFalse Then 'Window not maximized
        lngResult = GetWindowRect(lngHandle, AppRect) 'Get the window's position
        lngHeight = AppRect.Bottom - AppRect.Top
        lngWidth = AppRect.Right - AppRect.Left
        lngLeft = AppRect.Left
        lngTop = AppRect.Top
            If AppRect.Top < lngUpperLimit Then 'Is it underlapped?
                lngTop = lngUpperLimit + lngOffset
                lngResult = MoveWindow(lngHandle, lngLeft, lngTop, lngWidth, lngHeight, True)
            End If
    End If
End Function

Expert Comment

Comment Utility
    If the database app is so "poorly written", you would probably be better off rewriting it in VB.  If the app is encountering such severe problems, how trustworthy is the data being manipulated by it? VB is very string at communicating with databases.

    Just a thought.


Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.


Author Comment

Comment Utility
Well I've tried this:

I like the philosophy that zzzzzooc has... fix my app instead of messing with others, but from my expiriments, it's not possible to prevent every window from moving above a point on the screen. I did add the SetWindowPos() code but the problem is the application would be under the App Bar, not over it. For some reason the DB application thinks it can go under the App Bar. Quite frankly I can manually drag anything under it... it's just that this DB app strangely moves up all by itself.

I'd love to get rid of this DB application, but it's not feasible... we paid $120K+ for it, and it's a GUI front-end of our AS400, and re-training 700+ employees is just not going to happen.

I think I'll stick with the original request... lmckenzie is on track, but since my Windows API knowledge is pretty much non-existent, I just need the code to get a list of window handles so I can pass it to the function lmckenzie posted above to close & award points.
LVL 17

Assisted Solution

zzzzzooc earned 200 total points
Comment Utility
Something such as the below should work. Just put it together quickly so it might need tweaking.


Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long

Private Const GW_HWNDNEXT = 2
Private Sub Form_Load()
    Dim ColWindows As New Collection, iLoop As Integer
    Call ListWindows(ColWindows)
    For iLoop = 1 To ColWindows.Count
        Debug.Print ColWindows.Item(iLoop) 'This is the window handle
    Next iLoop
    Set ColWindows = Nothing
End Sub
Private Function ListWindows(ByRef ColWindows As Collection)
    Dim lHandle As Long
    lHandle = FindWindow(vbNullString, vbNullString)
    Do Until lHandle = 0
        ColWindows.Add lHandle
        lHandle = GetWindow(lHandle, GW_HWNDNEXT)
End Function

Author Comment

Comment Utility
The combo of the 2 worked beautifully.

Thanks for all the help... points given for code writers!

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now