Skip navigation links
IT services and product development
Menu
TwoLogs
IT services and product development

Source code for C_ActivateWindow

Download

The source files for this module are listed below.  You can also download the module C_ActivateWindow as a zip archive; this archive contains all the source files and documentation.

Description

ActivateWindow allows you to activate a window so that the user notices it; either by making the window the foreground window or if that fails by flashing the taskbar button.

Information

Part of this source code conditionally uses our C_DesktopWaiter module.  You can also download it at our website.

Since Windows 98 and Windows 2000, Windows has become more strict in which applications can bring their window to the foreground.  The consequence of this is that calling e.g. SetForegroundWindow, ActivateWindow and BringWindowToTop doesn't guarantee your window will be on top of all other windows with the input focus on it.  See the MSDN information on SetForegroundWindow for all the circumstances and exclusions.  There are some 'hacks' floating around the Internet that rely on the function AttachThreadInput, the ('deprecated') function SwitchToThisWindow and the function SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT).  But I feel uncomfortable using some of these and/or I didn't even get them to work reliably on my Windows XP SP3 box; it seems Windows is enforcing the rules more and more every day.

Another complication is that when the user is currently not logged on to the computer, SetForegroundWindow will not flash the taskbar window!  This is at least true on my Windows XP SP3 machine.  So before you can call SetForegroundWindow, you first have to check if the user is logged in (on Windows NT, XP and Vista systems).

When you know the user is logged on you can use ActivateWindow.  You pass it the window you want to activate and it will try to activate it or otherwise flash it's taskbar button.

When the user might be logged of and your application runs on a Windows NT system (NT 4, XP, Vista or 7), you're better of using the function ActivateWindowWaitForDesktop.  It takes two parameters: the window to activate and a utility window (they can be the same).  The utility window is needed when on a Windows NT system while the user is interacting with another desktop than the one your application is running on (this could be the logon desktop or a totally different desktop that was created by a "multiple desktop" application).  In this situation the embedded CDesktopWaiter object needs a Window to attach a timer to in order to poll for desktop changes.  To use ActivateWindowWaitForDesktop you have to define ACTIVATEWINDOW_USE_DESKTOP, and also include our C_DesktopWaiter module in your code.

Notes / todo's

  • This code is not tested on other systems than Windows XP; if you have tested it on another system, please tell me the results!
  • I explicitly didn't resort to hacks to get my window in the front with the input focus; that's why I rely on SetForegroundWindow and friends.

Files

Each file belonging to this source code module is listed below.

ActivateWindow.h

/*******************************************************************************

  Version: 2
  Author:  Carl Colijn, TwoLogs
  Contact: c.colijn@twologs.com
  Source:  http://www.twologs.com/sourcecode

  This code is freely distributable, as long as this comment remains intact.
  If you find this source useful, you may use this code in your own projects
  free of charge, but some acknowledgement to the author of this code is always
  appreciated :)
  The source is however distributed 'as is' without waranty and/or support, and
  may not be fit for each and every application.  Use it at your own discretion
  and at your own risk.
  The source already has undergone testing.  This doesn't mean however that all
  bugs are removed from this piece of code.  If you find one of them, please
  contact me about it.  I can however not guarantee when and if the bug will be
  fixed.

  More information about this module can be found in the accompanying HTML file.

*******************************************************************************/

#ifndef INCLUDE_TWOLOGS_COMMON_ACTIVATEWINDOW_H
#define INCLUDE_TWOLOGS_COMMON_ACTIVATEWINDOW_H

#include <windows.h>

// Activates the given window
void ActivateWindow(HWND hWindow);

#ifdef ACTIVATEWINDOW_USE_DESKTOP
// Activates the given window when the desktop the window is on is active
// If needed, the given utility window will be used to attach a Windows timer to
// by a DesktopWaiter object; you can use the same window if you like
void ActivateWindowWaitForDesktop(HWND hWindow, HWND hUtilityWindow);
#endif // ACTIVATEWINDOW_USE_DESKTOP

#endif // INCLUDE_TWOLOGS_COMMON_ACTIVATEWINDOW_H

ActivateWindow.cpp

/*******************************************************************************

  Version: 2
  Author:  Carl Colijn, TwoLogs
  Contact: c.colijn@twologs.com
  Source:  http://www.twologs.com/sourcecode

  This code is freely distributable, as long as this comment remains intact.
  If you find this source useful, you may use this code in your own projects
  free of charge, but some acknowledgement to the author of this code is always
  appreciated :)
  The source is however distributed 'as is' without waranty and/or support, and
  may not be fit for each and every application.  Use it at your own discretion
  and at your own risk.
  The source already has undergone testing.  This doesn't mean however that all
  bugs are removed from this piece of code.  If you find one of them, please
  contact me about it.  I can however not guarantee when and if the bug will be
  fixed.

  More information about this module can be found in the accompanying HTML file.

*******************************************************************************/

#include "ActivateWindow.h"
#ifdef ACTIVATEWINDOW_USE_DESKTOP
#include "..\C_DesktopWaiter\DesktopWaiter.h"
#endif // ACTIVATEWINDOW_USE_DESKTOP

// Activates the given window
void ActivateWindow(HWND hWindow) {
  // Restore the window correctly
  if (IsIconic(hWindow)) {
    ShowWindow(hWindow, SW_RESTORE);
  } else {
    ShowWindow(hWindow, SW_SHOW);
  }

  // And force the window to get attention
  BringWindowToTop(hWindow);
  SetForegroundWindow(hWindow);
  SetActiveWindow(hWindow);
}

#ifdef ACTIVATEWINDOW_USE_DESKTOP
// Window activator
class CWindowActivator:
  public CSlot<CUserOnOurDesktopEvent> {
public:
  // Constructor
  CWindowActivator();

  // The desktop waiter to use
  CDesktopWaiter m_oDesktopWaiter;

  // Activates the given window
  void Activate(HWND hWindow, HWND hUtilityWindow);

private:
  // The window to activate
  HWND m_hWindow;

  // Activates the window
  void Activate();

  // Events
  bool OnEvent(CUserOnOurDesktopEvent& oEvent);
};
static CWindowActivator g_oWindowActivator;

// Constructor
CWindowActivator::CWindowActivator():
 m_hWindow(NULL) {
  // Connect to our desktop waiter
  CSlot<CUserOnOurDesktopEvent>::Connect(&m_oDesktopWaiter);
}

// Events
bool CWindowActivator::OnEvent(CUserOnOurDesktopEvent& oEvent) {
  Activate();
  return true;
}

// Activates the given window
void CWindowActivator::Activate(HWND hWindow, HWND hUtilityWindow) {
  // Note the window to activate
  m_hWindow = hWindow;

  // Let the desktop waiter wait till the logon desktop is gone
  if (!m_oDesktopWaiter.StartWaiting(hUtilityWindow)) {
    // Done immediately -> activate now
    Activate();
  }
}

// Activates the window
void CWindowActivator::Activate() {
  ActivateWindow(m_hWindow);
}

// Activates the given window when the desktop the window is on is active
// If needed, the given utility window will be used to attach a Windows timer to
// by a DesktopWaiter object; you can use the same window if you like
void ActivateWindowWaitForDesktop(HWND hWindow, HWND hUtilityWindow) {
  g_oWindowActivator.Activate(hWindow, hUtilityWindow);
}
#endif // ACTIVATEWINDOW_USE_DESKTOP