您的位置:首页 > 其它

VC 获取任务栏窗口的句柄

2015-07-18 16:46 435 查看

本文将介绍一个未公开的Win32 API函数:GetTaskmanWindow,利用它对Windows的任务栏进行操作。这个函数返回拥有任务栏按钮的窗口句柄。在微软的MSDN文档中,对任务栏是这样描述的:"……Windows界面包含一个特殊的应用程序桌面工具栏,叫做任务栏。任务栏可以用于在打开的不同窗口之间进行切换,以及启动新的应用程序……。任务栏包含有开始菜单、任务栏按钮、快捷菜单和状态显示区……"。可惜在Win32 API的正式问当中没有能存取任务栏的函数。因此我们必须使用未公开的Win32 API函数。

下面是GetTaskmanWindow的原型:

//方法1. 获取任务栏句柄
//说明:仅仅是显示已启动应用程序的部分,不包括"开始菜单"、"语言区"、"托盘区"、"时钟区"和"显示桌面"
typedef HWND (WINAPI *PROCGETTASKMANWND)(void);
PROCGETTASKMANWND GetTaskmanWindow;

void main(int argc, char* argv[])
{
  HMODULE hUser32 = GetModuleHandle("user32");
  if (!hUser32)
  {
      return;
  }

  GetTaskmanWindow = (PROCGETTASKMANWND)GetProcAddress(hUser32,"GetTaskmanWindow"); 
  if (!GetTaskmanWindow)
  {
      return;
  }

  HWND hWnd = GetTaskmanWindow();
  if (!hWnd)
  {
      return;
  }
}


方法2:

(1)获取桌面窗口
(2)遍历桌面的子窗口
(3)判断类名为Shell_TrayWnd则为任务栏
(4)然后再遍历任务栏的子窗口找到你要的窗口

HWND g_hWndShell_TrayWnd = 0;

//先遍历桌面的子窗口,得到任务栏窗口句柄
BOOL CALLBACK EnumChildProc1(HWND hWnd, LPARAM lParam)
{
	//成功返回值为拷贝到缓冲的字符数,失败返回0
	TCHAR szText[33] = { 0 };
	if (0 == GetClassName(hWnd, szText, 32))
	{
		return TRUE;
	}

	//"Shell_TrayWnd"为任务栏窗口的句柄,可通过捕捉工具查看
	if (lstrcmp(szText, _T("Shell_TrayWnd")) == 0)
	{
		g_hWndShell_TrayWnd = hWnd;
		return FALSE;
	}
	return TRUE;
}

//再遍历任务栏上的子窗口,得到想要的子窗口句柄或标题
BOOL CALLBACK EnumChildProc2(HWND hWnd, LPARAM lParam)
{
	//[注意]得到的窗口类名肯定不为空,但窗口标题可能为空
	TCHAR szClassName[MAX_PATH] = { 0 };
	GetClassName(hWnd, szClassName, MAX_PATH);

	TCHAR szTitleName[MAX_PATH] = { 0 };
	GetWindowText(hWnd, szTitleName, MAX_PATH);

	//OutputDebugString(szClassName);
	//OutputDebugString("\r\n");

	//例如:得到类名结果如下:
	//说明:获取任务栏上系统窗口很全面,但获取其他用户应用程序窗口不全面
	// TrayNotifyWnd
	// Button								//"开始按钮"的窗口类名称
	// MSTaskListWClass						//显示"任务栏图标"的窗口类名称
	// CiceroUIWndFrame						//右边的显示"输入法"窗口类名称
	// ToolbarWindow32						//右边的显示"托盘图标"窗口类名称
	// TrayClockWClass						//右边显示"日期时间"的窗口类名称
	// TrayShowDesktopButtonWClass			//最右边的"显示桌面"的窗口类名称
	// Edit									//任务栏中的"地址栏"窗口类名称
	// ... ...
	// SysPager								//任务栏上其他应用程序窗口类名称
	// ReBarWindow32
	// MSTaskSwWClass
	// Address Band Root
	// msctls_progress32
	// ComboBoxEx32

	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//先枚举桌面所有子窗口,匹配类名得到任务栏窗口句柄
	//回调函数返回true,则枚举继续直到枚举完成;如果返回false,则中止枚举.
	//或者不用枚举,直接通过FindWindow("Shell_TrayWnd", NULL)一步得到任务栏窗口句柄
	EnumChildWindows(::GetDesktopWindow(), EnumChildProc1, 0);

	//得到任务栏句柄后,再枚举任务栏上所有子窗口句柄
	if (g_hWndShell_TrayWnd)
	{
		EnumChildWindows(g_hWndShell_TrayWnd, EnumChildProc2, 0);
	}

	return 0;
}


方法3:

//该函数是一个与EnumWindows或EnumDesktopWindows一起使用的应用程序定义的回调函数,它接收顶层窗口句柄.
//参数hwnd: 顶层窗口句柄.
//参数lParam: 指定在EnumWindows或EnumDesktopWindows中的应用程序定义值.
//返回值:为继续列表,回调函数必须返回TRUE;若停止列表,它必须返回FALSE.
BOOL CALLBACK EnumTaskbarWnds(HWND hwnd, LPARAM lParam)
{
	//滤掉不在任务栏显示的窗口
	//参数GW_OWNER: 返回的句柄标识了是指定窗口的所有者窗口(如果存在).
	//返回值: 成功返回值为窗口句柄;如果与指定窗口有特定关系的窗口不存在,则返回值为NULL.
	if (!GetWindow(hwnd, GW_OWNER) && IsWindowVisible(hwnd))
	{
		TCHAR szClassName[MAX_PATH] = { 0 };
		GetClassName(hwnd, szClassName, MAX_PATH);

		TCHAR szTitleName[MAX_PATH] = { 0 };
		GetWindowText(hwnd, szTitleName, MAX_PATH);

		if (strcmp(szClassName, "Shell_TrayWnd") != 0	 	//滤掉任务栏本身
			&& strcmp(szClassName, "Progman") != 0)    	//滤掉桌面
		{
			OutputDebugString(szClassName);
			OutputDebugString("\r\n");

			//例如: 得到类名结果如下:
			//说明: 获取任务栏上应用程序很全,但获取系统的不全(入开始菜单按钮,托盘窗口,时间窗口等等)
			//HwndWrapper[DefaultDomain;;1917a89e-ad21-4281-974c-a495d1aa6534]	//VisualStudio窗口
			//HwndWrapper[DefaultDomain;;d98f9c47-8d9c-42bd-87c9-9c924f9823be]
			//ConsoleWindowClass				//控制台窗口
			//Alternate Owner
			//Alternate Owner
			//IEFrame					//浏览器窗口
			//TXGuiFoundation				//QQ聊天窗口
			//Afx:00400000:8:00010003:00000000:00320807	//UEStudio
			//dbgviewClass					//DebugView
			//EVERYTHING					//Everything
			//Alternate Owner
			//Alternate Owner
			//Alternate Owner
			//Alternate Owner
			//Internet Explorer_Hidden
		}
	}

	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//该函数枚举所有屏幕上的顶层窗口,并将窗口句柄传送给应用程序定义的回调函数.
	//参数lPararm:指定一个传递给回调函数的应用程序定义值.
	//返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零.
	EnumWindows(EnumTaskbarWnds, NULL);

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: