Click here to Skip to main content
Click here to Skip to main content

How to bring window to top with SetForegroundWindow()

By , 27 Apr 2010
 

Introduction

This can help you to bypass limitation of using ::SetForegroundWindow() function.

Before code some from MSDN:

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

• The process is the foreground process.

• The process was started by the foreground process.

• The process received the last input event.

• There is no foreground process.

• The foreground process is being debugged.

• The foreground is not locked (see LockSetForegroundWindow).

• The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).

• No menus are active.

 
An application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user.

 
A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.

 
The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.

 
The system automatically enables calls to SetForegroundWindow if the user presses the ALT key or takes some action that causes the system itself to change the foreground window (for example, clicking a background window).

 
This function is provided so applications can prevent other applications from making a foreground change that can interrupt its interaction with the user.

So, there are 2 ways:

First is works like Alt+TAB window switching in Windows

void SetForegroundWindowInternal(HWND hWnd)
{
	if(!::IsWindow(hWnd)) return;
 
	BYTE keyState[256] = {0};
	//to unlock SetForegroundWindow we need to imitate Alt pressing
	if(::GetKeyboardState((LPBYTE)&keyState))
	{
		if(!(keyState[VK_MENU] & 0x80))
		{
			::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
		}
	}
 
	::SetForegroundWindow(hWnd);
 
	if(::GetKeyboardState((LPBYTE)&keyState))
	{
		if(!(keyState[VK_MENU] & 0x80))
		{
			::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
		}
	}
}
		

And second. In this version we are attaches the input processing mechanism of our thread to that of active thread.

void SetForegroundWindowInternal(HWND hWnd)
{
	if(!::IsWindow(hWnd)) return;
 
	//relation time of SetForegroundWindow lock
	DWORD lockTimeOut = 0;
	HWND  hCurrWnd = ::GetForegroundWindow();
	DWORD dwThisTID = ::GetCurrentThreadId(),
	      dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0);
 
	//we need to bypass some limitations from Microsoft :)
	if(dwThisTID != dwCurrTID)
	{
		::AttachThreadInput(dwThisTID, dwCurrTID, TRUE);
 
		::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0);
		::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
 
		::AllowSetForegroundWindow(ASFW_ANY);
	}
 
	::SetForegroundWindow(hWnd);
 
	if(dwThisTID != dwCurrTID)
	{
		::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
		::AttachThreadInput(dwThisTID, dwCurrTID, FALSE);
	}
}

Have a nice time of day :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

SHShadow
Engineer
Belarus Belarus
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5membergndnet7 Aug '12 - 22:23 
QuestionNeed to use GetAsyncKeyState()membervarkha25 May '12 - 12:03 
General>>The system automatically enables calls to SetForegroundWin...memberNaveen13 Dec '10 - 19:54 
>>The system automatically enables calls to SetForegroundWindow if the user presses the ALT key
 
This is a new information for me. So I was trying this. I created one dialog based application.Put one button and in the button click handler i put one timer for 3 sec and in the WM_TIMER handler, I called SetForegroundWindow(). Now when this application is started, after i clicked the button and immidately brings another window to foreground and kept pressing ALT key in keyboard. But my window didnt came to foreground after 3 seconds. Any comment on that?
 
<pre lang="cs">void CDialogBasedDlg::OnBnClickedButton1()
{
SetTimer( 1, 3000, 0 );
}</pre>
 

<pre lang="cs">void CDialogBasedDlg::OnTimer(UINT_PTR nIDEvent)
{
 
SetForegroundWindow();
 
CDialogEx::OnTimer(nIDEvent);
}</pre>
GeneralThanks for sharing, very helpful. but, if the window is mini...memberqiuchengw2 Dec '10 - 15:29 
GeneralWorks on Win Server 2008 R2memberChris at IAGAM13 Dec '10 - 11:48 
AnswerRe: Works on Win Server 2008 R2memberSHShadow4 Apr '11 - 21:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 28 Apr 2010
Article Copyright 2010 by SHShadow
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid