We help IT Professionals succeed at work.

Move Window Of Another Program?

mms_master
mms_master asked
on
Medium Priority
771 Views
Last Modified: 2012-06-27
Hi,

I want to move a window of another program to the top left of the screen.
At the moment I'm using FindWindow api to try to get the window hWnd.
After that I tried using MoveWindow api to move the window but it didn't do anything...

My code is:

Public Class Form1
    Private Declare Auto Function FindWindow Lib "user32" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As IntPtr

    Private Declare Function MoveWindow Lib "user32" Alias "MoveWindow" ( _
    ByVal hwnd As Integer, _
    ByVal x As Integer, _
    ByVal y As Integer, _
    ByVal nWidth As Integer, _
    ByVal nHeight As Integer, _
    ByVal bRepaint As Integer) As Integer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim D2Handle As IntPtr = FindWindow(vbNullString, "Window Title")
        MoveWindow(D2Handle, 0, 0, 800, 600, 0)

    End Sub
End Class

Can anyone help please?
Thanks In Advance
mms_master
Comment
Watch Question

I'm sorry to disappoint you, but your code seems right.
But are you sure you got your window title right?

Author

Commented:
The window title is correct.
Does IntPtr have to be converted to another format or something?
I thought maybe a hWnd is different to an IntPtr.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
IntPtr and Integer are interchangeable in this case.

As PockyMaster said, this should work.

Try it with Calculator...

Public Class Form1

    Private Declare Auto Function FindWindow Lib "user32" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As IntPtr

    Private Declare Function MoveWindow Lib "user32" Alias "MoveWindow" ( _
        ByVal hWnd As IntPtr, ByVal x As Integer, ByVal y As Integer, _
        ByVal nWidth As Integer, ByVal nHeight As Integer, _
        ByVal bRepaint As Integer) As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If Process.GetProcessesByName("calc").Length = 0 Then
            Dim p As Process = Process.Start("calc")
            p.WaitForInputIdle()
        End If

        Dim calcWnd As IntPtr = FindWindow(vbNullString, "Calculator")
        MoveWindow(calcWnd, 0, 0, 800, 600, 1)
    End Sub

End Class

Author

Commented:
I actually just tested it with internet explorer before I saw your post.
It worked with internet explorer...
But I know that the title of the window is correct.
To check that it was finding the window I used this code after calling the FindWindow api:

        If D2Handle.Equals(IntPtr.Zero) Then
            MsgBox("Zero")
            Exit Sub
        Else
            MsgBox(D2Handle)
        End If

The msgbox returned: 26411218
So I know that it is finding the window. But for some reason it is not moving the window. The window I am trying to move is a game playing in a window instead of full screen. I don't know if this makes any difference.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
It is always possible that the game is preventing its window from being moved or that it is constantly resetting its position.  Can you move this window normally with the mouse?

Author

Commented:
I can move it normaly with the mouse.
Also I have another program that moves the window, so I know that it is possible.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
I set the "Repaint" option to True in my example:

    MoveWindow(calcWnd, 0, 0, 800, 600, 1)

The "1" forces a repaint of the window.  Is it possible that the window is moving but not repainting so you can't see its new position?

Try it with the last parameter set to 1.

Author

Commented:
Just a thought, is it possible that because the window is not resisable it is stopping the MoveWindow api because it tries to resize it to 800x600?

Author

