Used the native window on windows

This commit is contained in:
dreamsourcelabTAI 2024-02-21 18:06:47 +08:00
parent decde39462
commit a7754ab2a3
11 changed files with 1389 additions and 677 deletions

View File

@ -237,9 +237,9 @@ bool bHighScale = true;
{
pv::MainFrame w;
control->Start();
w.show();
w.readSettings();
w.show_doc(); //to show the dailog for open help document
w.ShowFormInit();
w.ShowHelpDocAsync(); //to show the dailog for open help document
ret = a.exec(); //Run the application
control->Stop();

View File

@ -1,196 +1,196 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dsdialog.h"
#include "shadow.h"
#include <QObject>
#include <QEvent>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QAbstractButton>
#include "../dsvdef.h"
#include "../config/appconfig.h"
#include "../ui/fn.h"
namespace pv {
namespace dialogs {
DSDialog::DSDialog() :
DSDialog(NULL, false, false)
{
}
DSDialog::DSDialog(QWidget *parent):
DSDialog(parent, false, false)
{
}
DSDialog::DSDialog(QWidget *parent, bool hasClose):
DSDialog(parent, hasClose, false)
{
}
DSDialog::DSDialog(QWidget *parent, bool hasClose, bool bBaseButton) :
QDialog(parent),
m_bBaseButton(bBaseButton)
{
(void)parent;
_base_layout = NULL;
_main_layout = NULL;
_main_widget = NULL;
_titlebar = NULL;
_shadow = NULL;
_base_button = NULL;
_titleSpaceLine = NULL;
m_callback = NULL;
_clickYes = false;
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
setAttribute(Qt::WA_TranslucentBackground);
build_base(hasClose);
}
DSDialog::~DSDialog()
{
DESTROY_QT_OBJECT(_base_layout);
DESTROY_QT_OBJECT(_main_layout);
DESTROY_QT_OBJECT(_main_widget);
DESTROY_QT_OBJECT(_titlebar);
DESTROY_QT_OBJECT(_shadow);
DESTROY_QT_OBJECT(_base_button);
}
void DSDialog::accept()
{
_clickYes = true;
if (m_callback){
m_callback->OnDlgResult(true);
}
QDialog::accept();
}
void DSDialog::reject()
{
_clickYes = false;
if (m_callback){
m_callback->OnDlgResult(false);
}
QDialog::reject();
}
void DSDialog::setTitle(QString title)
{
if (_titlebar){
_titlebar->setTitle(title);
}
}
void DSDialog::reload()
{
show();
}
int DSDialog::exec()
{
//ok,cancel
if (m_bBaseButton){
_base_button = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,Qt::Horizontal, this);
_main_layout->addWidget(_base_button);//, 5, 1, 1, 1, Qt::AlignHCenter | Qt::AlignBottom);
//_main_layout->addWidget(_base_button,0, Qt::AlignHCenter | Qt::AlignBottom);
connect(_base_button, SIGNAL(rejected()), this, SLOT(reject()));
connect(_base_button, SIGNAL(accepted()), this, SLOT(accept()));
}
update_font();
return QDialog::exec();
}
void DSDialog::SetTitleSpace(int h)
{
if (_titleSpaceLine != NULL){
if (h > 0){
_titleSpaceLine->setFixedHeight(h);
_titleSpaceLine->setVisible(true);
}
else{
_titleSpaceLine->setVisible(false);
}
}
}
void DSDialog::build_base(bool hasClose)
{
_main_widget = new QWidget(this);
_main_layout = new QVBoxLayout(_main_widget);
_main_widget->setLayout(_main_layout);
_shadow = new Shadow(this);
_shadow->setBlurRadius(10.0);
_shadow->setDistance(3.0);
_shadow->setColor(QColor(0, 0, 0, 80));
_main_widget->setAutoFillBackground(true);
this->setGraphicsEffect(_shadow);
_titlebar = new toolbars::TitleBar(false, this, hasClose);
_main_layout->addWidget(_titlebar);
_titleSpaceLine = new QWidget(this);
_titleSpaceLine->setFixedHeight(15);
_main_layout->addWidget(_titleSpaceLine);
_base_layout = new QVBoxLayout(this);
_base_layout->addWidget(_main_widget);
setLayout(_base_layout);
_main_layout->setAlignment(Qt::AlignCenter | Qt::AlignTop);
_main_layout->setContentsMargins(10,5,10,10);
}
void DSDialog::update_font()
{
QFont font = this->font();
font.setPointSizeF(AppConfig::Instance().appOptions.fontSize);
ui::set_form_font(this, font);
if (_titlebar != NULL){
_titlebar->update_font();
}
}
void DSDialog::show()
{
update_font();
QWidget::show();
}
} // namespace dialogs
} // namespace pv
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dsdialog.h"
#include "shadow.h"
#include <QObject>
#include <QEvent>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QAbstractButton>
#include "../dsvdef.h"
#include "../config/appconfig.h"
#include "../ui/fn.h"
namespace pv {
namespace dialogs {
DSDialog::DSDialog() :
DSDialog(NULL, false, false)
{
}
DSDialog::DSDialog(QWidget *parent):
DSDialog(parent, false, false)
{
}
DSDialog::DSDialog(QWidget *parent, bool hasClose):
DSDialog(parent, hasClose, false)
{
}
DSDialog::DSDialog(QWidget *parent, bool hasClose, bool bBaseButton) :
QDialog(parent),
m_bBaseButton(bBaseButton)
{
(void)parent;
_base_layout = NULL;
_main_layout = NULL;
_main_widget = NULL;
_titlebar = NULL;
_shadow = NULL;
_base_button = NULL;
_titleSpaceLine = NULL;
m_callback = NULL;
_clickYes = false;
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
setAttribute(Qt::WA_TranslucentBackground);
build_base(hasClose);
}
DSDialog::~DSDialog()
{
DESTROY_QT_OBJECT(_base_layout);
DESTROY_QT_OBJECT(_main_layout);
DESTROY_QT_OBJECT(_main_widget);
DESTROY_QT_OBJECT(_titlebar);
DESTROY_QT_OBJECT(_shadow);
DESTROY_QT_OBJECT(_base_button);
}
void DSDialog::accept()
{
_clickYes = true;
if (m_callback){
m_callback->OnDlgResult(true);
}
QDialog::accept();
}
void DSDialog::reject()
{
_clickYes = false;
if (m_callback){
m_callback->OnDlgResult(false);
}
QDialog::reject();
}
void DSDialog::setTitle(QString title)
{
if (_titlebar){
_titlebar->setTitle(title);
}
}
void DSDialog::reload()
{
show();
}
int DSDialog::exec()
{
//ok,cancel
if (m_bBaseButton){
_base_button = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,Qt::Horizontal, this);
_main_layout->addWidget(_base_button);//, 5, 1, 1, 1, Qt::AlignHCenter | Qt::AlignBottom);
//_main_layout->addWidget(_base_button,0, Qt::AlignHCenter | Qt::AlignBottom);
connect(_base_button, SIGNAL(rejected()), this, SLOT(reject()));
connect(_base_button, SIGNAL(accepted()), this, SLOT(accept()));
}
update_font();
return QDialog::exec();
}
void DSDialog::SetTitleSpace(int h)
{
if (_titleSpaceLine != NULL){
if (h > 0){
_titleSpaceLine->setFixedHeight(h);
_titleSpaceLine->setVisible(true);
}
else{
_titleSpaceLine->setVisible(false);
}
}
}
void DSDialog::build_base(bool hasClose)
{
_main_widget = new QWidget(this);
_main_layout = new QVBoxLayout(_main_widget);
_main_widget->setLayout(_main_layout);
_shadow = new Shadow(this);
_shadow->setBlurRadius(10.0);
_shadow->setDistance(3.0);
_shadow->setColor(QColor(0, 0, 0, 80));
_main_widget->setAutoFillBackground(true);
this->setGraphicsEffect(_shadow);
_titlebar = new toolbars::TitleBar(false, this, NULL,hasClose);
_main_layout->addWidget(_titlebar);
_titleSpaceLine = new QWidget(this);
_titleSpaceLine->setFixedHeight(15);
_main_layout->addWidget(_titleSpaceLine);
_base_layout = new QVBoxLayout(this);
_base_layout->addWidget(_main_widget);
setLayout(_base_layout);
_main_layout->setAlignment(Qt::AlignCenter | Qt::AlignTop);
_main_layout->setContentsMargins(10,5,10,10);
}
void DSDialog::update_font()
{
QFont font = this->font();
font.setPointSizeF(AppConfig::Instance().appOptions.fontSize);
ui::set_form_font(this, font);
if (_titlebar != NULL){
_titlebar->update_font();
}
}
void DSDialog::show()
{
update_font();
QWidget::show();
}
} // namespace dialogs
} // namespace pv

