Forcing app to foreground through winapi

Hello,

I’m trying to force an app into the foreground through the winapi. It needs to be in the postopen event of a form but I’m just trying to get it working from a button (experimenting w/firefox) right now.

Here is the code that I’ve tried to gather and patch together from a few place - I’m quite lost when it comes to the winapi:

Declarations:

Declare Function GetWindowThreadProcessId Lib “user32” (Byval hWnd As Long, lpdwProcessId As Long) As Long

Declare Function AttachThreadInput Lib “user32” (Byval idAttach As Long, Byval idAttachTo As Long, Byval fAttach As Long) As Long

Declare Function GetForegroundWindow Lib “user32”() As Long

Declare Function SetForegroundWindow Lib “user32”(Byval hWnd As Long) As Long

Declare Function IsIconic Lib “user32” (Byval hWnd As Long) As Long

Declare Function ShowWindow Lib “user32” (Byval hWnd As Long, Byval nCmdShow As Long) As Long

Declare Function GetExitCodeProcess Lib “kernel32” (Byval hProcess As Long, lpExitCode As Long) As Long

Declare Function OpenProcess Lib “kernel32” (Byval dwDesiredAccess As Long, Byval bInheritHandle As Long, Byval dwProcessId As Long) As Long

Declare Function CloseHandle Lib “kernel32” ( Byval hObject As Long) As Long

Declare Function EnumProcesses Lib “PSAPI” ( lpidProcess As Any, cb As Long, cbNeeded As Long) As Boolean

Declare Function EnumProcessModules Lib “PSAPI” ( Byval hProcess As Long, lphModule As Any, cb As Long, lpcbNeeded As Long) As Boolean

Declare Function GetModuleBaseName Lib “PSAPI” Alias “GetModuleBaseNameA” (Byval hProcess As Long, Byval hModule As Long, Byval lpBasename As String, nSize As Long) As Boolean

Declare Function CreateToolhelpSnapshot Lib “kernel32” Alias “CreateToolhelp32Snapshot” (Byval lFlags As Long, lProcessID As Long) As Long

Declare Function BringWindowToTop Lib “user32” (Byval hwnd As Long) As Long

Declare Function GetDesktopWindow Lib “user32” () As Long

Declare Function GetWindow Lib “user32” (Byval hwnd As Long, Byval wCmd As Long) As Long

Private Type MODULEINFO

lpBaseOfDll As Long

SizeOfImage As Long

EntryPoint As Long

End Type

Const SW_RESTORE = 9

Const SW_SHOW = 5

Private Const MAX_PATH = 260&

Private Const PROCESS_ALL_ACCESS = &H1F0FFF

Private Const PROCESS_CREATE_PROCESS = &H80&

Private Const PROCESS_CREATE_THREAD = &H2&

Private Const PROCESS_DUP_HANDLE = &H40&

Private Const PROCESS_HEAP_ENTRY_BUSY = &H4&

Private Const PROCESS_HEAP_ENTRY_DDESHARE = &H20&

Private Const PROCESS_HEAP_ENTRY_MOVEABLE = &H10&

Private Const PROCESS_HEAP_REGION = &H1&

Private Const PROCESS_HEAP_UNCOMMITTED_RANGE = &H2&

Private Const PROCESS_QUERY_INFORMATION = &H400&

Private Const PROCESS_SET_INFORMATION = &H200&

Private Const PROCESS_SET_QUOTA = &H100&

Private Const PROCESS_TERMINATE = &H1&

Private Const PROCESS_VM_OPERATION = &H8&

Private Const PROCESS_VM_READ = &H10&

Private Const PROCESS_VM_WRITE = &H20&

Dim lngHandFirefox As Long

Sub Click(Source As Button)

Dim hWnd As Long

Call GetProcessList()

If lngHandFirefox<>0 Then

	Call ForceForegroundWindow(hWnd)

End If

End Sub

Function ForceForegroundWindow(Byval hWnd As Long) As Boolean

Dim ThreadID1 As Long

Dim ThreadID2 As Long

Dim nRet As Long



If hWnd = GetForegroundWindow() Then

	ForceForegroundWindow  = True

Else

	ThreadID1 = GetWindowThreadProcessId(GetForegroundWindow, Byval 0&)

	ThreadID2 = GetWindowThreadProcessId(hWnd, Byval 0&)

	

	If ThreadID1<> ThreadID2 Then

		Call AttachThreadInput(ThreadID1, ThreadID2, True)

		nRet = SetForegroundWindow(hWnd)

		Call AttachThreadInput(ThreadID1, ThreadID2, False)

	Else

		nRet = SetForegroundWindow(hWnd)

	End If

	

	If IsIconic(hWnd) Then

		Call ShowWindow(hWnd, SW_RESTORE)

	Else

		Call ShowWindow(hWnd, SW_SHOW)

	End If

	ForceForegroundWindow = Cbool(nRet)

End If

End Function

Function GetProcessList() As String

Dim pbolRtn As Boolean

Dim plngRtn As Long

Dim plngNeeded As Long

Dim plngNumItems As Long

Dim plngNumItemsMods As Long

Dim plngLoop As Long

Dim plngNumCols As Long

Dim plngNumRows As Long

Dim plngProcessHwnd As Long

Dim plngPos As Long

Dim plngLenFileName As Long

Dim palngModHwnds() As Long

Dim palngProcesses() As Long

Dim pstrProcessName As String

Dim ptypModuleInfo As MODULEINFO



Dim sProcessList As String



sProcessList = ""