Commented:
Setting repaint to true didn't work.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
That is possible (though I haven't tested it).

Do you want it to be 800x600?  Or did you just stick those arbitrary numbers in there for testing?

If you want to preserve the current size of the window, then use the GetWindowRect() API to determine its size.

Author

Commented:
I chose 800x600 because the video options on the game are set to 800x600.
So i assumed that that would be the size of the window...
Theres a chance that the window could be slightly bigger because maybe the area inside the window is 800x600 and not the actual window itself.

Ill try the GetWindowRect api now.

Author

Commented:
I used the following api:

Private Declare Function GetWindowRect Lib "user32" Alias "GetWindowRect" (ByVal hwnd As Integer, ByVal lpRect As RECT) As Integer

and got an error saying that RECT isn't defined.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
It should be:

    Public Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure

    Private Declare Function GetWindowRect Lib "user32" Alias "GetWindowRect" _
        (ByVal hWnd As Integer, ByRef lpRect As RECT) As Integer

*** Notice the RECT is passed ByRef.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
Then of course you have to compute the width:

    Dim myWidth As Integer = someRect.Right - someRect.Left + 1

...similar for the height...

Author

Commented:
I now have the following code:

        Dim D2Handle As IntPtr = FindWindow(vbNullString, "Diablo II")
        If D2Handle.Equals(IntPtr.Zero) Then
            MsgBox("Couldn't Find Instance...")
            Exit Sub
        End If

        GetWindowRect(D2Handle, varRect)
        varMoveWindow = MoveWindow(D2Handle, 10, 10, varRect.Right - varRect.Left + 1, varRect.Bottom - varRect.Top + 1, 1)
        If varMoveWindow.Equals(IntPtr.Zero) Then
            MsgBox("Move Failed!")
        End If

It still doesn't work and I don't get either of the message boxes.

Author

Commented:
Using the GetWindowRect api and the following code:

MsgBox(varRect.Right - varRect.Left + 1 & "x" & varRect.Bottom - varRect.Top + 1, 1)

the size of the window is shown as 161x32. But my screen resolution is 1024x768 and the window covers most of the screen... so I can't see how the size shown above is right.
This doesn't realy bother me though, i just want to get the window to move to top left of the screen.
Just a crazy thought, but try to move it to -100, -100. Are you sure the window you are selecting is not inside another window?

Author

Commented:
I just tried to move it to -100, -100 and still nothing happend :(
Did you try spy++ to catch the window?

Try to use the GetWindowRect API to check the current location your window thinks he's on.

Author

Commented:
It says that its current position is: (its roughly in the centre of my screen)

Top=-32000
Bottom=-31969
Left=-32000
Right=-31840
and now try to do that for your internet explorer, and see what it says for that

Author

Commented:
hmm big difference:
Top=86
Bottom=686
Left=108
Right=908
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
Use Spy++ to compare the handle of the window you see with the hande of the window being returned by FindWindow().

Are they the same?  (guessing not)

Author

Commented:
Whats spy++? lol
Spy++ is a tool that you get with visual studio
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
Spy++ is a tool that comes with Visual Studio that allows you to "spy" into windows on your system.  It gives you information as the handle, size, location, class name, and the attributes that determine how it looks.  It also gives a treeview giving a hierachical view of the windows with relation to each other.  Additionally you can "watch" a window to see all the windows messages being processed in its pump.

Many developers also use WinSpector:
http://www.windows-spy.com/

Author

Commented:
Not sure if i've got it.
Im using vb.net 2005 express. It's a free version that you can download from microsofts website. But i dont think they include all the tools that you get with the proffesional version.
Is it on the start bar? or on one of the menus in vb?
It should be in the tools menu, but I'm not sure if they give it for free
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
I don't think Spy++ comes with the Express versions.

Try Winspector from my link above.

Author

Commented:
no its not there.
Ill get WinSpector now.
For testing you might also try like this:
Find your PID in your taskmanager

Dim proc As Process
        proc = Process.GetProcessById(myPID)
        proc.MainWindowHandle  <-- your handle

Author

Commented:
is the handle the bit where it says:

Properties for window 0x001708FE

Author

Commented:
I used the following code:

        Dim D2Handle As IntPtr = FindWindow(vbNullString, "Diablo II")
        If D2Handle.Equals(IntPtr.Zero) Then
            MsgBox("Couldn't Find Instance...")
            Exit Sub
        End If

        GetWindowRect(D2Handle, varRect)
        MsgBox(D2Handle)
        'Dim temptxt As String = "Top=" & varRect.top & " Bottom=" & varRect.bottom & " Left=" & varRect.left & " Right=" & varRect.right
        'text1.text = temptxt
        Dim proc As Process
        proc = Process.GetProcessById("1932")
        MsgBox(proc.MainWindowHandle)

and got the same handle from both message boxes.
Well, I've never tried it with games, but your last test proofs to me you got the right window... It might be the game is behaving different than we expect. Or this question is out of my league.. I will sleep on the answer for now :D
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
Correct.  That is the windows handle in WinSpector.

To display your IntPtr in hex you can do this:

    MsgBox(D2Handle.ToInt32.ToString("x"))

Author

Commented:
I've increased the points for this question from 50 to 100.

Author

Commented:
I've been given some code that is supposed to work in C++
I'm in the middle of re-writing it in VB.NET but I need to know the integer value for SWP_NORESIZE. I can't find it anywhere on the internet.
I've FINALY got it to work :D
Just encase it was bugging anyone here's how I done it:

    Private Declare Auto Function FindWindow Lib "user32" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As IntPtr

    Private Declare Function ShowWindow Lib "user32" Alias "ShowWindow" _
    (ByVal hwnd As Integer, ByVal nCmdShow As Integer) As Integer

    Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" _
    (ByVal hwnd As Integer, _
    ByVal hWndInsertAfter As Integer, _
    ByVal x As Integer, _
    ByVal y As Integer, _
    ByVal cx As Integer, _
    ByVal cy As Integer, _
    ByVal wFlags As Integer) As Integer


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim D2Handle As IntPtr = FindWindow("Diablo II", vbNullString)

        If D2Handle.Equals(IntPtr.Zero) Then
            MsgBox("Couldn't Find Instance...")
            Exit Sub
        End If

        ShowWindow(D2Handle, 9) '9 = restore (equivalent of vb6's SW_RESTORE)

        If SetWindowPos(D2Handle, 0, 0, 0, 0, 0, 1) Then 'The 1 = vb6's SWP_NORESIZE
            ':D
        Else
            MsgBox("Failed to move window.")
        End If

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.