View File

@ -1,145 +1,145 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dsmessagebox.h"
#include "shadow.h"
#include <QObject>
#include <QEvent>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QAbstractButton>
#include "../dsvdef.h"
#include "../ui/langresource.h"
#include "../config/appconfig.h"
#include "../ui/fn.h"
namespace pv {
namespace dialogs {
DSMessageBox::DSMessageBox(QWidget *parent,const QString title) :
QDialog(parent)
{
(void)parent;
_layout = NULL;
_main_widget = NULL;
_msg = NULL;
_titlebar = NULL;
_shadow = NULL;
_main_layout = NULL;
_bClickYes = false;
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
setAttribute(Qt::WA_TranslucentBackground);
_main_widget = new QWidget(this);
_main_layout = new QVBoxLayout(_main_widget);
_main_widget->setLayout(_main_layout);
_shadow = new Shadow(this);
_msg = new QMessageBox(this);
_titlebar = new toolbars::TitleBar(false, this);
_layout = new QVBoxLayout(this);
_shadow->setBlurRadius(10.0);
_shadow->setDistance(3.0);
_shadow->setColor(QColor(0, 0, 0, 80));
_main_widget->setAutoFillBackground(true);
this->setGraphicsEffect(_shadow);
_msg->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
if (!title.isEmpty()){
_titlebar->setTitle(title);
}
else{
_titlebar->setTitle(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_MESSAGE), "Message"));
}
_main_layout->addWidget(_titlebar);
_main_layout->addWidget(_msg);
_layout->addWidget(_main_widget);
setLayout(_layout);
connect(_msg, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(on_button(QAbstractButton*)));
}
DSMessageBox::~DSMessageBox()
{
DESTROY_QT_OBJECT(_layout);
DESTROY_QT_OBJECT(_main_widget);
DESTROY_QT_OBJECT(_msg);
DESTROY_QT_OBJECT(_titlebar);
DESTROY_QT_OBJECT(_shadow);
DESTROY_QT_OBJECT(_main_layout);
}
void DSMessageBox::accept()
{
using namespace Qt;
QDialog::accept();
}
void DSMessageBox::reject()
{
using namespace Qt;
QDialog::reject();
}
QMessageBox* DSMessageBox::mBox()
{
return _msg;
}
void DSMessageBox::on_button(QAbstractButton *btn)
{
QMessageBox::ButtonRole role = _msg->buttonRole(btn);
if (role == QMessageBox::AcceptRole || role == QMessageBox::YesRole){
_bClickYes = true;
accept();
}
else
reject();
}
int DSMessageBox::exec()
{
QFont font = this->font();
font.setPointSizeF(AppConfig::Instance().appOptions.fontSize);
ui::set_form_font(this, font);
if (_titlebar != NULL){
_titlebar->update_font();
}
return QDialog::exec();
}
} // namespace dialogs
} // namespace pv
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dsmessagebox.h"
#include "shadow.h"
#include <QObject>
#include <QEvent>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QAbstractButton>
#include "../dsvdef.h"
#include "../ui/langresource.h"
#include "../config/appconfig.h"
#include "../ui/fn.h"
namespace pv {
namespace dialogs {
DSMessageBox::DSMessageBox(QWidget *parent,const QString title) :
QDialog(parent)
{
(void)parent;
_layout = NULL;
_main_widget = NULL;
_msg = NULL;
_titlebar = NULL;
_shadow = NULL;
_main_layout = NULL;
_bClickYes = false;
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
setAttribute(Qt::WA_TranslucentBackground);
_main_widget = new QWidget(this);
_main_layout = new QVBoxLayout(_main_widget);
_main_widget->setLayout(_main_layout);
_shadow = new Shadow(this);
_msg = new QMessageBox(this);
_titlebar = new toolbars::TitleBar(false, this, NULL, false);
_layout = new QVBoxLayout(this);
_shadow->setBlurRadius(10.0);
_shadow->setDistance(3.0);
_shadow->setColor(QColor(0, 0, 0, 80));
_main_widget->setAutoFillBackground(true);
this->setGraphicsEffect(_shadow);
_msg->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
if (!title.isEmpty()){
_titlebar->setTitle(title);
}
else{
_titlebar->setTitle(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_MESSAGE), "Message"));
}
_main_layout->addWidget(_titlebar);
_main_layout->addWidget(_msg);
_layout->addWidget(_main_widget);
setLayout(_layout);
connect(_msg, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(on_button(QAbstractButton*)));
}
DSMessageBox::~DSMessageBox()
{
DESTROY_QT_OBJECT(_layout);
DESTROY_QT_OBJECT(_main_widget);
DESTROY_QT_OBJECT(_msg);
DESTROY_QT_OBJECT(_titlebar);
DESTROY_QT_OBJECT(_shadow);
DESTROY_QT_OBJECT(_main_layout);
}
void DSMessageBox::accept()
{
using namespace Qt;
QDialog::accept();
}
void DSMessageBox::reject()
{
using namespace Qt;
QDialog::reject();
}
QMessageBox* DSMessageBox::mBox()
{
return _msg;
}
void DSMessageBox::on_button(QAbstractButton *btn)
{
QMessageBox::ButtonRole role = _msg->buttonRole(btn);
if (role == QMessageBox::AcceptRole || role == QMessageBox::YesRole){
_bClickYes = true;
accept();
}
else
reject();
}
int DSMessageBox::exec()
{
QFont font = this->font();
font.setPointSizeF(AppConfig::Instance().appOptions.fontSize);
ui::set_form_font(this, font);
if (_titlebar != NULL){
_titlebar->update_font();
}
return QDialog::exec();
}
} // namespace dialogs
} // namespace pv

