⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alttab.cpp

📁 该代码压缩包只为需要研究CE下的任务管理器的实现而提供的。某些通用的头文件没有包含在其中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*---------------------------------------------------------------------------*\
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 * 
 *
 *  file:  ALTTAB.CPP
 *  purpose: Implement Sample shell Task-manager-like dialog
 *
\*---------------------------------------------------------------------------*/

#include "windows.h"
#include "windowsx.h"
#include <sipapi.h>
#include "minshell.h"
#include "minshrc.h"
#include "commdlg.h"

// Useful macros
#define cchsizeof(x)	(sizeof(x)/sizeof(TCHAR))

#define RestoreForegroundWindow(hwnd)   \
    SetForegroundWindow((HWND)(((DWORD)hwnd) | 0x01))

// info passed to TaskMan_ReallyKill
typedef struct 
{
	HWND   hwnd;
	LPTSTR pszTitle;
}
KILLTARGETINFO;

// Local fns
int TaskMan_PopulateLB(HWND hwndLB, HWND hwndFG);
LRESULT CALLBACK TaskMan_ReallyKill(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
LRESULT CALLBACK RunDlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
BOOL IsOKToKill(HWND hwndApp);

// We dynamically determine whether the current OS configuration has the
// Fileopen component, by calling LoadLibrary & GetProcAddress. If we obtain
// the GetOpenFilename API then we display a Browse button on the Start-Run
// dialog. Otherwise we hide it.
typedef BOOL (APIENTRY*  PFNGETOPENFILENAME)(LPOPENFILENAME lpofn);
PFNGETOPENFILENAME g_pfnGetOpenFileName;

//
// This is the dlgproc for the Takman dialog. The dialog has a listbox of all
// top-level windows, and Switch-To and End-Task buttons, which allow the user
// to switch between apps or terminate hung apps. 
// The dialog also has a Run button that brings up Start-Run type dialog, and
// of course a Cancel button
// 
// NOTE: The dialog is actually a permanent modeless dialog created on shell 
// startup. Pressing ALt-Tab merely brings it to the front, and Cancel hides
// it, rather than actually destroying the dialog
//

int CALLBACK TaskMan_DlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
	int iIndex, iCount;
	HWND hwndLB = GetDlgItem(hwnd, IDC_LISTBOX);
	HWND hwndFG;

	DEBUGMSG(ZONE_TRACEMSGHF, (TEXT("AltTab Window Msg=%x wp=%x lp=%x\r\n"), msg, wp, lp));
	
	switch(msg)
	{
		// created on program startup
		case WM_INITDIALOG:
			break;

		// activated on user pressing Alt-Tab etc (see MINTASK.CPP)
		case WM_ACTIVATE:
			if(LOWORD(wp) != WA_INACTIVE)
			{
				CenterWindowSIPAware(hwnd, TRUE);
				// We use DWL_USER tp remember the window that was foreground *before*
				// this dialog came up, so that we can select it in our listbox
				hwndFG = (HWND)GetWindowLong(hwnd, DWL_USER);
				// Fill listbox with currently running top-level windows
				iCount = TaskMan_PopulateLB(hwndLB, hwndFG);
				// enable or disable SwitchTo & EndTask buttons, based on lisbox item count
				EnableWindow(GetDlgItem(hwnd, IDC_ENDTASK), iCount);
				EnableWindow(GetDlgItem(hwnd, IDOK), iCount);
				SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndLB, (LPARAM)TRUE);
			}
			break;

		case WM_SETTINGCHANGE:
			// Recenter dialog when SIP goes up (see details in the block 
			// comment at the head of the CenterWindowSIPAware function)
			if(wp==SPI_SETSIPINFO)
				CenterWindowSIPAware(hwnd, FALSE);
			break;
		
		case WM_COMMAND:
			switch (GET_WM_COMMAND_ID(wp,lp)) 
			{
				// Bring up a Start-Run type dialog
				case IDC_RUN:
				{
					// Choose the dialog template based on screen-dimensions. See details in RC file
					int idd = (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN))
											? IDD_RUN_G : IDD_RUN;
					if(-1 != DialogBox(g_hInst, MAKEINTRESOURCE(idd), hwnd, (DLGPROC)RunDlgProc))
					{
						// If user didnt cancel out of Run dialog, dismiss (hide) the Taskman dlg
						ListBox_ResetContent(hwndLB);
						ShowWindow(hwnd, SW_HIDE);
					}
					break;
				}

				// Try to terminate the task. First nicely (by sending WM_CLOSE), then
				// if it doesn't respond, use TerminateProcess
				case IDC_ENDTASK:
				{
					KILLTARGETINFO killinfo;
					DECLAREWAITCURSOR;
					if((iIndex = ListBox_GetCurSel(hwndLB)) != LB_ERR) 
					{
						SetWaitCursor();
						killinfo.hwnd = (HWND)ListBox_GetItemData(hwndLB, iIndex);
						// post Close message whether window is enabled or not
						// If it has child popups active it stil needs to be closed
						PostMessage(killinfo.hwnd, WM_CLOSE, 0, 0);
						// Wait for app to actually close
						for(int i=0;IsWindow(killinfo.hwnd) && i<3;i++) 
							Sleep(1700); // sleep min 1.7s, max 5.1sec
							
						// If app is still around prompt for TerminateProcess
						// IMPORTANT: First check if it is not a system process
						if (IsWindow(killinfo.hwnd) && IsOKToKill(killinfo.hwnd)) 
						{
							int iLen = ListBox_GetTextLen(hwndLB, iIndex);
							// set up a killinfo struct with the HWND & title of the window
							// and pass it into the ReallyKill dialog.
							if(iLen && (killinfo.pszTitle=(LPTSTR)_alloca((iLen+1)*sizeof(WCHAR))))
							{
								int idd;
								killinfo.pszTitle[0]=0;
								ListBox_GetText(hwndLB, iIndex, killinfo.pszTitle);
								ResetWaitCursor();
								// Choose the dialog template based on screen-dimensions. See details in RC file
								idd = (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN))
											? IDD_REALLYKILL_G : IDD_REALLYKILL;
								DialogBoxParam(g_hInst, MAKEINTRESOURCE(idd), hwnd,
										   (DLGPROC)TaskMan_ReallyKill, (LPARAM)(&killinfo));
								// we're done -- hide the Taskman dialog
								ListBox_ResetContent(hwndLB);
								ShowWindow(hwnd, SW_HIDE);
								break;
							}
						}
						// We could not terminate it. But we're done anyway. 
						// Hide the Taskman dialog
						ListBox_ResetContent(hwndLB);
						ResetWaitCursor(); // this must come *before* SW_HIDE
						ShowWindow(hwnd, SW_HIDE);
					}
					break;
				}

				case IDC_LISTBOX:
					// double-click in listbox is takedn to be a "switch-to" & falls through to IDOK
					if(HIWORD(wp) != LBN_DBLCLK)
						break;
					// else fall through
				case IDOK:
					// User pressed "Switch To"
					if((iIndex = ListBox_GetCurSel(hwndLB)) != LB_ERR)
					{
						RestoreForegroundWindow((HWND)ListBox_GetItemData(hwndLB, iIndex));
						ShowWindow(hwnd, SW_HIDE);
						ListBox_ResetContent(hwndLB);
					}
					break;

					// User pressed "Cancel"
				case IDCANCEL:
					ShowWindow(hwnd, SW_HIDE);
					ListBox_ResetContent(hwndLB);
					break;
			}
			break;
		default:
			return FALSE;
	}
	return TRUE;
}

