mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-12-24 20:24:13 +08:00
Qtplugin&&window&&config
This commit is contained in:
parent
d0d348e4f8
commit
f9ae99633f
14
Lang/en.h
14
Lang/en.h
@ -40,17 +40,27 @@
|
||||
#define HijackERROR "Hijack ERROR"
|
||||
#define WndSelectProcess L"SelectProcess"
|
||||
#define WndLunaHostGui L"LunaHost Gui"
|
||||
#define WndSetting L"Setting"
|
||||
#define WndPlugins L"Plugins"
|
||||
#define NotifyInvalidHookCode L"Invalid HookCode"
|
||||
#define BtnSelectProcess L"Select Process"
|
||||
#define BtnShowSettingWindow L"Settings"
|
||||
#define BtnAttach L"Attach"
|
||||
#define BtnRefresh L"Refresh"
|
||||
#define BtnToClipboard L"to clipboard"
|
||||
#define BtnInsertUserHook L"Insert UserHook"
|
||||
#define BtnAddPlugin L"Add Plugin"
|
||||
#define BtnPlugin L"Plugins"
|
||||
#define LblFlushDelay L"flushDelay"
|
||||
#define LblFilterRepeat L"Filter Repeat"
|
||||
#define LblCodePage L"CodePage"
|
||||
#define MenuCopyHookCode L"CopyHookCode"
|
||||
#define MenuRemoveHook L"RemoveHook"
|
||||
#define MenuDetachProcess L"DetachProcess"
|
||||
#define MenuAddPlugin L"Add Plugin"
|
||||
#define MenuAddQtPlugin L"Add Qt Plugin"
|
||||
#define MenuRemovePlugin L"Remove Plugin"
|
||||
#define DefaultFont L"Arial"
|
||||
#define InVaildPlugin L"InVaild Plugin"
|
||||
#define InVaildPlugin L"InVaild Plugin"
|
||||
#define CantLoadQtLoader L"Can't Load QtLoader.dll"
|
||||
#define LblPluginNotify L"Qt Plugins Will be Loaded at Start Only."
|
||||
#define LblPluginRemove L"Remove Plugins Will be Useful after Restart."
|
@ -1,4 +1,4 @@
|
||||
add_executable(LunaHost WIN32 controls.cpp main.cpp processlistwindow.cpp LunaHost.cpp window.cpp luna.rc pluginmanager.cpp Plugin/pluginexample.cpp)
|
||||
add_executable(LunaHost confighelper.cpp controls.cpp main.cpp processlistwindow.cpp LunaHost.cpp window.cpp luna.rc pluginmanager.cpp Plugin/pluginexample.cpp)
|
||||
target_precompile_headers(LunaHost REUSE_FROM pch)
|
||||
set_target_properties(LunaHost PROPERTIES OUTPUT_NAME "LunaHost${bitappendix}")
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <CommCtrl.h>
|
||||
#include <TlHelp32.h>
|
||||
#include<stdio.h>
|
||||
#include<fstream>
|
||||
#include"host.h"
|
||||
#include"hookcode.h"
|
||||
#include"textthread.h"
|
||||
@ -24,30 +25,43 @@ void LunaHost::toclipboard(std::wstring& sentence){
|
||||
}
|
||||
}
|
||||
void LunaHost::on_close(){
|
||||
delete configs;
|
||||
for(auto pid:attachedprocess){
|
||||
Host::DetachProcess(pid);
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
void LunaHost::on_size(int w,int h){
|
||||
int height = h-140;
|
||||
g_hListBox_listtext->setgeo(10, 110, w - 20, height/2);
|
||||
g_showtexts->setgeo(10, 120+height/2, w - 20, height/2);
|
||||
w-=20;
|
||||
g_selectprocessbutton->setgeo(10,10,w/3,40);
|
||||
btnshowsettionwindow->setgeo(10+w/3,10,w/3,40);
|
||||
btnplugin->setgeo(10+w*2/3,10,w/3,40);
|
||||
g_hListBox_listtext->setgeo(10, 110, w , height/2);
|
||||
g_showtexts->setgeo(10, 120+height/2, w , height/2);
|
||||
g_hEdit_userhook->setgeo(10,60,w*2/3,40);
|
||||
g_hButton_insert->setgeo(10+w*2/3,60,w/3,40);
|
||||
}
|
||||
|
||||
LunaHost::LunaHost(){
|
||||
configs=new confighelper;
|
||||
settext(WndLunaHostGui);
|
||||
btnshowsettionwindow=new button(this, BtnShowSettingWindow,100,100,100,100);
|
||||
g_selectprocessbutton =new button(this,BtnSelectProcess,830, 10, 200, 40) ;
|
||||
|
||||
g_hEdit_userhook = new textedit(this,L"",10, 60, 600, 40,ES_AUTOHSCROLL);
|
||||
btnaddplugin=new button(this,BtnAddPlugin,830,60,200,40);
|
||||
btnaddplugin->onclick=[&](){
|
||||
auto f=plugins->selectpluginfile();
|
||||
if(f.has_value()){
|
||||
plugins->addplugin(f.value());
|
||||
}
|
||||
btnplugin=new button(this,BtnPlugin,830,60,200,40);
|
||||
|
||||
plugins=new Pluginmanager(this);
|
||||
btnplugin->onclick=[&](){
|
||||
if(pluginwindow==0) pluginwindow=new Pluginwindow(this,plugins);
|
||||
pluginwindow->show();
|
||||
};
|
||||
g_hButton_insert = new button(this,BtnInsertUserHook,610, 60, 200, 40) ;
|
||||
|
||||
btnshowsettionwindow->onclick=[&](){
|
||||
if(settingwindow==0) settingwindow=new Settingwindow(this);
|
||||
settingwindow->show();
|
||||
};
|
||||
g_selectprocessbutton->onclick=[&](){
|
||||
if(_processlistwindow==0) _processlistwindow=new processlistwindow(this);
|
||||
_processlistwindow->show();
|
||||
@ -63,28 +77,6 @@ LunaHost::LunaHost(){
|
||||
g_showtexts->appendtext(NotifyInvalidHookCode);
|
||||
}
|
||||
};
|
||||
g_check_clipboard =new checkbox(this,BtnToClipboard,550, 10, 200, 40) ;
|
||||
g_check_clipboard->onclick=[&](){
|
||||
check_toclipboard=g_check_clipboard->ischecked();
|
||||
};
|
||||
new label(this,LblFlushDelay,10, 10, 150, 40);
|
||||
new label(this,LblCodePage,270, 10, 150, 40);
|
||||
|
||||
g_timeout = new textedit(this,std::to_wstring(TextThread::flushDelay).c_str(),160, 10, 100, 40) ;
|
||||
g_codepage = new textedit(this,L"932",420, 10, 100, 40) ;
|
||||
|
||||
g_timeout->ontextchange=[&](const std::wstring &text){
|
||||
TextThread::flushDelay=std::stoi(text);
|
||||
};
|
||||
g_codepage->ontextchange=[&](const std::wstring &text){
|
||||
try {
|
||||
auto cp=std::stoi(text);
|
||||
if(IsValidCodePage(cp))
|
||||
Host::defaultCodepage= cp;
|
||||
}
|
||||
catch (const std::invalid_argument& e) {
|
||||
}
|
||||
};
|
||||
|
||||
g_hListBox_listtext = new listbox(this,10, 120, 200, 200);
|
||||
g_hListBox_listtext->oncurrentchange=[&](int idx){
|
||||
@ -129,7 +121,6 @@ LunaHost::LunaHost(){
|
||||
};
|
||||
g_showtexts = new textedit(this,L"",10, 330, 200, 200,ES_READONLY|ES_MULTILINE |ES_AUTOVSCROLL| WS_VSCROLL);
|
||||
|
||||
plugins=new pluginmanager(this);
|
||||
|
||||
Host::Start(
|
||||
[&](DWORD pid) {attachedprocess.push_back(pid);},
|
||||
@ -140,6 +131,9 @@ LunaHost::LunaHost(){
|
||||
std::bind(&LunaHost::on_thread_delete,this,std::placeholders::_1),
|
||||
std::bind(&LunaHost::on_text_recv,this,std::placeholders::_1,std::placeholders::_2)
|
||||
);
|
||||
|
||||
setfont(25);
|
||||
setcentral(1000,600);
|
||||
}
|
||||
|
||||
bool LunaHost::on_text_recv(TextThread& thread, std::wstring& output){
|
||||
@ -179,4 +173,109 @@ void LunaHost::on_thread_delete(TextThread& thread){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
|
||||
new label(this,LblFlushDelay,10, 10, 150, 40);
|
||||
new label(this,LblCodePage,10, 60, 150, 40);
|
||||
ckbfilterrepeat=new checkbox(this,LblFilterRepeat,10, 160, 200, 40);
|
||||
ckbfilterrepeat->onclick=[=](){
|
||||
auto ck=ckbfilterrepeat->ischecked();
|
||||
TextThread::filterRepetition=ck;
|
||||
host->configs->set("filterrepeat",ck);
|
||||
};
|
||||
auto frp=host->configs->get("filterrepeat",false);
|
||||
TextThread::filterRepetition=frp;
|
||||
ckbfilterrepeat->setcheck(frp);
|
||||
|
||||
g_check_clipboard =new checkbox(this,BtnToClipboard,10, 110, 200, 40) ;
|
||||
g_check_clipboard->onclick=[=](){
|
||||
auto ck=g_check_clipboard->ischecked();
|
||||
((LunaHost*)parent)->check_toclipboard=ck;
|
||||
host->configs->set("ToClipboard",ck);
|
||||
};
|
||||
auto toc=host->configs->get("ToClipboard",false);
|
||||
((LunaHost*)parent)->check_toclipboard=toc;
|
||||
g_check_clipboard->setcheck(toc);
|
||||
|
||||
g_timeout = new textedit(this,std::to_wstring(host->configs->get("flushDelay",TextThread::flushDelay)).c_str(),160, 10, 100, 40) ;
|
||||
g_codepage = new textedit(this,std::to_wstring(host->configs->get("codepage",Host::defaultCodepage)).c_str(),160, 60, 100, 40) ;
|
||||
g_timeout->ontextchange=[=](const std::wstring &text){
|
||||
try{
|
||||
auto fla=std::stoi(text);
|
||||
TextThread::flushDelay=fla;
|
||||
host->configs->set("flushDelay",fla);
|
||||
}
|
||||
catch(std::exception&){}
|
||||
};
|
||||
g_codepage->ontextchange=[=](const std::wstring &text){
|
||||
try {
|
||||
auto cp=std::stoi(text);
|
||||
if(IsValidCodePage(cp)){
|
||||
Host::defaultCodepage= cp; printf("2");
|
||||
host->configs->set("codepage",cp);
|
||||
}
|
||||
}
|
||||
catch (const std::invalid_argument& e) {
|
||||
}
|
||||
};
|
||||
setcentral(300,300);
|
||||
settext(WndSetting);
|
||||
}
|
||||
void Pluginwindow::on_size(int w,int h){
|
||||
listplugins->setgeo(10,80,w-20,h-100);
|
||||
}
|
||||
Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p){
|
||||
pluginmanager=pl;
|
||||
new label(this,LblPluginNotify, 10,10,500,30);
|
||||
new label(this,LblPluginRemove, 10,40,500,30);
|
||||
static auto listadd=[&](const std::wstring& s){
|
||||
auto idx=listplugins->additem(std::filesystem::path(s).stem().c_str());
|
||||
listplugins->setdata(idx,(LONG_PTR)s.c_str());
|
||||
};
|
||||
listplugins = new listbox(this,10, 10,360,340);
|
||||
#define IDM_ADD_PLUGIN 1004
|
||||
#define IDM_ADD_QT_PLUGIN 1005
|
||||
#define IDM_REMOVE_PLUGIN 1006
|
||||
listplugins->oncontextmenu=[](){
|
||||
HMENU hMenu = CreatePopupMenu();
|
||||
AppendMenu(hMenu, MF_STRING, IDM_ADD_PLUGIN, MenuAddPlugin);
|
||||
AppendMenu(hMenu, MF_STRING, IDM_ADD_QT_PLUGIN, MenuAddQtPlugin);
|
||||
AppendMenu(hMenu, MF_STRING, IDM_REMOVE_PLUGIN, MenuRemovePlugin);
|
||||
return hMenu;
|
||||
};
|
||||
listplugins->oncontextmenucallback=[&](WPARAM wparam){
|
||||
|
||||
listplugins->currentidx() ;
|
||||
switch (LOWORD(wparam)) {
|
||||
|
||||
case IDM_ADD_PLUGIN:
|
||||
case IDM_ADD_QT_PLUGIN:
|
||||
{
|
||||
auto f=pluginmanager->selectpluginfile();
|
||||
if(f.has_value()){
|
||||
if(pluginmanager->addplugin(f.value(),LOWORD(wparam)==IDM_ADD_QT_PLUGIN)){
|
||||
listplugins->deleteitem(listplugins->count()-1);
|
||||
listadd(f.value());
|
||||
listadd(L"InternalClipBoard");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDM_REMOVE_PLUGIN:
|
||||
{
|
||||
|
||||
auto idx=listplugins->currentidx();
|
||||
if(idx==listplugins->count()-1)break;printf("??");
|
||||
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx));
|
||||
listplugins->deleteitem(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
for(int i=0;i<pluginmanager->PluginRank.size();i++){
|
||||
listadd(pluginmanager->PluginRank[i]);
|
||||
}
|
||||
settext(WndPlugins);
|
||||
setcentral(500,400);
|
||||
}
|
@ -3,30 +3,47 @@
|
||||
#include"processlistwindow.h"
|
||||
#include"textthread.h"
|
||||
#include"pluginmanager.h"
|
||||
#include"confighelper.h"
|
||||
class LunaHost;
|
||||
class Pluginwindow:public mainwindow{
|
||||
listbox* listplugins;
|
||||
Pluginmanager* pluginmanager;
|
||||
public:
|
||||
Pluginwindow(mainwindow*,Pluginmanager*);
|
||||
void on_size(int w,int h);
|
||||
};
|
||||
class Settingwindow:public mainwindow{
|
||||
checkbox* ckbfilterrepeat;
|
||||
textedit* g_timeout;
|
||||
textedit* g_codepage;
|
||||
checkbox* g_check_clipboard;
|
||||
public:
|
||||
Settingwindow(LunaHost*);
|
||||
};
|
||||
class LunaHost:public mainwindow{
|
||||
|
||||
Pluginwindow* pluginwindow=0;
|
||||
std::map<int64_t,std::vector<std::wstring>>savetext;
|
||||
std::vector<int>attachedprocess;
|
||||
std::mutex settextmutex;
|
||||
textedit* g_hEdit_userhook;
|
||||
button* g_hButton_insert;
|
||||
button* btnaddplugin;
|
||||
button* btnplugin;
|
||||
listbox* g_hListBox_listtext;
|
||||
textedit* g_showtexts;
|
||||
button* g_selectprocessbutton;
|
||||
textedit* g_timeout;
|
||||
textedit* g_codepage;
|
||||
checkbox* g_check_clipboard;
|
||||
button* btnshowsettionwindow;
|
||||
void toclipboard(std::wstring& sentence);
|
||||
processlistwindow *_processlistwindow=0;
|
||||
pluginmanager* plugins;
|
||||
Settingwindow *settingwindow=0;
|
||||
Pluginmanager* plugins;
|
||||
bool on_text_recv(TextThread& thread, std::wstring& sentence);
|
||||
void on_thread_create(TextThread& thread);
|
||||
void on_thread_delete(TextThread& thread);
|
||||
public:
|
||||
confighelper* configs;
|
||||
int64_t currentselect=0;
|
||||
bool check_toclipboard=false;
|
||||
void on_size(int w,int h);
|
||||
void on_close();
|
||||
LunaHost();
|
||||
};
|
||||
};
|
||||
|
@ -1,4 +1,16 @@
|
||||
|
||||
if(0) #仅作为参考范例,实际上已经链接到exe中
|
||||
add_library(ToClipboard MODULE pluginexample.cpp)
|
||||
target_precompile_headers(ToClipboard REUSE_FROM pch)
|
||||
set_target_properties(ToClipboard PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugin${bitappendix}")
|
||||
set_target_properties(ToClipboard PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugin${bitappendix}")
|
||||
endif()
|
||||
|
||||
|
||||
include(QtUtils.cmake)
|
||||
msvc_registry_search()
|
||||
find_qt5(Core Widgets)
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
add_library(QtLoader MODULE QtLoader.cpp)
|
||||
#qt5_wrap_cpp(MOC_SOURCES QtLoader.h)
|
||||
#target_sources(QtLoader PRIVATE ${MOC_SOURCES})
|
||||
target_link_libraries(QtLoader Qt5::Widgets Qt5::Core)
|
||||
set_target_properties(QtLoader PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugin${bitappendix}")
|
48
LunaHost/GUI/Plugin/QtLoader.cpp
Normal file
48
LunaHost/GUI/Plugin/QtLoader.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include<Windows.h>
|
||||
#include<QApplication>
|
||||
#include<QFont>
|
||||
#include<QDir>
|
||||
#include<thread>
|
||||
#include<mutex>
|
||||
#include<Shlwapi.h>
|
||||
void GetCommandLineArguments(int& argc, char**& argv)
|
||||
{
|
||||
LPWSTR* wideArgv = NULL;
|
||||
int wideArgc = 0;
|
||||
|
||||
LPWSTR commandLine = GetCommandLine();
|
||||
|
||||
wideArgv = CommandLineToArgvW(commandLine, &wideArgc);
|
||||
|
||||
if (wideArgv != NULL)
|
||||
{
|
||||
argv = new char*[wideArgc];
|
||||
argc = wideArgc;
|
||||
|
||||
for (int i = 0; i < wideArgc; i++)
|
||||
{
|
||||
int length = WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, NULL, 0, NULL, NULL);
|
||||
argv[i] = new char[length];
|
||||
WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, argv[i], length, NULL, NULL);
|
||||
}
|
||||
LocalFree(wideArgv);
|
||||
}
|
||||
}
|
||||
extern "C" __declspec(dllexport) HMODULE* QtLoadLibrary(LPCWSTR* dlls,int num){
|
||||
auto hdlls=new HMODULE[num];
|
||||
auto mutex=CreateSemaphoreW(0,0,1,0);
|
||||
std::thread([=](){
|
||||
int argc;
|
||||
char** argv;
|
||||
GetCommandLineArguments(argc, argv);
|
||||
QApplication app(argc, nullptr);
|
||||
app.setFont(QFont("MS Shell Dlg 2", 10));
|
||||
for(int i=0;i<num;i++)
|
||||
hdlls[i]=LoadLibraryW(dlls[i]);
|
||||
ReleaseSemaphore(mutex,1,0);
|
||||
app.exec();
|
||||
|
||||
}).detach();
|
||||
WaitForSingleObject(mutex,INFINITE);
|
||||
return hdlls;
|
||||
}
|
84
LunaHost/GUI/Plugin/QtUtils.cmake
Normal file
84
LunaHost/GUI/Plugin/QtUtils.cmake
Normal file
@ -0,0 +1,84 @@
|
||||
macro(msvc_registry_search)
|
||||
if(NOT DEFINED Qt5_DIR)
|
||||
if (NOT EXISTS ${QT_ROOT})
|
||||
# look for user-registry pointing to qtcreator
|
||||
get_filename_component(QT_ROOT [HKEY_CURRENT_USER\\Software\\Classes\\Applications\\QtProject.QtCreator.pro\\shell\\Open\\Command] PATH)
|
||||
|
||||
# get root path
|
||||
string(REPLACE "/Tools" ";" QT_ROOT "${QT_ROOT}")
|
||||
list(GET QT_ROOT 0 QT_ROOT)
|
||||
endif()
|
||||
file(GLOB QT_VERSIONS "${QT_ROOT}/5.13*")
|
||||
list(SORT QT_VERSIONS)
|
||||
|
||||
# assume the latest version will be last alphabetically
|
||||
list(REVERSE QT_VERSIONS)
|
||||
|
||||
list(GET QT_VERSIONS 0 QT_VERSION)
|
||||
|
||||
# fix any double slashes which seem to be common
|
||||
string(REPLACE "//" "/" QT_VERSION "${QT_VERSION}")
|
||||
|
||||
if(MSVC_VERSION GREATER_EQUAL 1920)
|
||||
set(QT_MSVC 2019)
|
||||
elseif(MSVC_VERSION GREATER_EQUAL 1910)
|
||||
set(QT_MSVC 2017)
|
||||
elseif(MSVC_VERSION GREATER_EQUAL 1900)
|
||||
set(QT_MSVC 2015)
|
||||
else()
|
||||
message(WARNING "Unsupported MSVC toolchain version")
|
||||
endif()
|
||||
|
||||
if(QT_MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
SET(QT_SUFFIX "_64")
|
||||
else()
|
||||
set(QT_SUFFIX "")
|
||||
endif()
|
||||
|
||||
# MSVC 2015+ is only backwards compatible
|
||||
if(EXISTS "${QT_VERSION}/msvc${QT_MSVC}${QT_SUFFIX}")
|
||||
set(Qt5_DIR "${QT_VERSION}/msvc${QT_MSVC}${QT_SUFFIX}/lib/cmake/Qt5")
|
||||
elseif(QT_MSVC GREATER_EQUAL 2019 AND EXISTS "${QT_VERSION}/msvc2017${QT_SUFFIX}")
|
||||
set(Qt5_DIR "${QT_VERSION}/msvc2017${QT_SUFFIX}/lib/cmake/Qt5")
|
||||
elseif(QT_MSVC GREATER_EQUAL 2017 AND EXISTS "${QT_VERSION}/msvc2015${QT_SUFFIX}")
|
||||
set(Qt5_DIR "${QT_VERSION}/msvc2015${QT_SUFFIX}/lib/cmake/Qt5")
|
||||
else()
|
||||
message(WARNING "Required QT5 toolchain is not installed")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(find_qt5)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
#add_definitions(-DQT_DEPRECATED_WARNINGS -DQT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
||||
find_package(Qt5 COMPONENTS ${ARGN})
|
||||
|
||||
if(Qt5_FOUND)
|
||||
if(WIN32 AND TARGET Qt5::qmake AND NOT TARGET Qt5::windeployqt)
|
||||
get_target_property(_qt5_qmake_location Qt5::qmake IMPORTED_LOCATION)
|
||||
|
||||
execute_process(
|
||||
COMMAND "${_qt5_qmake_location}" -query QT_INSTALL_PREFIX
|
||||
RESULT_VARIABLE return_code
|
||||
OUTPUT_VARIABLE qt5_install_prefix
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
set(imported_location "${qt5_install_prefix}/bin/windeployqt.exe")
|
||||
|
||||
if(EXISTS ${imported_location})
|
||||
add_executable(Qt5::windeployqt IMPORTED)
|
||||
|
||||
set_target_properties(Qt5::windeployqt PROPERTIES
|
||||
IMPORTED_LOCATION ${imported_location}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Cannot find QT5!")
|
||||
endif()
|
||||
endmacro(find_qt5)
|
58
LunaHost/GUI/confighelper.cpp
Normal file
58
LunaHost/GUI/confighelper.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include"confighelper.h"
|
||||
|
||||
std::string readfile(const wchar_t* fname) {
|
||||
FILE* f;
|
||||
_wfopen_s(&f, fname, L"rb");
|
||||
if (f == 0)return {};
|
||||
fseek(f, 0, SEEK_END);
|
||||
auto len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
std::string buff;
|
||||
buff.resize(len);
|
||||
fread(buff.data(), 1, len, f);
|
||||
fclose(f);
|
||||
return buff;
|
||||
}
|
||||
void writefile(const wchar_t* fname,const std::string& s){
|
||||
FILE* f;
|
||||
_wfopen_s(&f, fname, L"w");
|
||||
fprintf(f,"%s",s.c_str());
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
confighelper::confighelper(){
|
||||
configpath=std::filesystem::current_path()/(x64?"config64.json":"config32.json");
|
||||
try{
|
||||
configs=nlohmann::json::parse(readfile(configpath.c_str()));
|
||||
}
|
||||
catch(std::exception &){
|
||||
configs={};
|
||||
}
|
||||
}
|
||||
confighelper::~confighelper(){
|
||||
|
||||
writefile(configpath.c_str(), configs.dump(4));
|
||||
}
|
||||
void confighelper::pluginsremove(const std::string&s){
|
||||
auto &plgs=configs["plugins"];
|
||||
auto it=std::remove_if(plgs.begin(),plgs.end(),[&](auto&t){
|
||||
std::string p=t["path"];
|
||||
return p==s;
|
||||
});
|
||||
plgs.erase(it, plgs.end());
|
||||
}
|
||||
void confighelper::pluginsadd(const std::string& p,bool isQt){
|
||||
if(configs.find("plugins")==configs.end()){
|
||||
configs["plugins"]={};
|
||||
}
|
||||
configs["plugins"].push_back({
|
||||
{"path",p},
|
||||
{"isQt",isQt}
|
||||
});
|
||||
}
|
||||
nlohmann::json confighelper::pluginsget(){
|
||||
if(configs.find("plugins")==configs.end()){
|
||||
return {};
|
||||
}
|
||||
return configs["plugins"];
|
||||
}
|
24
LunaHost/GUI/confighelper.h
Normal file
24
LunaHost/GUI/confighelper.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef LUNA_CONFIG_HELPER
|
||||
#define LUNA_CONFIG_HELPER
|
||||
#include<nlohmann/json.hpp>
|
||||
class confighelper{
|
||||
nlohmann::json configs;
|
||||
std::wstring configpath;
|
||||
public:
|
||||
confighelper();
|
||||
~confighelper();
|
||||
nlohmann::json pluginsget();
|
||||
void pluginsadd(const std::string&,bool);
|
||||
void pluginsremove(const std::string&);
|
||||
template<class T>
|
||||
T get(const std::string&key,T default1){
|
||||
if(configs.find(key)==configs.end())return default1;
|
||||
return configs[key];
|
||||
}
|
||||
template<class T>
|
||||
void set(const std::string&key,T v){
|
||||
configs[key]=v;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -19,7 +19,10 @@ bool checkbox::ischecked(){
|
||||
int state = SendMessage(winId, BM_GETCHECK, 0, 0);
|
||||
return (state == BST_CHECKED);
|
||||
}
|
||||
checkbox::checkbox(mainwindow* parent,LPCWSTR text,int x,int y,int w,int h):button(parent,text,x,y,w,h,BS_AUTOCHECKBOX){
|
||||
checkbox::checkbox(mainwindow* parent,LPCWSTR text,int x,int y,int w,int h):button(parent,text,x,y,w,h,BS_AUTOCHECKBOX|BS_RIGHTBUTTON ){
|
||||
}
|
||||
void checkbox::setcheck(bool b){
|
||||
SendMessage(winId, BM_SETCHECK, (WPARAM)BST_CHECKED*b, 0);
|
||||
}
|
||||
textedit::textedit(mainwindow* parent,LPCWSTR text,int x,int y,int w,int h,DWORD stype):control(parent){
|
||||
winId=CreateWindowEx(0, L"EDIT", text, WS_CHILD | WS_VISIBLE | WS_BORDER|stype ,
|
||||
|
@ -21,6 +21,7 @@ class checkbox:public button{
|
||||
public:
|
||||
checkbox(mainwindow*,LPCWSTR,int,int,int,int);
|
||||
bool ischecked();
|
||||
void setcheck(bool);
|
||||
};
|
||||
class textedit:public control{
|
||||
public:
|
||||
|
@ -6,4 +6,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
LunaHost _lunahost;
|
||||
_lunahost.show();
|
||||
mainwindow::run();
|
||||
}
|
||||
int main(){
|
||||
SetProcessDPIAware();
|
||||
LunaHost _lunahost;
|
||||
_lunahost.show();
|
||||
mainwindow::run();
|
||||
}
|
@ -6,26 +6,7 @@
|
||||
#include"LunaHost.h"
|
||||
#include"Lang/Lang.h"
|
||||
#include"host.h"
|
||||
std::string readfile(const wchar_t* fname) {
|
||||
FILE* f;
|
||||
_wfopen_s(&f, fname, L"rb");
|
||||
if (f == 0)return {};
|
||||
fseek(f, 0, SEEK_END);
|
||||
auto len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
std::string buff;
|
||||
buff.resize(len);
|
||||
fread(buff.data(), 1, len, f);
|
||||
fclose(f);
|
||||
return buff;
|
||||
}
|
||||
void appendfile(const wchar_t* fname,const std::wstring& s){
|
||||
auto u8s=WideStringToString(s);
|
||||
FILE* f;
|
||||
_wfopen_s(&f, fname, L"a");
|
||||
fprintf(f,"\n%s",u8s.c_str());
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
std::optional<std::wstring>SelectFile(HWND hwnd,LPCWSTR lpstrFilter){
|
||||
OPENFILENAME ofn;
|
||||
wchar_t szFileName[MAX_PATH] = { 0 };
|
||||
@ -44,52 +25,75 @@ std::optional<std::wstring>SelectFile(HWND hwnd,LPCWSTR lpstrFilter){
|
||||
}
|
||||
else return {};
|
||||
}
|
||||
|
||||
std::vector<std::wstring>pluginmanager::readpluginfile(){
|
||||
if(!std::filesystem::exists(pluginfilename))
|
||||
return{};
|
||||
auto u16pl=StringToWideString(readfile(pluginfilename.c_str()).data());
|
||||
auto pls=strSplit(u16pl,L"\n");
|
||||
return pls;
|
||||
typedef HMODULE*(*QtLoadLibrary_t)(LPWSTR*,int);
|
||||
QtLoadLibrary_t loadqtloader(){
|
||||
auto QtLoaderPath=std::filesystem::current_path()/(x64?"plugin64":"plugin32")/"QtLoader.dll";
|
||||
auto helper=LoadLibrary(QtLoaderPath.c_str());
|
||||
if(helper==0)return 0;
|
||||
auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(helper, "QtLoadLibrary");
|
||||
return QtLoadLibrary;
|
||||
}
|
||||
void pluginmanager::writepluginfile(const std::wstring& plugf){
|
||||
appendfile(pluginfilename.c_str(),plugf);
|
||||
void Pluginmanager::loadqtdlls(std::vector<std::wstring>&collectQtplugs){
|
||||
auto QtLoadLibrary = loadqtloader();
|
||||
if(!QtLoadLibrary){
|
||||
MessageBoxW(host->winId,CantLoadQtLoader,L"Error",0);
|
||||
return ;
|
||||
}
|
||||
std::vector<wchar_t*>saves;
|
||||
for(auto&p:collectQtplugs){
|
||||
auto str=new wchar_t[p.size()+1];
|
||||
wcscpy(str,p.c_str());
|
||||
saves.emplace_back(str);
|
||||
}
|
||||
auto modules=QtLoadLibrary(saves.data(),collectQtplugs.size());
|
||||
for(auto str:saves)delete str;
|
||||
for(int i=0;i<collectQtplugs.size();i++){
|
||||
OnNewSentenceS[collectQtplugs[i]]=GetProcAddress(modules[i],"OnNewSentence");
|
||||
}
|
||||
}
|
||||
pluginmanager::pluginmanager(LunaHost* _host):host(_host){
|
||||
Pluginmanager::Pluginmanager(LunaHost* _host):host(_host){
|
||||
try {
|
||||
std::scoped_lock lock(OnNewSentenceSLock);
|
||||
pluginfilename=std::filesystem::current_path()/(x64?"plugin64.txt":"plugin32.txt");
|
||||
OnNewSentenceS.push_back({L"Internal ClipBoard",GetProcAddress(GetModuleHandle(0),"OnNewSentence")});//内部链接的剪贴板插件
|
||||
|
||||
for (auto &pl:readpluginfile()) {
|
||||
|
||||
auto ret=checkisvalidplugin(pl);
|
||||
if(ret.has_value()){
|
||||
auto v=ret.value();
|
||||
if(!checkisdump(v.second)){
|
||||
OnNewSentenceS.push_back(v);
|
||||
}
|
||||
auto plgs=host->configs->pluginsget();
|
||||
std::vector<std::wstring>collectQtplugs;
|
||||
for (auto i=0;i<plgs.size();i++) {
|
||||
bool isqt=plgs[i]["isQt"];
|
||||
auto path=StringToWideString(plgs[i]["path"]);
|
||||
PluginRank.push_back(path);
|
||||
OnNewSentenceS[path]=0;
|
||||
if(isqt){
|
||||
collectQtplugs.push_back((path));
|
||||
continue;
|
||||
}
|
||||
OnNewSentenceS[path]=GetProcAddress(LoadLibraryW(path.c_str()),"OnNewSentence");
|
||||
}
|
||||
if(collectQtplugs.size()){
|
||||
loadqtdlls(collectQtplugs);
|
||||
}
|
||||
PluginRank.push_back(L"InternalClipBoard");
|
||||
OnNewSentenceS[L"InternalClipBoard"]=GetProcAddress(GetModuleHandle(0),"OnNewSentence");//内部链接的剪贴板插件
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool pluginmanager::dispatch(TextThread& thread, std::wstring& sentence){
|
||||
bool Pluginmanager::dispatch(TextThread& thread, std::wstring& sentence){
|
||||
auto sentenceInfo=GetSentenceInfo(thread).data();
|
||||
wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, (sentence.size() + 1) * sizeof(wchar_t));
|
||||
wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str());
|
||||
concurrency::reader_writer_lock::scoped_lock_read readLock(OnNewSentenceSLock);
|
||||
for (const auto& extension : OnNewSentenceS){
|
||||
if (!*(sentenceBuffer = ((OnNewSentence_t)extension.second)(sentenceBuffer, sentenceInfo))) break;
|
||||
for (const auto& path : PluginRank){
|
||||
auto funptr=OnNewSentenceS[path];
|
||||
if(funptr==0)continue;
|
||||
if (!*(sentenceBuffer = ((OnNewSentence_t)funptr)(sentenceBuffer, sentenceInfo))) break;
|
||||
}
|
||||
sentence = sentenceBuffer;
|
||||
HeapFree(GetProcessHeap(), 0, sentenceBuffer);
|
||||
return !sentence.empty();
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::wstring,LPVOID>> pluginmanager::checkisvalidplugin(const std::wstring& pl){
|
||||
std::optional<LPVOID> Pluginmanager::checkisvalidplugin(const std::wstring& pl){
|
||||
auto path=std::filesystem::path(pl);
|
||||
if (!std::filesystem::exists(path))return{};
|
||||
if (!std::filesystem::is_regular_file(path))return{};
|
||||
@ -97,31 +101,43 @@ std::optional<std::pair<std::wstring,LPVOID>> pluginmanager::checkisvalidplugin(
|
||||
if((appendix!=std::wstring(L".dll"))&&(appendix!=std::wstring(L".xdll")))return {};
|
||||
auto dll=LoadLibraryW(pl.c_str());
|
||||
if(!dll)return {};
|
||||
auto OnNewSentence=GetProcAddress(dll,"OnNewSentence");
|
||||
auto OnNewSentence=GetProcAddress(LoadLibraryW(pl.c_str()),"OnNewSentence");
|
||||
if(!OnNewSentence){
|
||||
FreeLibrary(dll);
|
||||
return {};
|
||||
}
|
||||
return std::make_pair(path.stem(), OnNewSentence);
|
||||
return OnNewSentence ;
|
||||
}
|
||||
bool pluginmanager::checkisdump(LPVOID ptr){
|
||||
bool Pluginmanager::checkisdump(LPVOID ptr){
|
||||
for(auto& p:OnNewSentenceS){
|
||||
if(p.second==ptr)return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<std::wstring>pluginmanager::selectpluginfile(){
|
||||
void Pluginmanager::remove(const std::wstring& ss){
|
||||
std::scoped_lock lock(OnNewSentenceSLock);
|
||||
auto it = std::find(PluginRank.begin(), PluginRank.end(), ss);
|
||||
if (it != PluginRank.end()) {
|
||||
PluginRank.erase(it);
|
||||
}
|
||||
host->configs->pluginsremove(WideStringToString(ss));
|
||||
}
|
||||
std::optional<std::wstring>Pluginmanager::selectpluginfile(){
|
||||
return SelectFile(host->winId,L"Plugin Files\0*.dll;*.xdll\0");
|
||||
}
|
||||
bool pluginmanager::addplugin(const std::wstring& p){
|
||||
auto plugin=checkisvalidplugin(p);
|
||||
if(plugin.has_value()){
|
||||
auto v=plugin.value();
|
||||
bool Pluginmanager::addplugin(const std::wstring& p,bool isQt){
|
||||
if(isQt){
|
||||
host->configs->pluginsadd(WideStringToString(p),isQt);
|
||||
return true;
|
||||
}
|
||||
auto plugin=GetProcAddress(LoadLibraryW(p.c_str()),"OnNewSentence");
|
||||
if(plugin){
|
||||
std::scoped_lock lock(OnNewSentenceSLock);
|
||||
if(!checkisdump(v.second)){
|
||||
OnNewSentenceS.push_back(v);
|
||||
writepluginfile(p);
|
||||
if(!checkisdump(plugin)){
|
||||
PluginRank.push_back(p);
|
||||
//std::swap(PluginRank.end()-2,PluginRank.end()-1);
|
||||
OnNewSentenceS[p]=plugin;
|
||||
host->configs->pluginsadd(WideStringToString(p),isQt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -132,7 +148,7 @@ bool pluginmanager::addplugin(const std::wstring& p){
|
||||
}
|
||||
|
||||
|
||||
std::array<InfoForExtension, 20> pluginmanager::GetSentenceInfo(TextThread& thread)
|
||||
std::array<InfoForExtension, 20> Pluginmanager::GetSentenceInfo(TextThread& thread)
|
||||
{
|
||||
void (*AddText)(int64_t, const wchar_t*) = [](int64_t number, const wchar_t* text)
|
||||
{
|
||||
|
@ -3,20 +3,20 @@
|
||||
#include"Plugin/plugindef.h"
|
||||
#include"textthread.h"
|
||||
class LunaHost;
|
||||
class pluginmanager{
|
||||
std::vector<std::pair<std::wstring,LPVOID>>OnNewSentenceS;
|
||||
std::optional<std::pair<std::wstring,LPVOID>> checkisvalidplugin(const std::wstring&);
|
||||
std::vector<std::wstring>readpluginfile();
|
||||
void writepluginfile(const std::wstring&);
|
||||
std::wstring pluginfilename;
|
||||
class Pluginmanager{
|
||||
std::unordered_map<std::wstring,LPVOID>OnNewSentenceS;
|
||||
std::optional<LPVOID> checkisvalidplugin(const std::wstring&);
|
||||
concurrency::reader_writer_lock OnNewSentenceSLock;
|
||||
bool checkisdump(LPVOID);
|
||||
LunaHost* host;
|
||||
std::array<InfoForExtension, 20> GetSentenceInfo(TextThread& thread);
|
||||
void loadqtdlls(std::vector<std::wstring>&collectQtplugs);
|
||||
public:
|
||||
pluginmanager(LunaHost*);
|
||||
std::vector<std::wstring>PluginRank;
|
||||
Pluginmanager(LunaHost*);
|
||||
bool dispatch(TextThread&, std::wstring& sentence);
|
||||
bool addplugin(const std::wstring&);
|
||||
bool addplugin(const std::wstring&,bool isQt=false);
|
||||
void remove(const std::wstring&);
|
||||
std::optional<std::wstring>selectpluginfile();
|
||||
};
|
||||
|
||||
|
@ -49,8 +49,7 @@ void processlistwindow::PopulateProcessList(listbox* _listbox,std::unordered_map
|
||||
}
|
||||
}
|
||||
|
||||
processlistwindow::processlistwindow(mainwindow* parent):mainwindow(parent){
|
||||
settext(WndSelectProcess);
|
||||
processlistwindow::processlistwindow(mainwindow* p):mainwindow(p){
|
||||
g_hEdit = new textedit(this,L"",10, 10, 400, 40,ES_AUTOHSCROLL);
|
||||
g_hButton=new button(this,BtnAttach,420, 10, 100, 40);
|
||||
g_refreshbutton =new button(this,BtnRefresh,530, 10, 100, 40);
|
||||
@ -80,6 +79,8 @@ processlistwindow::processlistwindow(mainwindow* parent):mainwindow(parent){
|
||||
}
|
||||
g_hEdit->settext(_);
|
||||
};
|
||||
settext(WndSelectProcess);
|
||||
setcentral(800,400);
|
||||
}
|
||||
void processlistwindow::on_show(){
|
||||
g_hEdit->settext(L"");
|
||||
|
@ -1,19 +1,14 @@
|
||||
#include"window.h"
|
||||
#include"controls.h"
|
||||
#include"Lang/Lang.h"
|
||||
void SetDefaultFont(HWND hwnd)
|
||||
{
|
||||
EnumChildWindows(hwnd, [](HWND hwndChild, LPARAM lParam)
|
||||
{
|
||||
static auto fnt=CreateFont(28, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
||||
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
void basewindow::setfont(int sz,LPCWSTR fn){
|
||||
if(fn==0)fn=DefaultFont;
|
||||
hfont=CreateFont(sz, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
||||
DEFAULT_CHARSET , OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, DefaultFont);
|
||||
SendMessage(hwndChild, WM_SETFONT, (WPARAM)fnt, TRUE);
|
||||
return TRUE;
|
||||
}, 0);
|
||||
DEFAULT_PITCH | FF_DONTCARE, fn);
|
||||
SendMessage(winId, WM_SETFONT, (WPARAM)hfont, TRUE);
|
||||
}
|
||||
|
||||
std::wstring basewindow::text(){
|
||||
int textLength = GetWindowTextLength(winId);
|
||||
std::vector<wchar_t> buffer(textLength + 1);
|
||||
@ -39,7 +34,14 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
|
||||
case WM_SHOWWINDOW:
|
||||
{
|
||||
on_show();
|
||||
SetDefaultFont(winId);
|
||||
if(hfont==0)hfont=parent->hfont;
|
||||
if(hfont)
|
||||
EnumChildWindows(winId, [](HWND hwndChild, LPARAM lParam)
|
||||
{
|
||||
if(0==SendMessage(hwndChild, WM_GETFONT, 0, 0))
|
||||
SendMessage(hwndChild, WM_SETFONT, lParam, TRUE);
|
||||
return TRUE;
|
||||
}, (LPARAM)hfont);
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
@ -99,7 +101,25 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::pair<int,int>mainwindow::calculateXY(int w,int h){
|
||||
int cx,cy;
|
||||
if(parent==0){
|
||||
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||
cx = screenWidth / 2;
|
||||
cy = screenHeight / 2;
|
||||
}
|
||||
else{
|
||||
auto rect=parent->getgeo();
|
||||
cx=(rect.left+rect.right)/2;
|
||||
cy=(rect.top+rect.bottom)/2;
|
||||
}
|
||||
return {cx-w/2,cy-h/2};
|
||||
}
|
||||
void mainwindow::setcentral(int w,int h){
|
||||
auto [x,y]=calculateXY(w,h);
|
||||
setgeo(x,y,w,h);
|
||||
}
|
||||
mainwindow::mainwindow(mainwindow* _parent){
|
||||
const wchar_t CLASS_NAME[] = L"LunaHostWindow";
|
||||
|
||||
|
@ -3,11 +3,13 @@
|
||||
class control;
|
||||
class basewindow{
|
||||
public:
|
||||
HFONT hfont=0;
|
||||
HWND winId;
|
||||
void setgeo(int,int,int,int);
|
||||
RECT getgeo();
|
||||
std::wstring text();
|
||||
void settext(const std::wstring&);
|
||||
void setfont(int,LPCWSTR fn=0);
|
||||
operator HWND(){return winId;}
|
||||
};
|
||||
class mainwindow:public basewindow{
|
||||
@ -23,5 +25,7 @@ public:
|
||||
static void run();
|
||||
void show();
|
||||
void close();
|
||||
void setcentral(int,int);
|
||||
std::pair<int,int>calculateXY(int w,int h);
|
||||
};
|
||||
#endif
|
24674
libs/nlohmann/json.hpp
Normal file
24674
libs/nlohmann/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user