plngNumItems = 1024

Redim palngProcesses(0 To plngNumItems)

pbolRtn = EnumProcesses(palngProcesses(0), (1024 * 4), plngNeeded)



If pbolRtn = 0 Then

	Exit Function

End If



plngNumItems = plngNeeded / 4

Dim xx As Integer

xx = 0

For plngLoop = 0 To plngNumItems - 1

	If palngProcesses(plngLoop) <> 0 Then

		pstrProcessName = ""

		plngProcessHwnd = OpenProcess( _

		PROCESS_QUERY_INFORMATION& Or PROCESS_VM_READ&, 0&, _

		palngProcesses(plngLoop))

		plngNumItemsMods = 1024

		Redim palngModHwnds(0 To plngNumItemsMods)

		pbolRtn = EnumProcessModules(plngProcessHwnd, _

		palngModHwnds(0), (1024 * 4), plngNeeded)

		If pbolRtn <> 0 Then

			plngLenFileName = MAX_PATH

			pstrProcessName = Space$(plngLenFileName)

			pbolRtn = GetModuleBaseName(plngProcessHwnd, _

			palngModHwnds(0), pstrProcessName, plngLenFileName)

			plngPos = Instr(pstrProcessName, Chr$(0))

			If plngPos > 0 Then

				pstrProcessName = Mid$(pstrProcessName, 1, _

				plngPos - 1)

			End If

			If sProcessList <> "" Then sProcessList = _

			sProcessList & Chr(0)

			sProcessList = sProcessList & pstrProcessName

			If Instr(Lcase(pstrProcessName), "firefox") Then

						'tried

'				lngHandFirefox = plngProcessHwnd

'				lngHandFirefox = palngModHwnds(plngPos) 'plngProcessHwnd

				lngHandFirefox = plngLenFileName

			End If

			

		End If

	End If

	plngRtn = CloseHandle(plngProcessHwnd)

Next plngLoop



Erase palngProcesses



GetProcessList = sProcessList

End Function

Subject: Forcing app to foreground through winapi

In case someone wants the answer - this is what worked for me:

In caller Page, Form, Button, etc.

'Options

Use MoveAppToForeground

'under event, button:

Call Controller

Script Library

'MoveAppToForeground:

'Options

Option Public

Option Declare

Use “slWindowListExaminer”

'Declarations

Declare Function ShowWindow Lib “user32” (Byval hWnd As Long, Byval nCmdShow As Long) As Long

Const SW_RESTORE = 9

Const SW_MINIMIZE = 6

Sub Controller

Dim wle As New WindowListExaminer

Dim hWnd As Long

Const TASKNAME$ = "BOSaNOVA"



hWnd= wle.GetHandleOnTask(TASKNAME$, False)

Call ShowWindow(hWnd, SW_MINIMIZE)

Call ShowWindow(hWnd, SW_RESTORE)

End Sub

'slWindowListExaminer:

'Options

Option Public

Option Declare

'Declarations

Declare Function GetWindowText Lib “user32” Alias “GetWindowTextA” (Byval hwnd As Long, Byval lpString As String, Byval cch As Long) As Long

Declare Function GetWindowTextLength Lib “user32” Alias “GetWindowTextLengthA” (Byval hwnd As Long) As Long

Declare Function GetWindow Lib “user32” (Byval hwnd As Long,Byval wCmd As Long) As Long

Declare Function GetActiveWindow Lib “user32” () As Long

Declare Function IsWindowVisible Lib “user32” (Byval hwnd As Long) As Boolean

Class WindowListExaminer

'/**

'* This Windows-only class function can report whether a task exists in list of windows (as visible in Task Manager)

'* This function will not be appropriate for tasks running in Hidden windows.

'*

'* @author Martin Audley

'*/

Sub New

'/**

'* Error and return Null object if not MS Windows NT/XP etc

'*/

	Const PLATFORM_WINDOWS32$ = "Windows/32"

	Dim sess As New notessession

	If sess.Platform <> PLATFORM_WINDOWS32$ Then

		Error 1,"Unsupported operating system. This class is intended for use on " & PLATFORM_WINDOWS32$ & " platform only"

	End If

End Sub



Public Function GetHandleOnTask(Byval strCheckTask As String, Byval bExactMatch As Boolean) As Long

	Const GW_HWNDNEXT& = 2 ' 2 = next window handle

’ ****** Declare Variables ************

	Dim lgCurrWnd As Long

	Dim lgLength As Long

	Dim strTaskName As String

Compare given string against all window titles. Return true if found****

	lgCurrWnd& = GetActiveWindow()

	Do While (lgCurrWnd& <> 0)

		lgLength = GetWindowTextLength(lgCurrWnd&)

		strTaskName = Space$(lgLength& + 1)

		lgLength = GetWindowText(lgCurrWnd&, strTaskName$, lgLength& + 1)

		strTaskName = Left$(strTaskName$, Len(strTaskName$) - 1)

		If (lgLength& > 0) Then

			If bExactMatch = True Then ' Task name matches string exactly.

				If (strTaskName$ = strCheckTask$) Then

						GetHandleOnTask = lgCurrWnd



					Exit Do

				End If

			Else

				If Instr(Lcase(strTaskName$), Lcase(strCheckTask$)) Then



						GetHandleOnTask = lgCurrWnd

					Exit Do

				End If

			End If

		End If

		lgCurrWnd& = GetWindow(lgCurrWnd&, GW_HWNDNEXT&)

		Doevents

	Loop

	

End Function

End Class