| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- #include "windowpreviewwidget.h"
- #include <QApplication>
- #include <QBoxLayout>
- #include <QDebug>
- #include <QLabel> // 添加标签用于显示信息
- #include <QListView>
- #include <QMouseEvent>
- #include <QPainter>
- #include <QScreen>
- #include <QStandardItem>
- #include <QStandardItemModel>
- #include <QStyledItemDelegate>
- #include <QTimer>
- #include <QtWin>
- #include <psapi.h>
- #include <shellapi.h>
- #include <windows.h>
- class ThumbnailDelegate; // 前置声明
- struct WindowInfo
- {
- HWND hwnd;
- std::wstring title;
- std::wstring className; // 窗口类名
- };
- static bool isTooltipWindow(HWND hwnd);
- static bool isAltTabWindow(HWND hwnd, const std::wstring &title, const std::wstring &className)
- {
- HWND shellWindow = GetShellWindow();
- if (hwnd == shellWindow) {
- return false;
- }
- if (title.length() == 0 || title == L"NVIDIA GeForce Overlay") {
- return false;
- }
- if (!IsWindowVisible(hwnd)) {
- return false;
- }
- if (GetAncestor(hwnd, GA_ROOT) != hwnd) {
- return false;
- }
- // LONG style = GetWindowLong(hwnd, GWL_STYLE);
- // if (!((style & WS_DISABLED) != WS_DISABLED)) {
- // return false;
- // }
- // 跳过工具提示窗口
- // if (isTooltipWindow(hwnd)) {
- // return false;
- // }
- // 跳过桌面窗口的特殊类名
- if (className == L"WorkerW" || className == L"Progman") {
- return false;
- }
- return true;
- return !IsIconic(hwnd);
- }
- static bool isTooltipWindow(HWND hwnd)
- {
- wchar_t className[256] = {0};
- GetClassNameW(hwnd, className, 256);
- // 类名过滤列表
- const wchar_t *tooltipClasses[] = {L"tooltips_class32",
- L"Qt5QWindowToolSaveBtn",
- L"QWindowToolTipDropShadowEffect",
- L"QWindowToolTipDropShadows",
- L"PopupWindow",
- L"Xaml_WindowedPopupClass",
- L"Chrome_WidgetWin_2",
- L"QtQWindowIcon",
- L"QtQWindowOwnDCIcon",
- L"QtQWindowPopup",
- L"QtQWindowToolTip",
- L"Windows.UI.Core.CoreWindow"};
- for (const wchar_t *cls : tooltipClasses) {
- if (wcscmp(className, cls) == 0) {
- return true;
- }
- }
- // 通过窗口标题过滤(如果标题包含工具提示相关关键词)
- wchar_t title[256] = {0};
- GetWindowTextW(hwnd, title, 256);
- std::wstring titleStr(title);
- if (titleStr.find(L"Tooltip") != std::wstring::npos
- || titleStr.find(L"Tip") != std::wstring::npos
- || titleStr.find(L"提示") != std::wstring::npos
- || titleStr.find(L"Popup") != std::wstring::npos) {
- return true;
- }
- // // 通过窗口样式过滤
- // LONG style = GetWindowLong(hwnd, GWL_STYLE);
- // LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
- // // 过滤无边框、置顶且透明的弹出窗口
- // if ((exStyle & WS_EX_TOOLWINDOW) && (style & WS_POPUP) && !(style & WS_CHILD)
- // && (exStyle & WS_EX_LAYERED)) {
- // return true;
- // }
- // 过滤小尺寸窗口(通常为工具提示)
- // RECT rect;
- // GetWindowRect(hwnd, &rect);
- // int width = rect.right - rect.left;
- // int height = rect.bottom - rect.top;
- // if (width < 100 && height < 50) {
- // return true;
- // }
- return false;
- }
- BOOL CALLBACK enumWindowsProc(HWND hwnd, LPARAM lParam)
- {
- // 确保窗口有效
- if (!IsWindow(hwnd)) {
- return TRUE;
- }
- // 获取窗口标题
- std::wstring title;
- wchar_t buffer[256] = {0};
- GetWindowTextW(hwnd, buffer, 256);
- title = buffer;
- // 获取窗口类名
- std::wstring className;
- wchar_t classBuffer[256] = {0};
- GetClassNameW(hwnd, classBuffer, 256);
- className = classBuffer;
- // 检查是否是Alt+Tab窗口
- if (!isAltTabWindow(hwnd, title, className)) {
- return TRUE;
- }
- // 添加到窗口列表
- std::vector<WindowInfo> *windows = reinterpret_cast<std::vector<WindowInfo> *>(lParam);
- windows->push_back({hwnd, title, className});
- return TRUE;
- }
- class ThumbnailDelegate : public QStyledItemDelegate
- {
- public:
- explicit ThumbnailDelegate(QObject *parent = nullptr)
- : QStyledItemDelegate(parent)
- {}
- void paint(QPainter *painter,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const override
- {
- painter->save();
- painter->setRenderHint(QPainter::Antialiasing, true);
- // 整个项尺寸(160x120)
- const int itemWidth = 160;
- const int itemHeight = 120;
- // 计算绘制区域在父项中的位置(居中)
- const int left = option.rect.left() + (option.rect.width() - itemWidth) / 2;
- const int top = option.rect.top() + (option.rect.height() - itemHeight) / 2;
- // 主绘制区域(项边界)
- const QRect itemRect(left, top, itemWidth, itemHeight);
- // 创建圆角背景
- painter->setPen(Qt::NoPen);
- painter->setBrush(QColor(40, 40, 40, 180));
- painter->drawRoundedRect(itemRect, 8, 8);
- // 图标位置(左上角)
- const QRect iconRect(itemRect.left() + 5, itemRect.top() + 5, 30, 30);
- // 图标位置(右上角)
- const QRect isMinimizedRect(itemRect.width() - 25, itemRect.top() + 5, 30, 30);
- // 边框区域(内缩10像素)
- const QRect borderRect = itemRect.adjusted(10, 10, -10, -10);
- // 缩略图可用区域(减去底部标题空间)
- const QRect thumbArea = borderRect.adjusted(0, 0, 0, -20); // 底部留20像素给标题
- // 计算最大正方形区域(1:1比例)
- const int thumbSize = qMin(thumbArea.width(), thumbArea.height());
- const QRect thumbRect(thumbArea.left() + (thumbArea.width() - thumbSize) / 2,
- thumbArea.top() + (thumbArea.height() - thumbSize) / 2,
- thumbSize,
- thumbSize);
- // 标题区域(底部居中)
- const QRect titleRect(borderRect.left(), borderRect.bottom() - 20, borderRect.width(), 20);
- // 获取数据
- const QPixmap thumbnail = qvariant_cast<QPixmap>(index.data(Qt::DecorationRole));
- const QString title = index.data(Qt::DisplayRole).toString();
- const QString className = index.data(Qt::UserRole + 5).toString();
- const bool isActive = index.data(Qt::UserRole + 1).toBool();
- const bool isMinimized = index.data(Qt::UserRole + 2).toBool();
- const QIcon icon = qvariant_cast<QIcon>(index.data(Qt::UserRole + 3));
- const bool isDesktop = index.data(Qt::UserRole + 4).toBool();
- const bool hasFocus = option.state & QStyle::State_HasFocus;
- const bool isHovered = option.state & QStyle::State_MouseOver;
- // 绘制缩略图背景(边框区域内)
- painter->fillRect(borderRect, QColor(30, 30, 30, 150));
- // 居中绘制缩略图(保持1:1比例)
- if (!thumbnail.isNull()) {
- // 创建1:1比例的缩略图
- QPixmap scaledThumb = thumbnail.scaled(thumbSize,
- thumbSize,
- Qt::KeepAspectRatio,
- Qt::SmoothTransformation);
- // 居中绘制
- const int x = thumbRect.left() + (thumbRect.width() - scaledThumb.width()) / 2;
- const int y = thumbRect.top() + (thumbRect.height() - scaledThumb.height()) / 2;
- painter->drawPixmap(x, y, scaledThumb);
- } else {
- // 无缩略图时显示占位符
- painter->setPen(Qt::lightGray);
- painter->drawText(thumbRect, Qt::AlignCenter, "No Preview");
- }
- // 绘制标题(底部居中,不换行)
- painter->setPen(isActive ? Qt::white : Qt::lightGray);
- QFont titleFont = painter->font();
- titleFont.setBold(true);
- titleFont.setPointSize(9);
- painter->setFont(titleFont);
- // 截短标题以适应空间
- QString shortTitle = title;
- QFontMetrics titleMetrics(titleFont);
- shortTitle = titleMetrics.elidedText(title, Qt::ElideRight, titleRect.width());
- painter->drawText(titleRect, Qt::AlignCenter | Qt::TextSingleLine, shortTitle);
- // 绘制边框(焦点时变色)
- QPen borderPen;
- if (isHovered || hasFocus) {
- borderPen = QPen(QColor(0, 255, 0), 3);
- } else if (isActive) {
- borderPen = QPen(QColor(0, 120, 215), 3);
- } else {
- borderPen = QPen(Qt::gray, 1);
- }
- painter->setPen(borderPen);
- painter->setBrush(Qt::NoBrush);
- painter->drawRoundedRect(borderRect, 6, 6);
- // 绘制左上角图标
- if (!icon.isNull()) {
- QPixmap iconPix = icon.pixmap(30, 30);
- painter->drawPixmap(iconRect, iconPix);
- }
- if (isMinimized) {
- // 使用红色矩形作为最小化标识
- painter->setPen(QPen(Qt::red, 2));
- painter->setBrush(Qt::NoBrush);
- // 在右上角区域绘制矩形框
- const int markerSize = 20;
- QRect markerRect(isMinimizedRect.left() + (isMinimizedRect.width() - markerSize) / 2,
- isMinimizedRect.top() + (isMinimizedRect.height() - markerSize) / 2,
- markerSize,
- markerSize);
- painter->drawRect(markerRect);
- // 在矩形框内绘制减号"-"
- painter->setPen(QPen(Qt::red, 3));
- painter->drawLine(markerRect.left() + 5,
- markerRect.center().y(),
- markerRect.right() - 5,
- markerRect.center().y());
- }
- // 如果是桌面项,添加特殊标记
- if (isDesktop) {
- painter->setPen(QPen(Qt::cyan, 2));
- QFont desktopFont("Arial", 8, QFont::Bold);
- painter->setFont(desktopFont);
- painter->drawText(thumbRect.topLeft() + QPoint(10, 15), "Desktop");
- }
- painter->restore();
- }
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
- {
- Q_UNUSED(option);
- Q_UNUSED(index);
- return QSize(160, 120); // 调整大小以适应新布局
- }
- };
- WindowPreviewWidget::WindowPreviewWidget(QWidget *parent)
- : QListView(parent)
- {
- // 设置模型
- model = new QStandardItemModel(this);
- setModel(model);
- // 设置委托
- setItemDelegate(new ThumbnailDelegate(this));
- // 设置视图属性
- setViewMode(QListView::IconMode);
- setResizeMode(QListView::Adjust);
- setGridSize(QSize(180, 140)); // 增加网格大小以容纳间距
- setSpacing(20); // 增加项间间距到20像素
- setDragEnabled(false);
- setSelectionMode(QAbstractItemView::SingleSelection);
- setEditTriggers(QAbstractItemView::NoEditTriggers);
- // 设置焦点策略
- setFocusPolicy(Qt::StrongFocus);
- // 启用滚动
- setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- // 设置定时器
- updateTimer = new QTimer(this);
- connect(updateTimer, &QTimer::timeout, this, &WindowPreviewWidget::updateThumbnails);
- updateTimer->start(1000); // 初始1000ms更新一次
- // 初始更新
- QTimer::singleShot(100, this, &WindowPreviewWidget::updateThumbnails);
- // 启用鼠标跟踪
- setMouseTracking(true);
- viewport()->setMouseTracking(true);
- }
- WindowPreviewWidget::~WindowPreviewWidget()
- {
- // 安全清理资源
- for (auto it = thumbnailCache.begin(); it != thumbnailCache.end(); ++it) {
- if (it.value()) {
- delete it.value();
- }
- }
- thumbnailCache.clear();
- }
- void WindowPreviewWidget::mousePressEvent(QMouseEvent *event)
- {
- QListView::mousePressEvent(event);
- // if (event->button() == Qt::LeftButton) {
- // const QModelIndex index = indexAt(event->pos());
- // if (index.isValid()) {
- // const quintptr hwndPtr = index.data(Qt::UserRole).value<quintptr>();
- // const HWND hwnd = reinterpret_cast<HWND>(hwndPtr);
- // const bool isDesktop = index.data(Qt::UserRole + 4).toBool();
- // const bool isMinimized = index.data(Qt::UserRole + 2).toBool();
- // if (isDesktop) {
- // // 切换到桌面
- // const HWND desktopHwnd = FindWindow(L"Progman", L"Program Manager");
- // if (desktopHwnd) {
- // SetForegroundWindow(desktopHwnd);
- // }
- // } else if (hwnd) {
- // // 激活窗口
- // if (isMinimized) {
- // ShowWindow(hwnd, SW_RESTORE);
- // }
- // // 尝试多次激活窗口(解决某些情况下激活失败的问题)
- // for (int i = 0; i < 3; i++) {
- // if (SetForegroundWindow(hwnd)) {
- // break;
- // }
- // Sleep(50);
- // }
- // }
- // // 设置焦点索引
- // focusedIndex = index;
- // update();
- // }
- // }
- }
- // 添加双击事件处理
- void WindowPreviewWidget::mouseDoubleClickEvent(QMouseEvent *event)
- {
- if (event->button() == Qt::LeftButton) {
- const QModelIndex index = indexAt(event->pos());
- if (index.isValid()) {
- const quintptr hwndPtr = index.data(Qt::UserRole).value<quintptr>();
- const HWND hwnd = reinterpret_cast<HWND>(hwndPtr);
- const bool isDesktop = index.data(Qt::UserRole + 4).toBool();
- const bool isMinimized = index.data(Qt::UserRole + 2).toBool();
- const QString title = index.data(Qt::DisplayRole).toString();
- // if (isDesktop) {
- // // 切换到桌面
- // const HWND desktopHwnd = FindWindow(L"Progman", L"Program Manager");
- // if (desktopHwnd) {
- // SetForegroundWindow(desktopHwnd);
- // }
- // } else if (hwnd) {
- // // 激活窗口
- // if (isMinimized) {
- // ShowWindow(hwnd, SW_RESTORE);
- // }
- // // 尝试多次激活窗口(解决某些情况下激活失败的问题)
- // for (int i = 0; i < 3; i++) {
- // if (SetForegroundWindow(hwnd)) {
- // break;
- // }
- // Sleep(50);
- // }
- // }
- // 设置焦点索引
- focusedIndex = index;
- update();
- // 发出双击信号
- emit windowDoubleClicked(hwndPtr, title);
- }
- }
- // 调用基类实现以确保正确处理事件
- QListView::mouseDoubleClickEvent(event);
- }
- void WindowPreviewWidget::mouseMoveEvent(QMouseEvent *event)
- {
- QListView::mouseMoveEvent(event);
- // 获取当前鼠标位置下的索引
- QModelIndex currentIndex = indexAt(event->pos());
- // 更新悬停状态
- if (hoveredIndex != currentIndex) {
- if (hoveredIndex.isValid()) {
- update(hoveredIndex); // 更新旧的悬停项
- }
- hoveredIndex = currentIndex;
- if (hoveredIndex.isValid()) {
- update(hoveredIndex); // 更新新的悬停项
- }
- }
- }
- void WindowPreviewWidget::leaveEvent(QEvent *event)
- {
- Q_UNUSED(event);
- // 清除悬停状态
- if (hoveredIndex.isValid()) {
- update(hoveredIndex);
- hoveredIndex = QModelIndex();
- }
- }
- void WindowPreviewWidget::enterEvent(QEvent *event)
- {
- Q_UNUSED(event);
- // 不需要额外处理
- }
- void WindowPreviewWidget::focusInEvent(QFocusEvent *event)
- {
- QListView::focusInEvent(event);
- // 当获得焦点时更新视图
- update();
- }
- void WindowPreviewWidget::focusOutEvent(QFocusEvent *event)
- {
- QListView::focusOutEvent(event);
- // 当失去焦点时更新视图
- update();
- }
- void WindowPreviewWidget::updateThumbnails()
- {
- // 重置悬停索引
- if (hoveredIndex.isValid()) {
- update(hoveredIndex);
- hoveredIndex = QModelIndex();
- }
- // 获取活动窗口
- const HWND activeWindow = GetForegroundWindow();
- // 检查是否需要更新
- bool needUpdate = (activeWindow != lastActiveWindow);
- lastActiveWindow = activeWindow;
- // 获取所有窗口
- std::vector<WindowInfo> windows;
- EnumWindows(enumWindowsProc, reinterpret_cast<LPARAM>(&windows));
- // 清理缓存中的无效窗口
- for (auto it = thumbnailCache.begin(); it != thumbnailCache.end();) {
- if (!IsWindow(it.key())) {
- delete it.value();
- it = thumbnailCache.erase(it);
- } else {
- ++it;
- }
- }
- // 创建当前窗口集合(确保只包含有效窗口)
- QSet<HWND> currentWindowSet;
- for (const auto &win : windows) {
- if (IsWindow(win.hwnd)) {
- currentWindowSet.insert(win.hwnd);
- }
- }
- // 创建缓存窗口集合(确保只包含有效窗口)
- QSet<HWND> cachedWindowSet;
- for (auto it = thumbnailCache.begin(); it != thumbnailCache.end(); ++it) {
- if (IsWindow(it.key())) {
- cachedWindowSet.insert(it.key());
- }
- }
- // 如果窗口集合不同,需要完全更新
- if (currentWindowSet != cachedWindowSet) {
- needUpdate = true;
- }
- // 如果没有变化,不需要更新
- if (!needUpdate) {
- return;
- }
- // 清空模型
- model->clear();
- // 添加桌面预览
- addDesktopThumbnail(activeWindow);
- // 更新窗口预览
- for (const auto &win : windows) {
- // 确保窗口有效
- if (IsWindow(win.hwnd)) {
- addWindowThumbnail(win.hwnd, activeWindow);
- }
- }
- // 动态调整更新频率
- updateTimer->setInterval(needFullUpdate() ? 500 : 1500);
- }
- void WindowPreviewWidget::addWindowThumbnail(HWND hwnd, HWND activeWindow)
- {
- // 跳过某些系统窗口
- if (hwnd == (HWND) effectiveWinId())
- return;
- // 确保窗口有效
- if (!IsWindow(hwnd)) {
- return;
- }
- // 获取窗口标题
- std::wstring title;
- wchar_t titleBuffer[256] = {0};
- GetWindowTextW(hwnd, titleBuffer, 256);
- title = titleBuffer;
- // 获取窗口类名
- std::wstring className;
- wchar_t classBuffer[256] = {0};
- GetClassNameW(hwnd, classBuffer, 256);
- className = classBuffer;
- // 检查窗口状态
- const bool isMinimized = IsIconic(hwnd);
- const bool isActive = (activeWindow == hwnd);
- // 获取窗口图标
- QIcon icon = getWindowIcon(hwnd);
- // 获取窗口预览
- QPixmap *thumbnail = nullptr;
- if (thumbnailCache.contains(hwnd) && !needFullUpdate()) {
- thumbnail = thumbnailCache[hwnd];
- } else {
- thumbnail = captureWindow(hwnd);
- if (thumbnail) {
- thumbnailCache[hwnd] = thumbnail;
- }
- }
- // 创建列表项
- QStandardItem *item = new QStandardItem;
- if (thumbnail) {
- item->setData(*thumbnail, Qt::DecorationRole);
- }
- item->setData(QString::fromWCharArray(title.c_str()), Qt::DisplayRole);
- item->setData(reinterpret_cast<quintptr>(hwnd), Qt::UserRole); // 使用quintptr存储句柄
- item->setData(isActive, Qt::UserRole + 1);
- item->setData(isMinimized, Qt::UserRole + 2);
- item->setData(icon, Qt::UserRole + 3);
- item->setData(false, Qt::UserRole + 4);
- item->setData(QString::fromWCharArray(className.c_str()), Qt::UserRole + 5);
- model->appendRow(item);
- }
- QPixmap *WindowPreviewWidget::captureWindow(HWND hwnd)
- {
- // 确保窗口有效
- if (!IsWindow(hwnd)) {
- return nullptr;
- }
- // 获取窗口大小
- RECT rect;
- GetWindowRect(hwnd, &rect);
- const int width = rect.right - rect.left;
- const int height = rect.bottom - rect.top;
- if (width <= 0 || height <= 0) {
- return nullptr;
- }
- // 创建内存DC
- HDC hdcScreen = GetDC(NULL);
- HDC hdcMem = CreateCompatibleDC(hdcScreen);
- HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, width, height);
- SelectObject(hdcMem, hbm);
- // 尝试两种捕获方法
- bool captureSuccess = false;
- // 处理最小化窗口
- bool wasMinimized = IsIconic(hwnd);
- if (wasMinimized) {
- // 临时恢复窗口位置
- // WINDOWPLACEMENT wp;
- // wp.length = sizeof(WINDOWPLACEMENT);
- // GetWindowPlacement(hwnd, &wp);
- // // 移动窗口到屏幕外
- // SetWindowPos(hwnd,
- // NULL,
- // -width - 10,
- // -height - 10,
- // width,
- // height,
- // SWP_NOZORDER | SWP_SHOWWINDOW);
- // ShowWindow(hwnd, SW_RESTORE);
- // 方法2: 使用PrintWindow (适用于最小化窗口)
- if (!captureSuccess) {
- if (PrintWindow(hwnd, hdcMem, PW_RENDERFULLCONTENT)) {
- captureSuccess = true;
- }
- }
- }
- if (!captureSuccess) {
- // 方法1: 使用BitBlt (最快)
- if (BitBlt(hdcMem, 0, 0, width, height, GetWindowDC(hwnd), 0, 0, SRCCOPY)) {
- captureSuccess = true;
- }
- }
- // 恢复最小化窗口状态
- if (wasMinimized) {
- ShowWindow(hwnd, SW_MINIMIZE);
- }
- // 转换为QPixmap
- QImage image(width, height, QImage::Format_ARGB32);
- BITMAPINFO bmi = {0};
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = width;
- bmi.bmiHeader.biHeight = -height; // 从上到下
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- if (captureSuccess) {
- GetDIBits(hdcMem, hbm, 0, height, image.bits(), &bmi, DIB_RGB_COLORS);
- } else {
- // 创建纯色背景作为回退
- image.fill(QColor(60, 60, 60).rgb());
- QPainter painter(&image);
- painter.setPen(Qt::white);
- painter.drawText(image.rect(), Qt::AlignCenter, "Capture Failed");
- }
- QPixmap *pixmap = new QPixmap(QPixmap::fromImage(image));
- // 缩放缩略图
- *pixmap = pixmap->scaled(thumbnailSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
- // 清理资源
- DeleteObject(hbm);
- DeleteDC(hdcMem);
- ReleaseDC(NULL, hdcScreen);
- return pixmap;
- }
- void WindowPreviewWidget::addDesktopThumbnail(HWND activeWindow)
- {
- // 使用缓存
- static QPixmap desktopThumbnail;
- if (desktopThumbnail.isNull() || needFullUpdate()) {
- // 捕获桌面
- QScreen *screen = QApplication::primaryScreen();
- desktopThumbnail = screen->grabWindow(0);
- }
- // 创建桌面项
- QStandardItem *item = new QStandardItem;
- item->setData(desktopThumbnail.scaled(thumbnailSize,
- Qt::KeepAspectRatio,
- Qt::SmoothTransformation),
- Qt::DecorationRole);
- item->setData("Desktop", Qt::DisplayRole);
- item->setData(quintptr(0), Qt::UserRole); // 桌面项使用0作为句柄
- item->setData((activeWindow == GetDesktopWindow()), Qt::UserRole + 1);
- item->setData(false, Qt::UserRole + 2);
- item->setData(QIcon(), Qt::UserRole + 3); // 桌面不需要图标
- item->setData(true, Qt::UserRole + 4);
- item->setData("Desktop", Qt::UserRole + 5);
- model->appendRow(item);
- }
- QIcon WindowPreviewWidget::getWindowIcon(HWND hwnd)
- {
- // 确保窗口有效
- if (!IsWindow(hwnd)) {
- return QIcon();
- }
- HICON hIcon = (HICON) SendMessage(hwnd, WM_GETICON, ICON_BIG, 0);
- if (!hIcon) {
- hIcon = (HICON) GetClassLongPtr(hwnd, GCLP_HICON);
- }
- if (!hIcon) {
- hIcon = LoadIcon(NULL, IDI_APPLICATION);
- }
- if (hIcon) {
- QIcon icon = QIcon(QtWin::fromHICON(hIcon));
- DestroyIcon(hIcon);
- return icon;
- }
- return QIcon();
- }
- bool WindowPreviewWidget::needFullUpdate() const
- {
- // 每5次更新做一次完全更新
- static int counter = 0;
- return (++counter % 5) == 0;
- }
- // int main(int argc, char *argv[])
- // {
- // QApplication app(argc, argv);
- // QWidget mainWidget;
- // QVBoxLayout *layout = new QVBoxLayout(&mainWidget);
- // layout->setContentsMargins(0, 0, 0, 0);
- // // 设置半透明背景
- // mainWidget.setAttribute(Qt::WA_TranslucentBackground);
- // // mainWidget.setStyleSheet("background: rgba(0, 0, 0, 150);");
- // WindowPreviewWidget *previewWidget = new WindowPreviewWidget;
- // layout->addWidget(previewWidget);
- // // 添加信息标签
- // QLabel *infoLabel = new QLabel("Double-click a window to see its handle");
- // infoLabel->setAlignment(Qt::AlignCenter);
- // infoLabel->setStyleSheet("color: white; font-weight: bold; background: rgba(0, 0, 0, 100);");
- // layout->addWidget(infoLabel);
- // // 连接双击信号
- // QObject::connect(previewWidget,
- // &WindowPreviewWidget::windowDoubleClicked,
- // [infoLabel](quintptr hwnd, const QString &title) {
- // QString info = QString("Double-clicked window: HWND=0x%1, Title=\"%2\"")
- // .arg(hwnd, 0, 16) // 以十六进制显示句柄
- // .arg(title);
- // infoLabel->setText(info);
- // });
- // mainWidget.setWindowTitle("Window Preview");
- // mainWidget.resize(900, 700);
- // mainWidget.show();
- // return app.exec();
- // }
- // #include "main.moc"
|