qt-获取任务栏运行的程序(一)
很多时候我们想要拿到任务栏上开启的程序,比如下面所示:

我们以window为例说明
下面的代码主要部分就是通过一个回调函数: EnumWindows()
1、声明一个函数 static BOOL CALLBACK StaticEnumWindowsProc(HWND hwnd, LPARAM lParam);
2、实现如下
BOOL Widget::StaticEnumWindowsProc(HWND hwnd, LPARAM lParam) { //窗口是否可视 if (!::IsWindowVisible(hwnd)) return TRUE; //窗口是否可激活 if (!::IsWindowEnabled(hwnd)) return TRUE; //确定给定窗口是否是最小化(图标化)的窗口。 //if(IsIconic(hwnd)) // return TRUE; //窗口是否具有父窗口? HWND hParent = (HWND)GetWindowLong(hwnd, GWL_HWNDPARENT); //父窗口是否可激活? //据 Spy++ 观察,如“运行”对话框等被应列入列表的程序有一个隐藏的,具有 WS_DISABLED 的父窗口 if (IsWindowEnabled(hParent)) return TRUE; //父窗口是否可视? if (IsWindowVisible(hParent)) return TRUE; LONG gwl_style = GetWindowLong(hwnd, GWL_STYLE); if ((gwl_style & WS_POPUP) && !(gwl_style & WS_CAPTION)) return TRUE; CHAR caption[256]; memset(caption, 0, sizeof(caption)); ::GetWindowTextA(hwnd, caption, 255); if (strcmp(caption, "")) { if (GetClassLong(hwnd, GCL_HICON)) { HICON hIcon =(HICON)GetClassLong(hwnd, GCL_HICON); if(hIcon) { handleIcon.push_back(hIcon); handleWindow.push_back(hwnd); } } } return TRUE; }
3、然后调用 回调函数。在win32环境下,EnunWindows(StaticEnumWindowPro, NULL).如果是Qt环境,则EnumWindows(StaticEnumWindowsProc,reinterpret_cast<LPARAM>this)
---------------我是分割线--------------------
通过上面的几步,我们把符合条件的窗口句柄以及要用的图标句柄添加到QVector中(QVector<HWND> handleWindow; QVector<HICON>handleIcon)。下面就是把拿到的句柄展示出来
-----------------------GGGGGGG----------
4、我是在qt环境下显示的,当然你习惯用vc,那就用MFC的控件。
在一个QWidget中放置了一个QGridLayout布局,然后把QtoolButton用来显示图标。如下
void Widget::InitBtnIcon() { int i; int nIconCount = 0; CHAR szProgramName[256] = {0}; QString strName; nIconCount = handleIcon.count(); if(nIconCount <= 0) return; if(nIconCount > 6) { nIconCount = 6; m_rightBtn->setVisible(true); } //加一个定时器,每隔一段时间就运行一遍Enumwindows //给6个Button默认的图标 for(i = 0; i < nIconCount; i++) { //------------------ //QPixmap pixmap = QtWin::fromHBITMAP(GetScreenCapture(handleWindow[i + m_nBtnMove])); // m_arrAction[i]->setIcon(pixmap); //m_arrAction[i]->setIconSize(QSize(pixmap.width(), pixmap.height())); //----------------- m_arrAction[i]->setIcon(QtWin::fromHICON(handleIcon[i + m_nBtnMove])); // m_arrAction[i]->setIconSize(QSize(QtWin::fromHICON(handleIcon[i]).width(), // QtWin::fromHICON(handleIcon[i]).height())); m_arrAction[i]->setIconSize(QSize(32, 32)); //--------------- //QPixmap pixmap = QtWin::fromHBITMAP(GetScreenCapture(handleWindow[i + m_nBtnMove])); //m_arrAction[i]->setIcon(pixmap); //m_arrAction[i]->setIconSize(QSize(pixmap.width(), pixmap.height())); //m_arrAction[i]->setIconSize(fromHBITMAP(GetScreenCapture()).); //--------------- //screen capture //QScreen *screen = QGuiApplication::primaryScreen(); //screen->grabWindow(GetWindowLong(handleWindow[i+ m_nBtnMove],GWL_ID),0,0,-1,-1).save("captureImg1.jpg","jpg"); //screen->grabWindow(GetWindowLong(handleWindow[1],GWL_ID),0,0,-1,-1).save("captureImg3.jpg","jpg"); //GetModuleFileName(handleWindow[i], szProgramName, 255); GetWindowTextA(handleWindow[i+ m_nBtnMove], szProgramName, 255); strName = QString::fromLocal8Bit(szProgramName); //strName = strName.lastIndexOf("\\"); //m_arrAction[i]->setText(strName); m_arrAction[i]->setToolTip(strName); //m_arrAction[i]->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } }
5、添加按钮的响应槽
for(int i = 0; i < 6; i++)
{
connect(m_arrAction[i], SIGNAL(clicked()), m_pSignalArrBtns, SLOT(map()));
m_pSignalArrBtns->setMapping(m_arrAction[i], i);
}
connect(m_pSignalArrBtns, SIGNAL(mapped(int)), this, SLOT(slotClickBtn(int)));
因为同一类型的控件很多,我们用到一个信号影射。这样,通过nIndex可以确定是谁发出的信号。然后下面是slotClickBtn()的实现
//ShowWindow(handleWindow[nIndex + m_nBtnMove], SW_RESTORE);
::SetWindowPos(handleWindow[nIndex + m_nBtnMove], 0, 0, 0, 0, 0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW);
//QScreen *screen = QGuiApplication::primaryScreen();
//screen->grabWindow(GetWindowLong(handleWindow[i+ m_nBtnMove],GWL_ID),0,0,-1,-1).save("captureImg1.jpg","jpg");
//screen->grabWindow(GetWindowLong(handleWindow[1],GWL_ID),0,0,-1,-1).save("captureImg4.jpg","jpg");
//QMessageBox::information(this, "ddd", QString::number(nIndex));
//GetScreenCapture(handleWindow[nIndex]);
通过以上几步,我们大体就可以得到想要的结果,效果图如下:

但是有几个问题,第一:最小化的程序开的窗口不能识别,比如QQ,酷狗等。估计是因为窗口风格是WS_EX_LAYERED的原因。第二:资源管理器明显拿不到
注意,这几个函数需要添加头文件的支持:
#include<Windows.h> 以及静态库的支持 #pragma comment(lib, "user32.lib")
如果是qt环境,则添加如下:
#include "Windows.h" #include <QtWin> 、qtwinextras/qwinfunctions、以及库依赖#pragma comment(lib, "user32.lib"), 并且在.pro文件中添加 QT += winextras
完成源代码如下:
邮箱xxxx
如果是用MFC的方式实现,那么用下面的方法:
// File: OpenProgramOnTaskbar.h
#pragma once
#include <vector>
struct TaskInfo
{
// 程序名称
CString strProgramName;
// 窗口句柄
HWND hWnd;
};
class TaskbarInfo
{
public:
// 回调函数
static BOOL CALLBACK EnumWindowProc(HWND hWnd, LPARAM lParam);
public:
// 记录在任务栏打开的程序
std::vector<TaskInfo> m_TaskbarInfoArr;
// 顶层窗口句柄
HWND m_hWnd;
public:
TaskbarInfo();
~TaskbarInfo();
// 获得在任务栏打开程序信息
void GetTaskbarInof (void);
// 获得顶层窗口句柄,失败返回NULL
HWND GetTopWnd (void);
};
// File: OpenProgramOnTaskbar.cpp
#include "stdafx.h" // 如果编译出错,请删除这句
#include "OpenProgramOnTaskbar.h"
#include "Psapi.h"
#pragma comment(lib, "Psapi.lib")
TaskbarInfo::TaskbarInfo()
{
}
TaskbarInfo::~TaskbarInfo()
{
}
void TaskbarInfo::GetTaskbarInof (void)
{
EnumWindows(EnumWindowProc, (LPARAM)this);
}
BOOL CALLBACK TaskbarInfo::EnumWindowProc(HWND hWnd, LPARAM lParam)
{
TaskbarInfo * pTaskbarInfo = (TaskbarInfo*)lParam;
TCHAR szWindow[256]={0};
TaskInfo taskInfo;
::GetWindowText(hWnd, szWindow, 255); //获取窗口标题
if ( ::IsWindow(hWnd) &&
::IsWindowVisible(hWnd) &&
(::GetWindowLong(hWnd, GWL_EXSTYLE)&WS_EX_TOOLWINDOW)!=WS_EX_TOOLWINDOW &&
::GetWindowLong(hWnd, GWL_HWNDPARENT)==0 )
{
DWORD dwPID; //保存进程标识符
GetWindowThreadProcessId(hWnd, &dwPID); //接受一个窗口句柄。dwPID保存窗口的创建者的进程标识符,GetWindowThreadProcessId返回值是该创建者的线程标识符
HANDLE hBrowser = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); //打开一个已存在的进程对象,并返回进程的句柄,这就是我们要的进程句柄了
WCHAR exePath[256];
memset(exePath, 0, 256);
//获取程序的path,并保存到exePath
GetModuleFileNameEx(hBrowser, NULL, exePath, MAX_PATH);
CString strTemp = exePath;
strTemp.MakeLower();
// 过滤在桌面打开的文件夹等
if (!strTemp.IsEmpty() && strTemp.Find(_T("explorer.exe")) == -1)
{
taskInfo.strProgramName = szWindow;
taskInfo.hWnd = hWnd;
pTaskbarInfo->m_TaskbarInfoArr.push_back(taskInfo);
memset(szWindow, 0, 256);
}
}
return TRUE;
}
HWND TaskbarInfo::GetTopWnd (void)
{
DWORD dwPID; //保存进程标识符
HWND hWnd = NULL;
hWnd = ::GetForegroundWindow();
GetWindowThreadProcessId(hWnd, &dwPID); //接受一个窗口句柄。dwPID保存窗口的创建者的进程标识符,GetWindowThreadProcessId返回值是该创建者的线程标识符
HANDLE hBrowser = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); //打开一个已存在的进程对象,并返回进程的句柄,这就是我们要的进程句柄了
WCHAR exePath[256];
memset(exePath, 0, 256);
//获取程序的path,并保存到exePath
GetModuleFileNameEx(hBrowser, NULL, exePath, MAX_PATH);
CString strTemp = exePath;
strTemp.MakeLower();
if (!strTemp.IsEmpty() && strTemp.Find(_T("explorer.exe")) == -1)
{
m_hWnd = hWnd;
if (m_hWnd != NULL)
{
return m_hWnd;
}
}
return NULL;
}

浙公网安备 33010602011771号