File diff suppressed because it is too large Load Diff

View File

@ -28,25 +28,45 @@
#include <QFrame>
#include <QGridLayout>
#include <QTimer>
#include <QRect>
#ifdef _WIN32
#include <QWinTaskbarButton>
#include <QWinTaskbarProgress>
#endif
#include "toolbars/titlebar.h"
namespace pv {
class MainWindow;
namespace toolbars {
class TitleBar;
}
class WinNativeWidget;
namespace dialogs {
class DSMessageBox;
class DSDialog;
}
struct Point
{
int x;
int y;
};
class MainFrame : public QFrame
struct FormRegion{
int x;
int y;
int w;
int h;
};
struct FormInitInfo
{
FormRegion r;
bool isMaxSize;
};
class MainFrame : public QFrame, public ITitleParent
{
Q_OBJECT
@ -67,16 +87,20 @@ public:
public:
MainFrame();
void readSettings();
void ShowFormInit();
void ShowHelpDocAsync();
void PrintRegionProc();
void PrintRegion();
protected:
void resizeEvent(QResizeEvent *event);
void closeEvent(QCloseEvent *event);
bool eventFilter(QObject *object, QEvent *event);
#ifdef _WIN32
#ifdef _WIN32
void showEvent(QShowEvent *event);
#endif
#endif
void changeEvent(QEvent *event) override;
@ -88,7 +112,7 @@ public slots:
void showNormal();
void showMaximized();
void showMinimized();
void moveToNormal();
void moveToWinNaitiveNormal();
private:
void hide_border();
@ -96,6 +120,19 @@ private:
void writeSettings();
void saveNormalRegion();
void ReadSettings();
void AttachNativeWindow();
//ITitleParent
void MoveWindow(int x, int y) override;
QPoint GetParentPos() override;
bool ParentIsMaxsized() override;
void MoveBegin() override;
void MoveEnd() override;
void SetFormRegion(int x, int y, int w, int h);
QRect GetFormRegion();
private:
toolbars::TitleBar *_titleBar;
MainWindow *_mainWindow;
@ -110,8 +147,7 @@ private:
widgets::Border *_bottom_left;
widgets::Border *_bottom_right;
bool _bDraging;
QRect _dragStartGeometry;
bool _bDraging;
int _hit_border;
QTimer _timer;
bool _freezing;
@ -122,10 +158,15 @@ private:
#endif
bool _is_native_title;
bool _is_resize_ready;
int _move_event_count;
int _resize_event_count;
bool _is_resize_reset_timer;
bool _is_resize_ready;
WinNativeWidget *_parentNativeWidget;
FormInitInfo _initWndInfo;
FormRegion _normalRegion;
bool _is_max_status;
QPoint _clickPos;
QRect _dragStartRegion;
QRect _move_screen_region;
};
} // namespace pv

