forked from Public-Mirror/Textractor
Create a new attach dialog window
New dialog window that shows processes with icons in QListView instead of ComboBox.
This commit is contained in:
parent
dd4b8cfbb5
commit
a1d3abb080
@ -10,6 +10,7 @@ add_executable(Textractor WIN32
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
extenwindow.cpp
|
||||
attachtoprocessdialog.cpp
|
||||
host/exception.cpp
|
||||
host/host.cpp
|
||||
host/textthread.cpp
|
||||
|
92
GUI/attachtoprocessdialog.cpp
Normal file
92
GUI/attachtoprocessdialog.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "attachtoprocessdialog.h"
|
||||
#include "ui_attachtoprocessdialog.h"
|
||||
#include "utils/windowshelpers.h"
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
namespace
|
||||
{
|
||||
QString GetNameProcessFromIndex(const QModelIndex &index, const QVector<QPair<QString, HICON>>& data)
|
||||
{
|
||||
const int row = index.row();
|
||||
return data[row].first;
|
||||
}
|
||||
}
|
||||
|
||||
AttachToProcessDialog::AttachToProcessDialog(QWidget *parent) :
|
||||
QDialog(parent, Qt::WindowCloseButtonHint),
|
||||
ui(new Ui::AttachToProcessDialog),
|
||||
model(new QStandardItemModel(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
const QIntValidator* validator = new QIntValidator(0, INT_MAX, this);
|
||||
ui->lineEdit->setValidator(validator);
|
||||
}
|
||||
|
||||
AttachToProcessDialog::~AttachToProcessDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::setLabelText(const QString& text)
|
||||
{
|
||||
ui->label->setText(text);
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::setData(QVector<QPair<QString, HICON>>&& newData)
|
||||
{
|
||||
data = std::move(newData);
|
||||
selectedProcess.clear();
|
||||
std::sort(data.begin(), data.end(), [](const auto& left, const auto& right) {
|
||||
return left.first < right.first;
|
||||
});
|
||||
model->clear();
|
||||
for (const auto& [process, hIcon] : data)
|
||||
{
|
||||
QIcon icon = WindowsHepers::CreateQIconFromHIcon(hIcon);
|
||||
auto* item = new QStandardItem(icon, process);
|
||||
item->setEditable(false);
|
||||
model->appendRow(item);
|
||||
}
|
||||
ui->listView->setModel(model);
|
||||
}
|
||||
|
||||
QString AttachToProcessDialog::getSelectedData()
|
||||
{
|
||||
return selectedProcess.isEmpty() ? ui->lineEdit->text() : selectedProcess;
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::on_buttonBox_accepted()
|
||||
{
|
||||
accept();
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::on_buttonBox_rejected()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::on_listView_doubleClicked(const QModelIndex& index)
|
||||
{
|
||||
selectedProcess = GetNameProcessFromIndex(index, data);
|
||||
accept();
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::on_lineEdit_returnPressed()
|
||||
{
|
||||
selectedProcess = ui->lineEdit->text();
|
||||
accept();
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::on_listView_clicked(const QModelIndex &index)
|
||||
{
|
||||
selectedProcess = GetNameProcessFromIndex(index, data);
|
||||
}
|
||||
|
||||
void AttachToProcessDialog::on_lineEdit_editingFinished()
|
||||
{
|
||||
selectedProcess = ui->lineEdit->text();
|
||||
}
|
51
GUI/attachtoprocessdialog.h
Normal file
51
GUI/attachtoprocessdialog.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef ATTACHTOPROCESSDIALOG_H
|
||||
#define ATTACHTOPROCESSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include <QPair>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QVector>
|
||||
#include <QtWinExtras/QtWin>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class AttachToProcessDialog;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class QStandardItemModel;
|
||||
class QModelIndex;
|
||||
|
||||
class AttachToProcessDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttachToProcessDialog(QWidget *parent = nullptr);
|
||||
void setData(QVector<QPair<QString, HICON>>&& newData);
|
||||
void setLabelText(const QString& text);
|
||||
QString getSelectedData();
|
||||
~AttachToProcessDialog();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
void on_listView_doubleClicked(const QModelIndex &index);
|
||||
|
||||
void on_lineEdit_returnPressed();
|
||||
|
||||
void on_listView_clicked(const QModelIndex &index);
|
||||
|
||||
void on_lineEdit_editingFinished();
|
||||
|
||||
private:
|
||||
Ui::AttachToProcessDialog* ui;
|
||||
QStandardItemModel* model;
|
||||
QString selectedProcess;
|
||||
QVector<QPair<QString, HICON>> data;
|
||||
};
|
||||
|
||||
#endif // ATTACHTOPROCESSDIALOG_H
|
52
GUI/attachtoprocessdialog.ui
Normal file
52
GUI/attachtoprocessdialog.ui
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AttachToProcessDialog</class>
|
||||
<widget class="QWidget" name="AttachToProcessDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>813</width>
|
||||
<height>426</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="placeholderText">
|
||||
<string>PID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="listView"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -5,6 +5,9 @@
|
||||
#include "extenwindow.h"
|
||||
#include "host/host.h"
|
||||
#include "host/hookcode.h"
|
||||
#include "attachtoprocessdialog.h"
|
||||
#include "utils/windowshelpers.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
#include <process.h>
|
||||
#include <QRegularExpression>
|
||||
@ -14,6 +17,7 @@
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QFontDialog>
|
||||
#include <QHash>
|
||||
|
||||
extern const char* ATTACH;
|
||||
extern const char* LAUNCH;
|
||||
@ -79,6 +83,7 @@ namespace
|
||||
Ui::MainWindow ui;
|
||||
std::atomic<DWORD> selectedProcessId = 0;
|
||||
ExtenWindow* extenWindow = nullptr;
|
||||
AttachToProcessDialog* attachDialog = nullptr;
|
||||
std::unordered_set<DWORD> alreadyAttached;
|
||||
bool autoAttach = false, autoAttachSavedOnly = true;
|
||||
bool showSystemProcesses = false;
|
||||
@ -152,17 +157,51 @@ namespace
|
||||
}
|
||||
|
||||
void AttachProcess()
|
||||
{
|
||||
QMultiHash<QString, DWORD> allProcesses;
|
||||
for (auto [processId, processName] : GetAllProcesses())
|
||||
{
|
||||
auto processes = GetAllProcesses();
|
||||
QMultiHash<QString, DWORD> processesMap;
|
||||
QVector<QPair<QString, HICON>> dialogData;
|
||||
dialogData.reserve(processes.size());
|
||||
for (auto [processId, processName] : processes)
|
||||
{
|
||||
if (processName && (showSystemProcesses || processName->find(L":\\Windows\\") == std::string::npos))
|
||||
allProcesses.insert(QFileInfo(S(processName.value())).fileName(), processId);
|
||||
{
|
||||
const auto& value = processName.value();
|
||||
const QFileInfo& fileInfo = QFileInfo(S(value));
|
||||
const QString& fileName = fileInfo.fileName();
|
||||
if (!processesMap.contains(fileName))
|
||||
{
|
||||
const auto icon = WindowsHepers::GetIconHandlerFromExe(value.c_str());
|
||||
dialogData.push_back({fileName, icon});
|
||||
}
|
||||
processesMap.insert(fileName, processId);
|
||||
}
|
||||
}
|
||||
dialogData.shrink_to_fit();
|
||||
processes.clear();
|
||||
|
||||
QStringList processList(allProcesses.uniqueKeys());
|
||||
processList.sort(Qt::CaseInsensitive);
|
||||
if (QString process = QInputDialog::getItem(This, SELECT_PROCESS, ATTACH_INFO, processList, 0, true, &ok, Qt::WindowCloseButtonHint); ok)
|
||||
if (process.toInt(nullptr, 0)) Host::InjectProcess(process.toInt(nullptr, 0));
|
||||
else for (auto processId : allProcesses.values(process)) Host::InjectProcess(processId);
|
||||
attachDialog->setWindowTitle(SELECT_PROCESS);
|
||||
attachDialog->setLabelText(ATTACH_INFO);
|
||||
|
||||
attachDialog->setData(std::move(dialogData));
|
||||
const bool hasChosenData = attachDialog->exec() != 0;
|
||||
|
||||
if (hasChosenData)
|
||||
{
|
||||
const QString& process = attachDialog->getSelectedData();
|
||||
const int pid = process.toInt(nullptr, 0);
|
||||
if (pid)
|
||||
{
|
||||
Host::InjectProcess(pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& processId : processesMap.values(process))
|
||||
{
|
||||
Host::InjectProcess(processId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchProcess()
|
||||
@ -597,6 +636,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
This = this;
|
||||
ui.setupUi(this);
|
||||
extenWindow = new ExtenWindow(this);
|
||||
attachDialog = new AttachToProcessDialog(this);
|
||||
for (auto [text, slot] : Array<const char*, void(&)()>{
|
||||
{ ATTACH, AttachProcess },
|
||||
{ LAUNCH, LaunchProcess },
|
||||
|
Loading…
x
Reference in New Issue
Block a user