|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic System Services GetWindowThreadProcessId: Obtain the hWnd of an App Started with Shell |
||
Posted: | Wednesday May 12, 1999 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows 98 | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Related: |
EnumWindows: Enumerate (and Restore) a Window via Callback SetWindowPlacement: Restore and Activate a Window via its hWnd |
|
Prerequisites |
None. |
|
Although the CreateProcess API can be used to start an
application and provide information from that app, legacy code relied on the VB Shell() statement to start foreign application execution. But
one drawback of the Shell() method is that it returns an instance handle which is itself useless should the developer wish to refer to the
shelled process at a later time.
This method demonstrates using Shell() to launch notepad, obtain its hwnd using GetWindowThreadProcessId, and then use that hwnd to change its caption and place text into its Edit window using SetWindowText and SendMessage. |
BAS Module Code |
None. |
|
Form Code |
To test, add a command button to a form along with the following: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const GW_HWNDFIRST = 0 Private Const GW_HWNDNEXT = 2 Private Const GW_CHILD = 5 Private Const WM_SETTEXT = &HC Private Declare Function GetWindow Lib "user32" _ (ByVal hwnd As Long, _ ByVal wCmd As Long) As Long Private Declare Function GetDesktopWindow Lib "user32" () As Long Private Declare Function GetWindowThreadProcessId Lib "user32" _ (ByVal hwnd As Long, _ lpdwProcessId As Long) As Long Private Declare Function BringWindowToTop Lib "user32" _ (ByVal hwnd As Long) As Long Private Declare Function SetWindowText Lib "user32" _ Alias "SetWindowTextA" _ (ByVal hwnd As Long, ByVal _ lpString As String) As Long Private Declare Function GetClassName Lib "user32" _ Alias "GetClassNameA" _ (ByVal hwnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Private Sub Command1_Click() Dim hWndApp As Long 'call the wrapper function to start shell, 'and return the handle to the shelled app. hWndApp = StartShell("notepad.exe") 'if found, prove it! If hWndApp Then 'change its caption Call SetWindowText(hWndApp, "The handle to Notepad is " & CStr(hWndApp)) 'bring it to the top Call BringWindowToTop(hWndApp) 'and add some text to its edit window Call PutTextIntoNotepad(hWndApp) End If End Sub Private Function GethWndFromProcessID(hProcessIDToFind As Long) As Long Dim hWndDesktop As Long Dim hWndChild As Long Dim hWndChildProcessID As Long On Local Error GoTo GethWndFromProcessID_Error 'get the handle to the desktop hWndDesktop = GetDesktopWindow() 'get the first child under the desktop hWndChild = GetWindow(hWndDesktop, GW_CHILD) 'hwndchild will = 0 when no more child windows are found Do While hWndChild <> 0 'get the ThreadProcessID of the window Call GetWindowThreadProcessId(hWndChild, hWndChildProcessID) 'if it matches the target, exit returning that value If hWndChildProcessID = hProcessIDToFind Then GethWndFromProcessID = hWndChild Exit Do End If 'not found, so get the next hwnd hWndChild = GetWindow(hWndChild, GW_HWNDNEXT) Loop Exit Function GethWndFromProcessID_Error: GethWndFromProcessID = 0 Exit Function End Function Private Function StartShell(sApplication As String) As Long Dim hProcessID As Long 'start using shell, and get the process ID hProcessID = Shell(sApplication, vbNormalFocus) 'return the hwnd to the shelled process StartShell = GethWndFromProcessID(hProcessID) End Function Private Sub PutTextIntoNotepad(hWndApp As Long) 'This adds text to notepad, by locating its ''Edit' class window. This is similar to the 'method used to locate the hwnd itself, but 'here we know the parent (hWndApp) so only 'have to search its child windows. Dim hWndChild As Long Dim sMsg As String Dim sBuffer As String * 32 Dim nSize As Long 'this string is split only to fit the browser window sMsg = "This method demonstrates using Shell() " sMsg = sMsg & "to launch notepad, obtain its hwnd using " sMsg = sMsg & "GetWindowThreadProcessId, and then use that" sMsg = sMsg & "hwnd to change its caption and place text into " sMsg = sMsg & "its Edit window using SetWindowText and SendMessage." 'get the first child window in Notepad hWndChild = GetWindow(hWndApp, GW_CHILD) 'hwndchild will = 0 when no more child windows are found Do While hWndChild <> 0 'get the Class Name of the window nSize = GetClassName(hWndChild, sBuffer, 32) 'if nSize > 0, it contains the length 'of the class name retrieved If nSize Then 'if the class name is "Edit", 'set some text and exit If Left$(sBuffer, nSize) = "Edit" Then Call SendMessage(hWndChild, WM_SETTEXT, 0&, ByVal sMsg) Exit Sub End If End If 'not found, so get the next hwnd hWndChild = GetWindow(hWndChild, GW_HWNDNEXT) Loop End Sub |
Comments |
Save the project and run. The comments are self explanatory. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |