How to Control the Placement of Desktop Windows
ID: Q113702
|
The information in this article applies to:
-
Microsoft Visual Basic Professional Edition for Windows, version 3.0
SUMMARY
There are situations where you'd like your program to have control over
windows that do not belong to the program itself. For example, when a
Visual Basic program performs OLE automation with Microsoft Word for
Windows, you might want to place the Word window next to the current
position of the program's window -- so that the two windows are tiled side
by side.
This article demonstrates how to use the Windows API SetWindowPlacement
function in a tiling algorithm.
MORE INFORMATION
The example code in this article obtains the handles of three standard
applications (CALC.EXE, WRITE.EXE, and NOTEPAD.EXE) by using the FindWindow
function. Then it tiles the application windows horizontally or vertically,
along with the Visual Basic program's form. The handles are obtained after
using the Visual Basic Shell function to launch the applications.
After obtaining the handles, the example code calls the Windows API
SetWindowPlacement function to size and position the top-level window. For
illustration, an algorithm that tiles the windows either horizontally or
vertically is called using an array of window handles.
Possible Enhancement
You could enhance the example in this article by applying a technique
described in another Microsoft Knowledge Base article to obtain the handles
of already running applications. For information about this technique
please see the following article in the Microsoft Knowledge Base:
Q78001
: How to Get Windows Master List (Task List) Using Visual Basic
Step-by-Step Example
Here are the steps necessary to construct the example:
- Start a new project in Visual Basic. Form1 is created by default.
- Add a command button (Command1) to the form, and change its Caption
property to Tile.
- Add a code module (Module1) to the project by choosing New Module
from the File menu (ALT, F, M).
- Add the following code to the general declarations section of Module1:
Type POINTAPI
x As Integer
y As Integer
End Type
Type RECT
left As Integer
top As Integer
right As Integer
bottom As Integer
End Type
Type WINDOWPLACEMENT
length As Integer
flags As Integer
showCmd As Integer
ptMinPosition As POINTAPI
ptMaxPosition As POINTAPI
rcNormalPosition As RECT
End Type
Global lpwndplOld As WINDOWPLACEMENT
Global lpwndplNew As WINDOWPLACEMENT
' Enter each of the following Declare statements as one, single line:
Declare Function FindWindow Lib "User" (ByVal lpClassName As Any,
ByVal lpWindowName As Any) As Integer
Declare Function GetWindowPlacement Lib "User" (ByVal hwnd As
Integer, lpwndpl As WINDOWPLACEMENT) As Integer
Declare Function SetWindowPlacement Lib "User" (ByVal hwnd As
Integer, lpwndpl As WINDOWPLACEMENT) As Integer
Global Const SW_SHOWNORMAL = 1
Global hWnds() As Integer
- Add the following code to Module1:
' Enter the following Function statement as one, single line:
Function Tile (hWndArr() As Integer, cardinal As Integer,
HorV As Integer)
Dim ordinal As Integer
On Error GoTo handler
Select Case HorV
Case 1
For ordinal = 1 To cardinal
' Optionally, check old placement of window:
' ****************************************************
' Note that the debug statements induce a slight delay
' Enter each Debug.Print statement as one, single line:
'
' lpwndplOld.length = Len(lpwndplOld)
' ret% = GetWindowPlacement(hWndArr(ordinal), lpwndplOld)
' Debug.Print
' Debug.Print "ordinal= "; ordinal
' Enter the following two lines as one, single line:
' Debug.Print " Old window placement values for handle = ";
' Hex$(hWndArr(ordinal))
' Debug.Print "lpwndplOld.length= "; lpwndplOld.length
' Debug.Print "lpwndplOld.flags= "; lpwndplOld.flags
' Debug.Print "lpwndplOld.showCmd= "; lpwndplOld.showCmd
'
' Debug.Print "lpwndplOld.ptMinPosition.x= ";
' lpwndplOld.ptMinPosition.x
' Debug.Print "lpwndplOld.ptMinPosition.y= ";
' lpwndplOld.ptMinPosition.y
'
' Debug.Print "lpwndplOld.ptMaxPosition.x= ";
' lpwndplOld.ptMaxPosition.x
' Debug.Print "lpwndplOld.ptMaxPosition.y= ";
' lpwndplOld.ptMaxPosition.y
'
' Debug.Print "lpwndplOld.rcNormalPosition.left= ";
' lpwndplOld.rcNormalPosition.left
' Debug.Print "lpwndplOld.rcNormalPosition.top= ";
' lpwndplOld.rcNormalPosition.top
' Debug.Print "lpwndplOld.rcNormalPosition.right= ";
' lpwndplOld.rcNormalPosition.right
' Debug.Print "lpwndplOld.rcNormalPosition.bottom= ";
' lpwndplOld.rcNormalPosition.bottom
'**************************************************************
lpwndplNew.length = Len(lpwndplNew)
lpwndplNew.flags = 0
lpwndplNew.showCmd = SW_SHOWNORMAL
l = 0
' Enter the following two lines as one, single line:
t = (ordinal - 1) *
(screen.Height / screen.TwipsPerPixelY) \ cardinal
r = (screen.Width / screen.TwipsPerPixelX)
b = ordinal * (screen.Height / screen.TwipsPerPixelY) \ cardinal
lpwndplNew.rcNormalPosition.left = l
lpwndplNew.rcNormalPosition.top = t
lpwndplNew.rcNormalPosition.right = r
lpwndplNew.rcNormalPosition.bottom = b
ret% = SetWindowPlacement(hWndArr(ordinal), lpwndplNew)
Next ordinal
Case 2
For ordinal = 1 To cardinal
lpwndplNew.length = Len(lpwndplNew)
lpwndplNew.flags = 0
lpwndplNew.showCmd = SW_SHOWNORMAL
' Enter the following two lines as one, single line:
l = (ordinal - 1) *
(screen.Width / screen.TwipsPerPixelX) \ cardinal
t = 0
r = ordinal * (screen.Width / screen.TwipsPerPixelX) \ cardinal
b = (screen.Height / screen.TwipsPerPixelY)
lpwndplNew.rcNormalPosition.left = l
lpwndplNew.rcNormalPosition.top = t
lpwndplNew.rcNormalPosition.right = r
lpwndplNew.rcNormalPosition.bottom = b
ret% = SetWindowPlacement(hWndArr(ordinal), lpwndplNew)
Next ordinal
End Select
Tile = True
Exit Function
handler:
MsgBox Error$
Tile = False
Exit Function
End Function
- Add the following code to Command1_Click event procedure:
Sub Command1_Click ()
Dim orientation As Integer, handlecount As Integer, i As Integer
ret% = Shell("notepad", 7)
If FindWindow("NOTEPAD", 0&) Then
handlecount = handlecount + 1
ReDim Preserve hWnds(1 To handlecount)
hWnds(handlecount) = FindWindow("NOTEPAD", 0&)
End If
ret% = Shell("write", 7)
If FindWindow("MSWRITE_MENU", 0&) Then
handlecount = handlecount + 1
ReDim Preserve hWnds(1 To handlecount)
hWnds(handlecount) = FindWindow("MSWRITE_MENU", 0&)
End If
handlecount = handlecount + 1
ReDim Preserve hWnds(1 To handlecount)
hWnds(handlecount) = Me.hWnd ' the handle of Form1
ret% = Shell("calc", 7)
If FindWindow("SCICALC", 0&) Then
handlecount = handlecount + 1
ReDim Preserve hWnds(1 To handlecount)
hWnds(handlecount) = FindWindow("SCICALC", 0&)
End If
'orientation = 1 ' horizontal
orientation = 2 ' vertical
ret% = Tile(hWnds(), handlecount, orientation)
End Sub
- Save the project and run the program by pressing the F5 key.
- Click the Tile button, and observe the vertical tiling of the windows.
Then stop the program, and close the three applications (CALC.EXE,
WRITE.EXE, and NOTEPAD.EXE). Remove the single quotation mark from
"orientation = 1" line. Then add a single quotation mark to the
"orientation = 2" line. Run the program again, and observe the
horizontal tiling.
Additional query words:
3.00
Keywords :
Version :
Platform :
Issue type :
|