Click here to Skip to main content
15,884,592 members
Articles / Programming Languages / C#
Article

Selecting Running Application

Rate me:
Please Sign up or sign in to vote.
4.00/5 (6 votes)
29 May 2008CPOL6 min read 28K   857   11   3
Clone of the control displayed by Windows XP if Alt+Tab is pressed

Introduction

The goal of this project is to create a program which can capture a defined region of a running tasks window. This is done by first choosing the task from a list similar to Windows’ own task switching control (it appears in the center of the screen when the user presses the Alt and Tab key), after that you can select the region to be captured by clicking and dragging a rectangle around it.

Using the Code

First of all, let us introduce files of the solution:

  • Config: Configure application behavior
  • TestForm: Used to test different task switching modes
  • FormSelectApp: Form displaying appropriate applications. It is a clone of the built-in control of Windows XP
  • Win32: Encapsulates Win32 API calls

TestForm - Test Environment

This is the main form of the program where the user can set how screen capturing will work. If capture Alt + Tab is not checked, first the user has to click on the Custom button to show the task switching control (FormSelectApp), while if checked, the program behaves as a clone of Windows’ built-in task switching tool, captures the event of pressing Alt + Tab and then shows FormSelectApp. Win32 classes RegisterHotkey() function is called to register Alt+Tab and Alt+Shift+Tab as a hotkey with ids 111 and 112. To disable Windows’ built-in functionality, we override Windows’ message handling (WndProc()), and watch for pressings of hot keys with ids 111 and 112. Each hot key starts FormSelectApp first by calling OpenFormSelectApp(), and besides that, repeatedly pressing them tells it to iterate through the elements shown in its list. To imitate Windows’ task switching mechanism, we have to watch out for the release of the left Alt key. This is done by using global keyboard hooks and by using the code presented in this article.

When an Alt+Tab or Alt+Shift+Tab hot key event is processed first, OpenFormSelectApp() initializes a global hook for listening to KeyDown and KeyUp events. The KeyUp() eventhandler processes the release of left Alt key, and when ShouldSwitchToSelected is set to true, it calls FormSelectApp’s SwitchToSelected. It brings the selected ListViewItem’s task to the foreground and closes FormSelectApp by CloseFormSelectApp(). ShouldSwitchToSelected is set to false when the user cancels the Alt+Tab mechanism by pressing something else other than Alt, Tab, Shift, Enter or the arrow keys. The pressing of these keys is handled by the KeyDown eventhandler. Pressing the right arrow key tells FormSelectApp to select the next ListViewItem, the left selects the previous item. Pressing the Enter key triggers the release of the left Alt key, i.e. switching to the selected task. Pressing anything else other than these turns ShouldSwitchToSelected to false and raises a KeyUp event with left Alt. CloseFormSelectApp() closes the form and unregisters the eventlisteners for pressing and releasing keys.

FormSelectApp - Displaying Applications

This is the form which is used to select the task to capture from. It has a ListView control on it showing icons of the running apps and a TextBox showing the title of the currently selected ones.
Depending on the forms' DisplayMode property, it can show icons only or icons and titles under them. In the constructor, we use the EnumWindows() function of Win32 with a callback pointer created from Win32’s EnumWindowsCallBack() delegate function. Their exact functionality is described in a separate section. EnumWindows() is used to enumerate through all the currently running Windows, and by passing a callback pointer of our function to it, we can examine them one by one. FormSelectApps AddWindowItem() is used as a delegate function for Win32’s AddWindowItem delegate to add a WindowItem to the ListView when EnumWindowsCallback() function calls it. This is done by creating a new ListViewItem containing the title of the passed WindowItem, and when passed, the index of its icon is added to an ImageList named appIconList. The ListView’s DrawItem() function is overridden for its look to be as close to Windows’ own task switching components' look as possible. Without custom drawing, it is impossible to implement the blue border around the selected item. When the user clicks on a ListViewItem, Win32’s SetForegroundWindow() function is called to bring it to the foreground. This double clicking event handler is called upon pressing the enter key, or when the user releases the left Alt key if it is captured. SelectNext() and SelectPrevious() functions are called when the user presses the arrow keys, or if Alt + Tab is captured and Tab or Shift+Tab is pressed along with left Alt.

In order to be as close to the Windows’ own task switching components' look as possible, we have to use bevel around the controls. The implementation is based on this article.

It has been changed to derive from Panel instead of Control (to make it easier to put items in it) and a new property, BevelWidth was added.

Win32

The reason for creating this class was to separate Windows’ low-level calls which it handles from the presentation layer (MainForm and FormSelectApp).

Finding Windows

CallBackPtr is a delegate used in user32.dll's EnumWindows function to call back from every running application. We use EnumWindowsCallBack as a delegate function for EnumWindows to call with the actual Windows handle. While processing these Windows with EnumWindowsCallBack, we collect the ones to display and add them to our ListView. The decision is made by calling user32.dll's GetParent function, which returns a zero int pointer for Windows without parents. User32.dll's GetWindow() and GetWindowLong() functions are used to filter Windows without owners in tool style and Windows with an owner in application style. The title of the Windows is extracted by user32.dll's GetWindowText() function.

Retrieving Icons

We get hold of the icons with the GetWindowBigIcon() function. For each adequate window, we create a WindowItem and call the delegate function AddWindowItem() with it. GetWindowBigIcon() returns with the icon of the window handle it was passed. It uses user32.dll’s SendMessageTimeout() function with a message to return with the passed window handlers icon (WM_GETICON). If it fails (the icon handle created from the result variable is null), then we use another user32.dll function, GetClassLong() with GCL_HICON to retrieve the required icon. If it still fails, we use SendMessageTimeout() again with a message WM_QUERYDRAGICON.

Points of Interest

The article introduces how to use delegates to communicate between low level API classes and GUI. Retrieving icons seems to be a simple task, however most people forget the case that some applications cannot respond to SendMessage correctly and the returned icon is null. The article also describes how to use custom draw of Listview items to display a frame around the selected item.

History

  • 2008.05.29: First version of the article

License

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


Written By
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSeems to me... Pin
#realJSOP29-May-08 11:07
mve#realJSOP29-May-08 11:07 
GeneralRe: Seems to me... Pin
radialronnie29-May-08 15:50
radialronnie29-May-08 15:50 
GeneralRe: Seems to me... Pin
Giorgi Dalakishvili5-Oct-08 20:53
mentorGiorgi Dalakishvili5-Oct-08 20:53 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.