View File

@ -186,6 +186,7 @@ namespace pv
_view = new pv::view::View(_session, _sampling_bar, this);
_vertical_layout->addWidget(_view);
setIconSize(QSize(40, 40));
addToolBar(_sampling_bar);
addToolBar(_trig_bar);
@ -255,6 +256,7 @@ namespace pv
_sampling_bar->set_view(_view);
// Add the font form
AppControl::Instance()->add_font_form(_protocol_widget);
AppControl::Instance()->add_font_form(_dso_trigger_widget);
@ -1425,10 +1427,7 @@ namespace pv
qss.open(QFile::ReadOnly | QFile::Text);
qApp->setStyleSheet(qss.readAll());
qss.close();
#ifdef _WIN32
setDark_Titlebar(reinterpret_cast<HWND>(_frame->winId()), style == THEME_STYLE_DARK);
#endif
data_updated();
}
@ -2195,29 +2194,5 @@ namespace pv
_view->update_all_trace_postion();
}
#ifdef _WIN32
void MainWindow::setDark_Titlebar(HWND hwnd, bool isDarkStyle)
{
HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
HMODULE hUser32 = GetModuleHandleW(L"user32.dll");
fnAllowDarkModeForWindow AllowDarkModeForWindow
= reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));
fnSetPreferredAppMode SetPreferredAppMode
= reinterpret_cast<fnSetPreferredAppMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135)));
fnSetWindowCompositionAttribute SetWindowCompositionAttribute
= reinterpret_cast<fnSetWindowCompositionAttribute>(GetProcAddress(hUser32, "SetWindowCompositionAttribute"));
SetPreferredAppMode(AllowDark);
BOOL dark = isDarkStyle;
AllowDarkModeForWindow(hwnd, dark);
WINDOWCOMPOSITIONATTRIBDATA data = {
WCA_USEDARKMODECOLORS,
&dark,
sizeof(dark)
};
SetWindowCompositionAttribute(hwnd, &data);
}
#endif
} // namespace pv

