zoukankan      html  css  js  c++  java
  • VC 获取任务栏窗体的句柄

    

    本文将介绍一个未公开的Win32 API函数:GetTaskmanWindow。利用它对Windows的任务栏进行操作。

    这个函数返回拥有任务栏button的窗体句柄。

    在微软的MSDN文档中。对任务栏是这样描写叙述的:"……Windows界面包括一个特殊的应用程序桌面工具栏,叫做任务栏。任务栏能够用于在打开的不同窗体之间进行切换,以及启动新的应用程序……。任务栏包括有開始菜单、任务栏button、快捷菜单和状态显示区……"。可惜在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("
    ");
    
    	//比如:得到类名结果例如以下:
    	//说明:获取任务栏上系统窗体非常全面,但获取其它用户应用程序窗体不全面
    	// TrayNotifyWnd
    	// Button								//"開始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("
    ");
    
    			//比如: 得到类名结果例如以下:
    			//说明: 获取任务栏上应用程序非常全,但获取系统的不全(入開始菜单button,托盘窗体,时间窗体等等)
    			//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;
    }

  • 相关阅读:
    从零到有模拟实现一个Set类
    node+express+mysql 实现登陆注册
    从路由原理出发,深入阅读理解react-router 4.0的源码
    linux rsyncserver文件同步
    为什么说Python是一门动态语言--Python的魅力
    python基础教程_学习笔记11:魔法方法、属性和迭代器
    list,set,map,数组间的相互转换
    TCP/IP协议族
    宿舍更换的新淋浴喷头"水温vs旋钮角度"关系的研究(曲线)
    单元測试中 Right-BICEP 和 CORRECT
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6858077.html
Copyright © 2011-2022 走看看