Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:43 pm
by brendan1 >> Wed, 11 Jun 2003 20:20:19 GMT
Stephen,
This is a well-known problem for Windows 2000, 98 etc. and particularly for COM object writers since they always want to force the window of another app to the foreground. There are many long laments and moans on various newsgroups on the web.
Unfortunately setForegroundWindow does not work on W2K. However, there are nasty ways round this which I have found on various newgroups and tested in JADE. The following code works on W2K and Windows NT. You may be able to remove the restriction on process.getOSPlatform(versionOS, archOS) = Node.OSWindowsEnterprise and extend it to Windows 98 and XP. I didn't have 98 or XP to test it on. Please let me know how it gpoes if you can.
External function calls (all on user32) required are
attachThreadInput(idAttach : Integer; idAttachTo : Integer; fAttach : Integer): Integer is AttachThreadInput in user32;
// if fAttach is TRUE, attaches thread idAttach to thread idAttachTo
// if fAttach is FALSE, detaches thread idAttach from thread idAttachTo
bringWindowToTop(hwnd : Integer): Integer is BringWindowToTop in user32; // Attempts to put window hwnd to top of window list
getForegroundWindow(): Integer is GetForegroundWindow in user32;
// Returns a handle to the current foreground window
getWindowThreadProcessId(hWnd, lpdwProcessId : Integer): Integer is GetWindowThreadProcessId in user32;
// returns thread corresponding to window with handle hWnd. Set lpdwProcessId = 0
setForegroundWindow(hwnd : Integer): Integer is SetForegroundWindow in user32;
// Attempts to set the foregrond window to hwnd
getSystemParametersInfo(uAction:Integer;uParam:Integer;lpvParam:Integer io;fuWinIni:Integer):Integer is SystemParametersInfoA in user32;
// Has many different functions, mainly to do with getting values in registry normally viewed via ControlPanel
setSystemParametersInfo(uAction:Integer;uParam:Integer;lpvParam:Integer;fuWi nIni:Integer):Integer is SystemParametersInfoA in user32;
// Has many different functions, mainly to do with setting values in registry normally set via ControlPanel
The following method will return true if the required window is forced to the foreground.
forceForegroundWindow(pForm : Form): Boolean;
// Forces pForm to be the foreground window.
// Returns true if successful, false otherwise.
constants
TRUE : Integer = 1;
FALSE : Integer = 0;
SPI_GETFOREGROUNDLOCKTIMEOUT : Integer = #2000;
SPI_SETFOREGROUNDLOCKTIMEOUT : Integer = #2001;
SPIF_SENDCHANGE : Integer = 2;
vars
formHandle : Integer;
currentForegroundWindow : Integer;
saveTimeout : Integer;
foregroundThreadId : Integer;
formThreadId : Integer;
versionOS : String;
archOS : Integer;
begin
formHandle := pForm.hwnd;
// Check to see if it already is the foreground window
if call getForegroundWindow() = formHandle then
return true;
endif;
// Try using BringWindowToFront etc without any fiddling
call bringWindowToTop(formHandle);
call setForegroundWindow(formHandle);
if call getForegroundWindow() = formHandle then
return true;
endif;
// That didn't work so try setting foregroundLockTimeout to zero
call getSystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, saveTimeout, 0);
if saveTimeout <> 0 then
call setSystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_SENDCHANGE);
call bringWindowToTop(formHandle);
call setForegroundWindow(formHandle);
call setSystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, saveTimeout, SPIF_SENDCHANGE);
if call getForegroundWindow() = formHandle then
return true;
endif;
endif;
// That didn't work so, as a last resort, try the attach thread method
if process.getOSPlatform(versionOS, archOS) = Node.OSWindowsEnterprise then
// May be able to relax this restriction and use on any OS. Will need testing
// Tested for W2K and NT
foregroundThreadId := call getWindowThreadProcessId(call getForegroundWindow(), 0);
formThreadId := call getWindowThreadProcessId(formHandle, 0);
if call attachThreadInput(formThreadId, foregroundThreadId, TRUE) <> 0 then // successfully attached
call bringWindowToTop(formHandle);
call setForegroundWindow(formHandle);
call attachThreadInput(formThreadId, foregroundThreadId, FALSE); // hopefully detached
endif;
endif;
return call getForegroundWindow() = formHandle;
end;
Cheers, Brendan