View File

@ -34,61 +34,6 @@
#include <chrono>
#include "dstimer.h"
#ifdef _WIN32
#include <Windows.h>
#include <dwmapi.h>
#pragma comment (lib, "Dwmapi.lib")
enum PreferredAppMode {
Default,
AllowDark,
ForceDark,
ForceLight,
Max
};
enum WINDOWCOMPOSITIONATTRIB {
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_USEDARKMODECOLORS = 26,
WCA_LAST = 27
};
struct WINDOWCOMPOSITIONATTRIBDATA {
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
};
using fnAllowDarkModeForWindow = BOOL (WINAPI *)(HWND hWnd, BOOL allow);
using fnSetPreferredAppMode = PreferredAppMode (WINAPI *)(PreferredAppMode appMode);
using fnSetWindowCompositionAttribute = BOOL (WINAPI *)(HWND hwnd, WINDOWCOMPOSITIONATTRIBDATA *);
#endif
class QAction;
class QMenuBar;
class QMenu;
@ -213,10 +158,7 @@ private:
void check_config_file_version();
void load_demo_decoder_config(QString optname);
#ifdef _WIN32
static void setDark_Titlebar(HWND hwnd, bool isDarkStyle);
#endif
private:
//ISessionCallback
void session_error() override;

View File

