Microsoft KB Archive/113702

= How to Control the Placement of Desktop Windows =

Article ID: 113702

Article Last Modified on 10/20/2003

-

APPLIES TO


 * Microsoft Visual Basic 3.0 Professional Edition

-



This article was previously published under Q113702



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:

78001 : 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.</li> 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.</li></ol>

Additional query words: 3.00

Keywords: KB113702

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.