How to control placement of app on startup

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I want to start an app, and at the same time control where it is placed. I
use the following code, but it doesn't seem to work. The MoveWindow call
doesn't move the window. What am I doing wrong? Isn't the shell function
supposed to return the handle to the window? Or is this just a process id
and
am I then supposed to make another call to translate this into a window
handle? Or what else is wrong?

Public Class Form1
Inherits System.Windows.Forms.Form
Declare Sub MoveWindow Lib "User32" (ByVal hWnd As Long, _
ByVal X As Long, ByVal Y As Long, ByVal Width
As Long, _
ByVal Height As Long, ByVal bRepaint As
Boolean)
....
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim cProgram As String = "Notepad.exe"
Dim nHandle As Integer = Shell(cProgram)
MoveWindow(nHandle, 10, 10, 500, 300, True)
End Sub
End Class

Another question: Are there any calls inside the .net framework to support
this?

Any help appreciated


Peter
 
I want to start an app, and at the same time control where it is placed. I
use the following code, but it doesn't seem to work. The MoveWindow call
doesn't move the window. What am I doing wrong? Isn't the shell function
supposed to return the handle to the window? Or is this just a process id
and

Well, the docs say it's the process ID. So, presumably you can use the
System.Diagnostics.Process class to get the window handle...

Hmmm... Time to experiment:

Option Strict On
Option Explicit On

Imports System
Imports System.Diagnostics

Module Module1

Declare Function MoveWindow Lib "user32" _
(ByVal hWnd As IntPtr, _
ByVal X As Integer, _
ByVal Y As Integer, _
ByVal nWidth As Integer, _
ByVal nHeight As Integer, _
ByVal bRepaint As Boolean) As Boolean

Sub Main()
Dim procId As Integer = Shell("notepad.exe",
AppWinStyle.NormalFocus)
Dim proc As Process = Process.GetProcessById(procId)

proc.WaitForInputIdle() ' give the window a chance to
initialize

' move it where we want it...
MoveWindow(proc.MainWindowHandle, 10, 10, 500, 300, True)
End Sub

End Module

This seems to work. Obviously, you might want to do a little more error
handling :) Just a note, this also seems to work without the
WaitForInputIdle call - but I put it in just to make sure the main
window is fully initialized and ready to accept messages anyway.
am I then supposed to make another call to translate this into a window
handle? Or what else is wrong?

Public Class Form1
Inherits System.Windows.Forms.Form
Declare Sub MoveWindow Lib "User32" (ByVal hWnd As Long, _
ByVal X As Long, ByVal Y As Long, ByVal Width
As Long, _
ByVal Height As Long, ByVal bRepaint As
Boolean)

Your declare is wrong... Datatype sizes have changed in VB.NET. Long
is a 64-bit integer. It should be Integer, as that is now 32-bit.
Also, handles should be declared as System.IntPtr...

Declare Function MoveWindow Lib "user32" _
(ByVal hWnd As IntPtr, _
ByVal X As Integer, _
ByVal Y As Integer, _
ByVal nWidth As Integer, _
ByVal nHeight As Integer, _
ByVal bRepaint As Boolean) As Boolean
...
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim cProgram As String = "Notepad.exe"
Dim nHandle As Integer = Shell(cProgram)
MoveWindow(nHandle, 10, 10, 500, 300, True)
End Sub
End Class

Another question: Are there any calls inside the .net framework to support
this?

No, not really. You'll need to do interop for this.
 
Thanks Tom, that works like a charm,

now I have to go the other way too. When the user has positioned the app
that I just started, I have to log the new position, to be able to start it
at the new position the next time. I have fiddled around a bit with
GetWindowRect, but I can't get it to work.

I have tried the following code:

Structure RECT
Public left As Long
Public top As Long
Public right As Long
Public bottom As Long
End Structure

Declare Function GetWindowRect Lib "user32.dll" _
(ByVal hWnd As IntPtr, _
ByVal lPRect As RECT) As Long

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim proc As Process = Process.GetProcessById(Me._procid)
Dim objRect As New RECT()
If GetWindowRect(proc.MainWindowHandle, objRect) <> 0 Then
MsgBox(objRect.top & " " & objRect.left)
End If
End Sub

But I get "Object reference not set to an instance of an object." on the
GetWIndowRect Call.
proc.MainWIndowHandle returns a valid handle, and objRect seems to be a
valid rect structure.
If I replace the RECT with the .net Rectangle object I get the same error.

What's wrong?

Peter
 
Just figured that one out myself. Forgot to declare the Rectangle "ByRef"

Peter

Peter...

I'm glad you got it working. But, you still have some issues :)
Remeber datatype sizes have changed in VB.NET. So, all the longs in
your declarations, really should be declared as Integer or Int32.
 
Thank you Tom. Actually, I did know that, but forgot to change it. This is
just a test case built on cut-and-paste sample code from msdn kb. I will
remember that when I make the actual implementation.

Thanks for your help

Peter
 
Back
Top