@ -20,7 +20,6 @@
*/
#include "titlebar.h"
#include <QStyle>
#include <QLabel>
#include <QToolButton>
@ -31,6 +30,12 @@
#include <QPainter>
#include <QStyleOption>
#include <assert.h>
#include <QTimer>
#ifdef _WIN32
#include <windows.h>
#endif
#include "../config/appconfig.h"
#include "../appcontrol.h"
#include "../dsvdef.h"
@ -39,18 +44,21 @@
namespace pv {
namespace toolbars {
TitleBar::TitleBar(bool top, QWidget *parent, bool hasClose) :
TitleBar::TitleBar(bool top, QWidget *parent, ITitleParent *titleParent, bool hasClose) :
QWidget(parent)
{
_minimizeButton = NULL;
_maximizeButton = NULL;
_closeButton = NULL;
_moving = false;
_is_draging = false;
_parent = parent;
_isTop = top;
_hasClose = hasClose;
_title = NULL;
_is_native = false;
_titleParent = titleParent;
_is_done_moved = false;
assert(parent);
@ -114,7 +122,7 @@ void TitleBar::reStyle()
if (_isTop) {
_minimizeButton->setIcon(QIcon(iconPath+"/minimize.svg"));
if (parentWidget()->isMaximized())
if (ParentIsMaxsized())
_maximizeButton->setIcon(QIcon(iconPath+"/restore.svg"));
else
_maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg"));
@ -123,6 +131,16 @@ void TitleBar::reStyle()
_closeButton->setIcon(QIcon(iconPath+"/close.svg"));
}
bool TitleBar::ParentIsMaxsized()
{
if (_titleParent != NULL){
return _titleParent->ParentIsMaxsized();
}
else{
return parentWidget()->isMaximized();
}
}
void TitleBar::paintEvent(QPaintEvent *event)
{
//draw logo icon
@ -182,7 +200,7 @@ QString TitleBar::title()
void TitleBar::showMaxRestore()
{
QString iconPath = GetIconPath();
if (parentWidget()->isMaximized()) {
if (ParentIsMaxsized()) {
_maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg"));
normalShow();
} else {
@ -203,7 +221,9 @@ void TitleBar::setRestoreButton(bool max)
void TitleBar::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton && !parentWidget()->isMaximized())
bool ableMove = !ParentIsMaxsized();
if(event->button() == Qt::LeftButton && ableMove)
{
int x = event->pos().x();
int y = event->pos().y();
@ -212,9 +232,25 @@ void TitleBar::mousePressEvent(QMouseEvent* event)
bool bClick = (x >= 6 && y >= 5 && x <= width() - 6); //top window need resize hit check
if (!bTopWidow || bClick ){
_moving = true;
_is_draging = true;
#ifdef _WIN32
POINT p;
GetCursorPos(&p);
_clickPos.setX(p.x);
_clickPos.setY(p.y);
#else
_clickPos = event->globalPos();
_oldPos = _parent->pos();
#endif
if (_titleParent != NULL){
_oldPos = _titleParent->GetParentPos();
}
else{
_oldPos = _parent->pos();
}
_is_done_moved = false;
event->accept();
return;
}
@ -224,28 +260,74 @@ void TitleBar::mousePressEvent(QMouseEvent* event)
void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
if(_moving){
int x = _oldPos.x() + (event->globalPos().x() - _clickPos.x());
int y = _oldPos.y() + (event->globalPos().y() - _clickPos.y());
_parent->move(x, y);
event->accept();
return;
if(_is_draging){
int datX = 0;
int datY = 0;
#ifdef _WIN32
POINT p;
GetCursorPos(&p);
int k = window()->devicePixelRatio();
datX = (p.x - _clickPos.x()) / k;
datY = (p.y - _clickPos.y()) / k;
#else
datX = (event->globalPos().x() - _clickPos.x());
datY = (event->globalPos().y() - _clickPos.y());
#endif
int x = _oldPos.x() + datX;
int y = _oldPos.y() + datY;
if (!_moving){
if (ABS_VAL(datX) >= 2 || ABS_VAL(datY) >= 2){
_moving = true;
}
else{
return;
}
}
if (_titleParent != NULL){
if (!_is_done_moved){
_is_done_moved = true;
_titleParent->MoveBegin();
}
_titleParent->MoveWindow(x, y);
}
else{
_parent->move(x, y);
}
event->accept();
return;
}
QWidget::mouseMoveEvent(event);
}
void TitleBar::mouseReleaseEvent(QMouseEvent* event)
{
if (_moving && _titleParent != NULL){
_titleParent->MoveEnd();
}
_moving = false;
_is_draging = false;
QWidget::mouseReleaseEvent(event);
}
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
if (_isTop){
showMaxRestore();
}
QWidget::mouseDoubleClickEvent(event);
{
QWidget::mouseDoubleClickEvent(event);
if (_isTop){
QTimer::singleShot(200, this, [this](){
showMaxRestore();
});
}
}
void TitleBar::update_font()

View File

@ -30,6 +30,17 @@ class QHBoxLayout;
class QLabel;
namespace pv {
class ITitleParent
{
public:
virtual void MoveWindow(int x, int y)=0;
virtual QPoint GetParentPos()=0;
virtual bool ParentIsMaxsized()=0;
virtual void MoveBegin()=0;
virtual void MoveEnd()=0;
};
namespace toolbars {
class TitleBar : public QWidget, public IFontForm
@ -37,7 +48,7 @@ class TitleBar : public QWidget, public IFontForm
Q_OBJECT
public:
TitleBar(bool top, QWidget *parent, bool hasClose = false);
TitleBar(bool top, QWidget *parent, ITitleParent *titleParent, bool hasClose);
~TitleBar();
void setTitle(QString title);
@ -54,6 +65,8 @@ private:
void changeEvent(QEvent *event);
void reStyle();
bool ParentIsMaxsized();
signals:
void normalShow();
void maximizedShow();
@ -77,12 +90,15 @@ protected:
QLabel *_title;
bool _moving;
bool _is_draging;
bool _isTop;
bool _hasClose;
QPoint _clickPos;
QPoint _oldPos;
QWidget *_parent;
bool _is_native;
ITitleParent *_titleParent;
bool _is_done_moved;
};
} // namespace toolbars

View File

@ -0,0 +1,232 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2024 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "winnativewidget.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <dwmapi.h>
#include <assert.h>
#include <QString>
#include "log.h"
#include "../config.h"
#define NAI_WIN_CREATE_STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN
namespace pv {
WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, const int height)
{
_childWindow = nullptr;
childWidget = nullptr;
_hWnd = NULL;
HBRUSH windowBackground = CreateSolidBrush(RGB(255, 255, 255));
HINSTANCE hInstance = GetModuleHandle(nullptr);
WNDCLASSEX wcx = { 0 };
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.hInstance = hInstance;
wcx.lpfnWndProc = WndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.lpszClassName = L"WindowClass";
wcx.hbrBackground = windowBackground;
wcx.hCursor = LoadCursor(hInstance, IDC_ARROW);
RegisterClassEx(&wcx);
if (FAILED(RegisterClassEx(&wcx)))
{
dsv_info("ERROR: can't register window class");
assert(false);
}
QString title = QApplication::applicationName() + " v" + QApplication::applicationVersion();
wchar_t title_string_buffer[50];
int title_len = title.toWCharArray(title_string_buffer);
title_string_buffer[title_len] = 0;
_hWnd = CreateWindow(L"WindowClass", title_string_buffer,
NAI_WIN_CREATE_STYLE, x, y,
width, height, 0, 0, hInstance, nullptr);
if (!_hWnd)
{
dsv_info("ERROR: can't create naitive window");
assert(false);
}
SetWindowLongPtr(_hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
SetWindowPos(_hWnd, NULL, x, y, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
}
WinNativeWidget::~WinNativeWidget()
{
if (_hWnd){
Show(false);
DestroyWindow(_hWnd);
}
}
void WinNativeWidget::SetChildWidget(QWidget *w)
{
childWidget = w;
_childWindow = NULL;
if (w != NULL){
_childWindow = (HWND)w->winId();
}
}
LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WinNativeWidget *self = reinterpret_cast<WinNativeWidget*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (self == NULL)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
switch (message)
{
case WM_SYSCOMMAND:
{
if (wParam == SC_KEYMENU)
{
RECT winrect;
GetWindowRect(hWnd, &winrect);
TrackPopupMenu(GetSystemMenu(hWnd, false), TPM_TOPALIGN | TPM_LEFTALIGN, winrect.left + 5, winrect.top + 5, 0, hWnd, NULL);
break;
}
else
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
case WM_NCCALCSIZE:
{
return 0;
}
case WM_CLOSE:
{
if (self->childWidget != NULL)
{
self->childWidget->close();
return 0;
}
break;
}
case WM_DESTROY:
{
// PostQuitMessage(0);
break;
}
case WM_SIZE:
{
if (self->_childWindow != NULL){
self->ResizeChild(false);
}
break;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void WinNativeWidget::ResizeChild(bool bManual)
{
if (_childWindow != NULL){
RECT rc;
GetClientRect(_hWnd, &rc);
int k = QApplication::desktop()->screen()->devicePixelRatio();
k = childWidget->window()->devicePixelRatio();
int w = rc.right;
int h = rc.bottom;
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(_hWnd, &wp);
if (wp.showCmd == SW_MAXIMIZE) {
w -= 8;
h -= 8;
}
childWidget->adjustSize();
MoveWindow(_childWindow, 0, 0, w , h , 1 );
// dsv_info("resize child, w:%d, h:%d, k1:%d, k2:%d", w / k, h / k, k1, k2);
}
}
void WinNativeWidget::setGeometry(const int x, const int y, const int width, const int height)
{
// dsv_info("set parent window, x:%d, y:%d, w:%d, h:%d", x, y, width, height);
if (_hWnd != NULL){
MoveWindow(_hWnd, x, y, width, height, 1);
}
}
void WinNativeWidget::Show(bool bShow)
{
if (_hWnd){
ShowWindow(_hWnd, bShow ? SW_SHOW : SW_HIDE);
}
}
void WinNativeWidget::Move(int x, int y)
{
RECT rc;
GetClientRect(_hWnd, &rc);
MoveWindow(_hWnd, x, y, rc.right, rc.bottom, 0);
}
void WinNativeWidget::ShowNormal()
{
if (_hWnd){
SendMessage(_hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
}
}
void WinNativeWidget::ShowMax()
{
if (_hWnd){
SendMessage(_hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}
}
void WinNativeWidget::ShowMin()
{
if (_hWnd){
SendMessage(_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
}
}

View File

@ -0,0 +1,69 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2024 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WINNATIVEWINDOW_H
#define WINNATIVEWINDOW_H
#include <Windows.h>
#include <Windowsx.h>
#include <QWidget>
namespace pv {
class WinNativeWidget
{
public:
WinNativeWidget(const int x, const int y, const int width, const int height);
~WinNativeWidget();
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void SetChildWidget(QWidget *w);
void setGeometry(const int x, const int y, const int width, const int height);
inline HWND Handle(){
return _hWnd;
}
void Show(bool bShow);
void Move(int x, int y);
void ShowNormal();
void ShowMax();
void ShowMin();
void ResizeChild(bool bManul);
private:
QWidget* childWidget;
HWND _childWindow;
HWND _hWnd;
};
}
#endif // WINNATIVEWINDOW_H