// If the user manages to terminate one of these system processes, the system will 
// crash, so disallow it. This situation can happen if, say, a device driver 
// in device.exe puts up a dialog box & the user tries to terminate it
//
// Forbidden processes list. Must be all lower-case
LPTSTR rgVerboten[] = { L"device.exe", L"gwes.exe", L"nk.exe", L"filesys.exe", 0 };

// Check if a window belongs to a system process
BOOL IsOKToKill(HWND hwndApp)
{
	HANDLE hProc;
	WCHAR wszBuf[MAX_PATH];
	int i;
	DWORD dwProcessId;

	// Get the window's owning process
	GetWindowThreadProcessId(hwndApp, &dwProcessId);
	// Open the process
	hProc = OpenProcess(PROCESS_ALL_ACCESS,0,dwProcessId);
	wszBuf[0] = 0;
	// Get it's filename
	GetModuleFileName((HINSTANCE)hProc, wszBuf, MAX_PATH);
	CloseHandle(hProc);
	// lowercase the filename so substring match will suceed
	wcslwr(wszBuf);
	
	DEBUGMSG(1, (L"Trying to kill process %s\r\n", wszBuf));

	// Check if the process is in the Forbidden list
	for(i=0; rgVerboten[i]; i++)
	{
		// Note: we use a substring match so path effects are eliminated
		if(wcsstr(wszBuf, rgVerboten[i]))
		{
			RETAILMSG(1, (L"It is VERBOTEN to kill process %s\r\n", wszBuf));
			return FALSE;
		}
	}
	return TRUE;
}

//
// Walk the list of top-level windows & populate the Taskman listbox
//
int TaskMan_PopulateLB(HWND hwndLB, HWND hwndFG)
{
	int iIndex, iCount;
	HWND hwndApp;

	DEBUGMSG(ZONE_TRACETASKMAN, (L"TaskMan: Populate: hwndFG=%x hwndTaskbar=%x hwndDesktop=%x\r\n", hwndFG, g_hwndTaskBar, g_hwndDesktop));
	ListBox_ResetContent(hwndLB);

	// Iterate through all windows. Ignore all non-top-level windows
	// Also ignore taskbar & desktop. Normally we would ignore top-level popup/dialogs BUT
	// since we're a minshell here & there's no other way to get to things such as RNAAPP
	// we allow these to stay on the list.
	for(iCount=0, hwndApp=GetWindow(g_hwndTaskBar, GW_HWNDLAST); hwndApp; hwndApp = GetWindow(hwndApp, GW_HWNDPREV))
	{

		if (IsWindowVisible(hwndApp) &&
			(hwndApp != g_hwndTaskBar) &&
			(hwndApp != g_hwndDesktop) &&
			(hwndApp != g_hwndTaskMan) && 
			!GetWindow(hwndApp, GW_OWNER) /*&&
			!(GetWindowLong(hwndApp, GWL_STYLE) & WS_POPUP)*/)
		{
			WCHAR wszBuf[MAX_PATH];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -