This commit is contained in:
恍兮惚兮 2024-07-21 19:28:47 +08:00
parent 5c048ee8b2
commit 3e66a81e40
19 changed files with 1941 additions and 1548 deletions

View File

@ -92,7 +92,7 @@
#define HS_SEARCH_FOR_TEXT L"Search for specific text"
#define VersionLatest L"Latest version"
#define VersionCurrent L"Current version"
#define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nHomepage: https://lunatranslator.xyz\nDiscord: https://discord.gg/f8NSvaDU"
#define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nHomepage: https://lunatranslator.xyz\npatreon: https://patreon.com/HIllya51\nDiscord: https://discord.gg/f8NSvaDU\n\nThis program is a core submodule of LunaTranslator and is fully integrated in Lunatranslator. This program contains only some simple functions, if you need more functions, please use LunaTranslator.\n\nIf you find unsupported games, please submit an issue\nhttps://github.com/HIllya51/LunaHook/issues/new?assignees=&labels=enhancement&projects=&template=01_game_request.yaml"
#define LIST_HOOK L"Hook"
#define LIST_TEXT L"Text"
#define PROC_CONN L"process connected %d"

View File

@ -92,7 +92,7 @@
#define HS_SEARCH_FOR_TEXT L"Искать определенный текст"
#define VersionLatest L"Последняя версия"
#define VersionCurrent L"Текущая версия"
#define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nСтраница проекта: https://lunatranslator.xyz\nDiscord: https://discord.gg/f8NSvaDU\nПеревод на русский: https://github.com/NekoIriyaRu"
#define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nСтраница проекта: https://lunatranslator.xyz\npatreon: https://patreon.com/HIllya51\nDiscord: https://discord.gg/f8NSvaDU\nПеревод на русский: https://github.com/NekoIriyaRu\n\nЭта программа является основным подмодулем LunaTranslator и полностью интегрирована в Lunatranslator. Эта программа содержит только некоторые простые функции. Если вам нужны дополнительные функции, используйте LunaTranslator.\n\nЕсли вы обнаружите какие-либо неподдерживаемые игры, сообщите о проблеме.\nhttps://github.com/HIllya51/LunaHook/issues/new?assignees=&labels=enhancement&projects=&template=01_game_request.yaml"
#define LIST_HOOK L"Хук"
#define LIST_TEXT L"Текст"
#define PROC_CONN L"Процесс подключен %d"

View File

@ -92,7 +92,7 @@
#define HS_SEARCH_FOR_TEXT L"搜索指定文本"
#define VersionLatest L"最新版本"
#define VersionCurrent L"当前版本"
#define ProjectHomePage L"Github https://github.com/HIllya51/LunaHook\n项目主页 https://lunatranslator.xyz\nDiscordhttps://discord.gg/f8NSvaDU"
#define ProjectHomePage L"Github https://github.com/HIllya51/LunaHook\n项目主页 https://lunatranslator.xyz\npatreonhttps://patreon.com/HIllya51\nDiscordhttps://discord.gg/f8NSvaDU\n\n本程序是LunaTranslator 的核心子模块并完全集成在Lunatranslator中。本程序仅包含一些简单功能如果您需要更多功能请使用 LunaTranslator。\n\n如果你发现有不支持的游戏请提交issue\nhttps://github.com/HIllya51/LunaHook/issues/new?assignees=&labels=enhancement&projects=&template=01_game_request.yaml"
#define LIST_HOOK L"Hook"
#define LIST_TEXT L"文本"
#define PROC_CONN L"进程已连接 %d"

View File

@ -31,7 +31,7 @@ namespace{
GlobalUnlock(hClipboardData);
s->ARG2=(uintptr_t)hClipboardData;
};
return NewHook(hp,"hookClipboard");
return NewHook(hp,"nwjs/electron");
}
}
namespace v8script{

File diff suppressed because it is too large Load Diff

View File

@ -1,130 +1,144 @@
#include"window.h"
#include"controls.h"
#include"textthread.h"
#include"pluginmanager.h"
#include"confighelper.h"
#include "window.h"
#include "controls.h"
#include "textthread.h"
#include "pluginmanager.h"
#include "confighelper.h"
class LunaHost;
class Pluginwindow:public mainwindow{
listbox* listplugins;
Pluginmanager* pluginmanager;
class Pluginwindow : public mainwindow
{
listbox *listplugins;
Pluginmanager *pluginmanager;
public:
Pluginwindow(mainwindow*,Pluginmanager*);
void on_size(int w,int h);
Pluginwindow(mainwindow *, Pluginmanager *);
void on_size(int w, int h);
void pluginrankmove(int);
};
class Settingwindow:public mainwindow{
checkbox* ckbfilterrepeat;
spinbox* g_timeout;
spinbox* g_codepage;
checkbox* g_check_clipboard;
checkbox* readonlycheck;
checkbox* autoattach;
checkbox* autoattach_so;
checkbox* copyselect;
spinbox* spinmaxbuffsize;
spinbox* spinmaxhistsize;
gridlayout* mainlayout;
lineedit* showfont;
button* selectfont;
class Settingwindow : public mainwindow
{
checkbox *ckbfilterrepeat;
spinbox *g_timeout;
spinbox *g_codepage;
checkbox *g_check_clipboard;
checkbox *readonlycheck;
checkbox *autoattach;
checkbox *autoattach_so;
checkbox *copyselect;
spinbox *spinmaxbuffsize;
spinbox *spinmaxhistsize;
gridlayout *mainlayout;
lineedit *showfont;
button *selectfont;
public:
Settingwindow(LunaHost*);
Settingwindow(LunaHost *);
};
class processlistwindow:public mainwindow{
gridlayout* mainlayout;
lineedit* g_hEdit;
button* g_hButton;
listview* g_hListBox;
button* g_refreshbutton;
std::unordered_map<std::wstring,std::vector<int>> g_exe_pid;
void PopulateProcessList(listview*,std::unordered_map<std::wstring,std::vector<int>>&);
class processlistwindow : public mainwindow
{
gridlayout *mainlayout;
lineedit *g_hEdit;
button *g_hButton;
listview *g_hListBox;
button *g_refreshbutton;
std::unordered_map<std::wstring, std::vector<int>> g_exe_pid;
void PopulateProcessList(listview *, std::unordered_map<std::wstring, std::vector<int>> &);
public:
processlistwindow(mainwindow* parent=0);
processlistwindow(mainwindow *parent = 0);
void on_show();
};
class HooksearchText:public mainwindow{
gridlayout* layout;
lineedit* edittext;
button* checkok;
spinbox* codepage;
class HooksearchText : public mainwindow
{
gridlayout *layout;
lineedit *edittext;
button *checkok;
spinbox *codepage;
public:
HooksearchText(mainwindow*);
void call(std::set<DWORD>pids);
HooksearchText(mainwindow *);
void call(std::set<DWORD> pids);
};
class Hooksearchsetting:public mainwindow{
gridlayout* layout;
spinbox* spinduration;
spinbox* spinoffset;
spinbox* spincap;
spinbox* spincodepage;
lineedit* editpattern;
lineedit* editmodule;
lineedit* editmaxaddr;
lineedit* editminaddr;
spinbox* spinpadding;
lineedit* editregex;
button* start;
class Hooksearchsetting : public mainwindow
{
gridlayout *layout;
spinbox *spinduration;
spinbox *spinoffset;
spinbox *spincap;
spinbox *spincodepage;
lineedit *editpattern;
lineedit *editmodule;
lineedit *editmaxaddr;
lineedit *editminaddr;
spinbox *spinpadding;
lineedit *editregex;
button *start;
public:
Hooksearchsetting(mainwindow*);
void call(std::set<DWORD>pids,std::wstring);
Hooksearchsetting(mainwindow *);
void call(std::set<DWORD> pids, std::wstring);
};
class Hooksearchwindow:public mainwindow{
checkbox* cjkcheck;
button* hs_default,*hs_text,*hs_user;
gridlayout* layout;
Hooksearchsetting* hooksearchsetting=0;
HooksearchText* hooksearchText=0;
class Hooksearchwindow : public mainwindow
{
checkbox *cjkcheck;
button *hs_default, *hs_text, *hs_user;
gridlayout *layout;
Hooksearchsetting *hooksearchsetting = 0;
HooksearchText *hooksearchText = 0;
public:
Hooksearchwindow(LunaHost* parent);
Hooksearchwindow(LunaHost *parent);
};
class LunaHost:public mainwindow{
Pluginwindow* pluginwindow=0;
std::set<DWORD>attachedprocess;
lineedit* g_hEdit_userhook;
gridlayout* mainlayout;
button* g_hButton_insert;
button* btnplugin;
//listbox* g_hListBox_listtext;
listview*g_hListBox_listtext;
multilineedit* g_showtexts;
button* g_selectprocessbutton;
button* btndetachall;
button* btnsearchhooks;
button* btnshowsettionwindow;
//button* btnsavehook;
processlistwindow *_processlistwindow=0;
Settingwindow *settingwindow=0;
Pluginmanager* plugins;
Hooksearchwindow * hooksearchwindow=0;
std::atomic<bool> hasstoped=false;
bool on_text_recv(TextThread& thread, std::wstring& sentence);
void on_text_recv_checkissaved(TextThread& thread);
void on_thread_create(TextThread& thread);
void on_thread_delete(TextThread& thread);
class LunaHost : public mainwindow
{
Pluginwindow *pluginwindow = 0;
std::set<DWORD> attachedprocess;
lineedit *g_hEdit_userhook;
gridlayout *mainlayout;
button *g_hButton_insert;
button *btnplugin;
// listbox* g_hListBox_listtext;
listview *g_hListBox_listtext;
multilineedit *g_showtexts;
button *g_selectprocessbutton;
button *btndetachall;
button *btnsearchhooks;
button *btnshowsettionwindow;
// button* btnsavehook;
processlistwindow *_processlistwindow = 0;
Settingwindow *settingwindow = 0;
Pluginmanager *plugins;
Hooksearchwindow *hooksearchwindow = 0;
std::atomic<bool> hasstoped = false;
bool on_text_recv(TextThread &thread, std::wstring &sentence);
void on_text_recv_checkissaved(TextThread &thread);
void on_thread_create(TextThread &thread);
void on_thread_delete(TextThread &thread);
void on_proc_connect(DWORD pid);
void on_proc_disconnect(DWORD pid);
void showtext(const std::wstring&text,bool clear);
void updatelisttext(const std::wstring&text,LONG_PTR data);
void showtext(const std::wstring &text, bool clear);
void updatelisttext(const std::wstring &text, LONG_PTR data);
public:
confighelper* configs;
int64_t currentselect=0;
bool check_toclipboard;
confighelper *configs;
int64_t currentselect = 0;
bool check_toclipboard;
bool check_toclipboard_selection;
std::wstring defaultFont;
Font uifont;
bool autoattach;
bool autoattach_savedonly;
std::set<std::string>autoattachexes;
std::unordered_map<std::string,nlohmann::json>savedhookcontext;
std::set<int>userdetachedpids;
std::set<std::string> autoattachexes;
std::unordered_map<std::string, nlohmann::json> savedhookcontext;
std::set<int> userdetachedpids;
void on_close();
LunaHost();
friend class Settingwindow;
friend class Hooksearchwindow;
private:
void loadsettings();
void savesettings();
void doautoattach();
};

View File

@ -1,11 +1,11 @@
#include<Windows.h>
#include<thread>
#include<mutex>
#include<Shlwapi.h>
#include<filesystem>
#include<queue>
#include"pluginmanager.h"
#include"lockedqueue.hpp"
#include <Windows.h>
#include <thread>
#include <mutex>
#include <Shlwapi.h>
#include <filesystem>
#include <queue>
#include "pluginmanager.h"
#include "lockedqueue.hpp"
#ifndef _WIN64
#define THISCALL __thiscall
#define _CDECL __cdecl
@ -33,115 +33,124 @@
#endif
#define fnQApplication_processEvents "?processEvents@QCoreApplication@@SAXV?$QFlags@W4ProcessEventsFlag@QEventLoop@@@@@Z"
FARPROC QString_fromStdWString, QCoreApplication_addLibraryPath, QString_dtor, QApplication_ctor, QFont_ctor, QFont_dtor, QApplication_setFont, QApplication_exec, QApplication_dtor, QApplication_processEvents;
FARPROC QString_fromStdWString,QCoreApplication_addLibraryPath,QString_dtor,QApplication_ctor,QFont_ctor,QFont_dtor,QApplication_setFont,QApplication_exec,QApplication_dtor,QApplication_processEvents;
bool checkqterror(){
return QString_fromStdWString==0||QCoreApplication_addLibraryPath==0||QString_dtor==0||QApplication_ctor==0||QFont_ctor==0||QFont_dtor==0||QApplication_setFont==0||QApplication_exec==0||QApplication_dtor==0||QApplication_processEvents==0;
bool checkqterror()
{
return QString_fromStdWString == 0 || QCoreApplication_addLibraryPath == 0 || QString_dtor == 0 || QApplication_ctor == 0 || QFont_ctor == 0 || QFont_dtor == 0 || QApplication_setFont == 0 || QApplication_exec == 0 || QApplication_dtor == 0 || QApplication_processEvents == 0;
}
void loadqtdlls(){
QString_fromStdWString=QCoreApplication_addLibraryPath=QString_dtor=QApplication_ctor=QFont_ctor=QFont_dtor=QApplication_setFont=QApplication_exec=QApplication_dtor=QApplication_processEvents=0;
void loadqtdlls()
{
QString_fromStdWString = QCoreApplication_addLibraryPath = QString_dtor = QApplication_ctor = QFont_ctor = QFont_dtor = QApplication_setFont = QApplication_exec = QApplication_dtor = QApplication_processEvents = 0;
auto Qt5Widgets=LoadLibrary(L"Qt5Widgets.dll");
auto Qt5Gui=LoadLibrary(L"Qt5Gui.dll");
auto Qt5Core=LoadLibrary(L"Qt5Core.dll");
if(Qt5Core==0||Qt5Gui==0||Qt5Widgets==0)return;
QString_fromStdWString=GetProcAddress(Qt5Core,fnQString_fromStdWString);
QCoreApplication_addLibraryPath=GetProcAddress(Qt5Core,fnQCoreApplication_addLibraryPath);
QString_dtor=GetProcAddress(Qt5Core,fnQString_dtor);
QApplication_ctor=GetProcAddress(Qt5Widgets,fnQApplication_ctor);
QFont_ctor=GetProcAddress(Qt5Gui,fnQFont_ctor);
QFont_dtor=GetProcAddress(Qt5Gui,fnQFont_dtor);
QApplication_setFont=GetProcAddress(Qt5Widgets,fnQApplication_setFont);
QApplication_exec=GetProcAddress(Qt5Widgets,fnQApplication_exec);
QApplication_dtor=GetProcAddress(Qt5Widgets,fnQApplication_dtor);
QApplication_processEvents=GetProcAddress(Qt5Core,fnQApplication_processEvents);
auto Qt5Widgets = LoadLibrary(L"Qt5Widgets.dll");
auto Qt5Gui = LoadLibrary(L"Qt5Gui.dll");
auto Qt5Core = LoadLibrary(L"Qt5Core.dll");
if (Qt5Core == 0 || Qt5Gui == 0 || Qt5Widgets == 0)
return;
QString_fromStdWString = GetProcAddress(Qt5Core, fnQString_fromStdWString);
QCoreApplication_addLibraryPath = GetProcAddress(Qt5Core, fnQCoreApplication_addLibraryPath);
QString_dtor = GetProcAddress(Qt5Core, fnQString_dtor);
QApplication_ctor = GetProcAddress(Qt5Widgets, fnQApplication_ctor);
QFont_ctor = GetProcAddress(Qt5Gui, fnQFont_ctor);
QFont_dtor = GetProcAddress(Qt5Gui, fnQFont_dtor);
QApplication_setFont = GetProcAddress(Qt5Widgets, fnQApplication_setFont);
QApplication_exec = GetProcAddress(Qt5Widgets, fnQApplication_exec);
QApplication_dtor = GetProcAddress(Qt5Widgets, fnQApplication_dtor);
QApplication_processEvents = GetProcAddress(Qt5Core, fnQApplication_processEvents);
}
struct info{
struct info
{
int type;
std::wstring dll;
HMODULE hdll;
};
lockedqueue<info>waitingtask;
lockedqueue<HMODULE>waitingresult;
lockedqueue<info> waitingtask;
lockedqueue<HMODULE> waitingresult;
extern "C" __declspec(dllexport) void QtStartUp(std::vector<std::wstring>* dlls){
static bool once=false;
if(once)return;
loadqtdlls();
once=!checkqterror();
if(!once)return;
std::thread([=](){
static void* qapp; //必须static
void* qstring;
void* qfont;
for(int i=0;i<dlls->size();i++){
auto dirname=std::filesystem::path(dlls->at(i)).parent_path().wstring();
((void* (_CDECL*)(void*,void*))QString_fromStdWString)(&qstring,&dirname);
((void(_CDECL *)(void*))QCoreApplication_addLibraryPath)(&qstring);
((void(THISCALL*)(void*))QString_dtor)(&qstring);
//QCoreApplication_addLibraryPath(QString_fromStdWString(std::filesystem::path(collectQtplugs[i]).parent_path()));
}
int _=0;
((void*(THISCALL*)(void*,int*,char**,int))QApplication_ctor)(&qapp,&_,0,331266);
std::wstring font=L"MS Shell Dlg 2";
((void* (_CDECL*)(void*,void*))QString_fromStdWString)(&qstring,&font);
((void*(THISCALL*)(void*,void*,int,int,bool))QFont_ctor)(&qfont,&qstring,10,-1,0);
((void(_CDECL*)(void*,void*))QApplication_setFont)(&qfont,0);
((void(THISCALL*)(void*))QFont_dtor)(&qfont);
((void(THISCALL*)(void*))QString_dtor)(&qstring);
while(true)
{
if(!waitingtask.empty())
{
auto top=waitingtask.pop();
if(top.type==1)
extern "C" __declspec(dllexport) void QtStartUp(std::vector<std::wstring> *dlls)
{
static bool once = false;
if (once)
return;
loadqtdlls();
once = !checkqterror();
if (!once)
return;
std::thread([=]()
{
waitingresult.push(LoadLibraryW(top.dll.c_str()));
}
else if(top.type==2)
{
FreeLibrary(top.hdll);
}
}
((void(_CDECL*)(DWORD))QApplication_processEvents)(0);
Sleep(1);
}
// ((void(*)())QApplication_exec)();
// ((void(THISCALL*)(void*))QApplication_dtor)(&qapp);
}).detach();
static void *qapp; // 必须static
void *qstring;
void *qfont;
for (int i = 0; i < dlls->size(); i++)
{
auto dirname = std::filesystem::path(dlls->at(i)).parent_path().wstring();
((void *(_CDECL *)(void *, void *))QString_fromStdWString)(&qstring, &dirname);
((void(_CDECL *)(void *))QCoreApplication_addLibraryPath)(&qstring);
((void(THISCALL *)(void *))QString_dtor)(&qstring);
// QCoreApplication_addLibraryPath(QString_fromStdWString(std::filesystem::path(collectQtplugs[i]).parent_path()));
}
int _ = 0;
((void *(THISCALL *)(void *, int *, char **, int))QApplication_ctor)(&qapp, &_, 0, 331266);
std::wstring font = L"MS Shell Dlg 2";
((void *(_CDECL *)(void *, void *))QString_fromStdWString)(&qstring, &font);
((void *(THISCALL *)(void *, void *, int, int, bool))QFont_ctor)(&qfont, &qstring, 10, -1, 0);
((void(_CDECL *)(void *, void *))QApplication_setFont)(&qfont, 0);
((void(THISCALL *)(void *))QFont_dtor)(&qfont);
((void(THISCALL *)(void *))QString_dtor)(&qstring);
while (true)
{
if (!waitingtask.empty())
{
auto top = waitingtask.pop();
if (top.type == 1)
{
waitingresult.push(LoadLibraryW(top.dll.c_str()));
}
else if (top.type == 2)
{
FreeLibrary(top.hdll);
}
}
((void(_CDECL *)(DWORD))QApplication_processEvents)(0);
Sleep(1);
}
// ((void(*)())QApplication_exec)();
// ((void(THISCALL*)(void*))QApplication_dtor)(&qapp);
})
.detach();
}
std::mutex loadmutex;
extern "C" __declspec(dllexport) std::vector<HMODULE>* QtLoadLibraryBatch(std::vector<std::wstring>* dlls){
extern "C" __declspec(dllexport) std::vector<HMODULE> *QtLoadLibraryBatch(std::vector<std::wstring> *dlls)
{
std::lock_guard _(loadmutex);
QtStartUp(dlls);
auto hdlls=new std::vector<HMODULE>;
for(int i=0;i<dlls->size();i++){
if(checkqterror()){
auto hdlls = new std::vector<HMODULE>;
for (int i = 0; i < dlls->size(); i++)
{
if (checkqterror())
{
hdlls->push_back(0);
}
else{
waitingtask.push({1,dlls->at(i)});
else
{
waitingtask.push({1, dlls->at(i)});
hdlls->push_back(waitingresult.pop());
}
}
return hdlls;
}
extern "C" __declspec(dllexport) void QtFreeLibrary(HMODULE hd){
extern "C" __declspec(dllexport) void QtFreeLibrary(HMODULE hd)
{
std::lock_guard _(loadmutex);
waitingtask.push({2,L"",hd});
waitingtask.push({2, L"", hd});
}

View File

@ -1,9 +1,11 @@
#include"confighelper.h"
#include"stringutils.h"
std::string readfile(const wchar_t* fname) {
FILE* f;
#include "confighelper.h"
#include "stringutils.h"
std::string readfile(const wchar_t *fname)
{
FILE *f;
_wfopen_s(&f, fname, L"rb");
if (f == 0)return {};
if (f == 0)
return {};
fseek(f, 0, SEEK_END);
auto len = ftell(f);
fseek(f, 0, SEEK_SET);
@ -12,29 +14,34 @@ std::string readfile(const wchar_t* fname) {
fread(buff.data(), 1, len, f);
fclose(f);
return buff;
}
void writefile(const wchar_t* fname,const std::string& s){
FILE* f;
}
void writefile(const wchar_t *fname, const std::string &s)
{
FILE *f;
_wfopen_s(&f, fname, L"w");
fprintf(f,"%s",s.c_str());
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()));
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={};
catch (std::exception &)
{
configs = {};
}
if(configs.find("plugins")==configs.end()){
configs["plugins"]={};
if (configs.find("plugins") == configs.end())
{
configs["plugins"] = {};
}
}
confighelper::~confighelper(){
confighelper::~confighelper()
{
writefile(configpath.c_str(), configs.dump(4));
}

View File

@ -1,26 +1,33 @@
#ifndef LUNA_CONFIG_HELPER
#define LUNA_CONFIG_HELPER
#include<nlohmann/json.hpp>
#include <nlohmann/json.hpp>
class confighelper{
class confighelper
{
std::wstring configpath;
public:
nlohmann::json configs;
confighelper();
~confighelper();
template<class T>
T get(const std::string&key,T default1){
if(configs.find(key)==configs.end())return default1;
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;
template <class T>
void set(const std::string &key, T v)
{
configs[key] = v;
}
};
template<typename T>
T safequeryjson(const nlohmann::json& js,const std::string& key,const T &defaultv){
if(js.find(key)==js.end()){
template <typename T>
T safequeryjson(const nlohmann::json &js, const std::string &key, const T &defaultv)
{
if (js.find(key) == js.end())
{
return defaultv;
}
return js[key];

View File

@ -1,279 +1,343 @@
#include"controls.h"
#include"window.h"
#include<commdlg.h>
control::control(mainwindow*_parent){
if(_parent==0)return;
parent=_parent;
#include "controls.h"
#include "window.h"
#include <commdlg.h>
control::control(mainwindow *_parent)
{
if (_parent == 0)
return;
parent = _parent;
parent->controls.push_back(this);
}
void control::dispatch(WPARAM){}
void control::dispatch_2(WPARAM wParam, LPARAM lParam){};
button::button(mainwindow* parent):control(parent){}
button::button(mainwindow* parent,const std::wstring& text):control(parent)
void control::dispatch(WPARAM) {}
void control::dispatch_2(WPARAM wParam, LPARAM lParam) {};
button::button(mainwindow *parent) : control(parent) {}
button::button(mainwindow *parent, const std::wstring &text) : control(parent)
{
winId=CreateWindowEx(0, L"BUTTON", text.c_str(), WS_CHILD | WS_VISIBLE ,
0,0,0,0, parent->winId , NULL, NULL, NULL);
winId = CreateWindowEx(0, L"BUTTON", text.c_str(), WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
}
void button::dispatch(WPARAM wparam){
if(wparam==BN_CLICKED){
void button::dispatch(WPARAM wparam)
{
if (wparam == BN_CLICKED)
{
onclick();
}
}
bool checkbox::ischecked(){
bool checkbox::ischecked()
{
int state = SendMessage(winId, BM_GETCHECK, 0, 0);
return (state == BST_CHECKED);
}
checkbox::checkbox(mainwindow* parent,const std::wstring& text):button(parent)
checkbox::checkbox(mainwindow *parent, const std::wstring &text) : button(parent)
{
winId=CreateWindowEx(0, L"BUTTON", text.c_str(), WS_CHILD | WS_VISIBLE |BS_AUTOCHECKBOX|BS_RIGHTBUTTON,
0,0,0,0, parent->winId , NULL, NULL, NULL);
winId = CreateWindowEx(0, L"BUTTON", text.c_str(), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_RIGHTBUTTON,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
}
void checkbox::setcheck(bool b){
SendMessage(winId, BM_SETCHECK, (WPARAM)BST_CHECKED*b, 0);
void checkbox::setcheck(bool b)
{
SendMessage(winId, BM_SETCHECK, (WPARAM)BST_CHECKED * b, 0);
}
int spinbox::getcurr(){
int spinbox::getcurr()
{
return SendMessage(hUpDown, UDM_GETPOS32, 0, 0);
}
spinbox::spinbox(mainwindow* parent,int value):control(parent){
winId=CreateWindowEx(0, L"EDIT", std::to_wstring(value).c_str(), WS_CHILD | WS_VISIBLE | WS_BORDER|ES_NUMBER ,
0,0,0,0, parent->winId, NULL, NULL, NULL);
spinbox::spinbox(mainwindow *parent, int value) : control(parent)
{
winId = CreateWindowEx(0, L"EDIT", std::to_wstring(value).c_str(), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
hUpDown = CreateWindowEx(0, UPDOWN_CLASS, NULL,
WS_CHILD | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS ,
0, 0, 0, 0,
parent->winId, NULL, NULL, NULL);
WS_CHILD | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,
0, 0, 0, 0,
parent->winId, NULL, NULL, NULL);
SendMessage(hUpDown, UDM_SETBUDDY, (WPARAM)winId, 0);
setminmax(0,0x7fffffff);
std::tie(minv,maxv)= getminmax();
setminmax(0, 0x7fffffff);
std::tie(minv, maxv) = getminmax();
}
void spinbox::setgeo(int x,int y,int w,int h)
void spinbox::setgeo(int x, int y, int w, int h)
{
MoveWindow(winId,x,y,w,h,TRUE);
MoveWindow(winId, x, y, w, h, TRUE);
SendMessage(hUpDown, UDM_SETBUDDY, (WPARAM)winId, 0);
}
void spinbox::setcurr(int cur){
void spinbox::setcurr(int cur)
{
SendMessage(hUpDown, UDM_SETPOS32, 0, cur);
}
void spinbox::dispatch(WPARAM wparam){
if(HIWORD(wparam)==EN_CHANGE){
bool ok=false;int value;
try{
value=std::stoi(text());
ok=true;
void spinbox::dispatch(WPARAM wparam)
{
if (HIWORD(wparam) == EN_CHANGE)
{
bool ok = false;
int value;
try
{
value = std::stoi(text());
ok = true;
}
catch(std::exception&){}
if(ok){
if(value>maxv){
catch (std::exception &)
{
}
if (ok)
{
if (value > maxv)
{
setcurr(maxv);
value=maxv;
value = maxv;
}
else if(value<minv){
else if (value < minv)
{
setcurr(minv);
value=minv;
value = minv;
}
else{
else
{
onvaluechange(value);
}
}
}
}
std::pair<int,int>spinbox::getminmax(){
std::pair<int, int> spinbox::getminmax()
{
int minValue, maxValue;
SendMessage(hUpDown, UDM_GETRANGE32, (WPARAM)&minValue, (LPARAM)&maxValue);
return {minValue,maxValue};
return {minValue, maxValue};
}
void spinbox::setminmax(int min,int max){
SendMessage(hUpDown, UDM_SETRANGE32,min, max);
std::tie(minv,maxv)= getminmax();
void spinbox::setminmax(int min, int max)
{
SendMessage(hUpDown, UDM_SETRANGE32, min, max);
std::tie(minv, maxv) = getminmax();
}
multilineedit::multilineedit(mainwindow* parent):texteditbase(parent){
winId=CreateWindowEx(0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER| ES_MULTILINE |ES_AUTOVSCROLL| WS_VSCROLL ,
0,0,0,0, parent->winId, NULL, NULL, NULL);
multilineedit::multilineedit(mainwindow *parent) : texteditbase(parent)
{
winId = CreateWindowEx(0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
SendMessage(winId, EM_SETLIMITTEXT, 0, 0);
}
std::wstring multilineedit::getsel(){
std::wstring multilineedit::getsel()
{
DWORD start, end;
SendMessage(winId, EM_GETSEL, reinterpret_cast<WPARAM>(&start), reinterpret_cast<LPARAM>(&end));
int length = end - start;
return text().substr(start,length);
return text().substr(start, length);
}
lineedit::lineedit(mainwindow* parent):texteditbase(parent){
winId=CreateWindowEx(0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER| ES_AUTOHSCROLL ,
0,0,0,0, parent->winId, NULL, NULL, NULL);
lineedit::lineedit(mainwindow *parent) : texteditbase(parent)
{
winId = CreateWindowEx(0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
}
texteditbase::texteditbase(mainwindow* parent):control(parent){}
void texteditbase::setreadonly(bool ro){
texteditbase::texteditbase(mainwindow *parent) : control(parent) {}
void texteditbase::setreadonly(bool ro)
{
SendMessage(winId, EM_SETREADONLY, ro, 0);
}
void texteditbase::scrolltoend(){
void texteditbase::scrolltoend()
{
int textLength = GetWindowTextLength(winId);
SendMessage(winId, EM_SETSEL, (WPARAM)textLength, (LPARAM)textLength);
SendMessage(winId, EM_SCROLLCARET, 0, 0);
}
void texteditbase::appendtext(const std::wstring& text){
auto _=std::wstring(L"\r\n")+text;
SendMessage(winId, EM_REPLACESEL, 0, (LPARAM)_.c_str());
void texteditbase::appendtext(const std::wstring &text)
{
auto _ = std::wstring(L"\r\n") + text;
SendMessage(winId, EM_REPLACESEL, 0, (LPARAM)_.c_str());
}
void texteditbase::dispatch(WPARAM wparam){
if(HIWORD(wparam)==EN_CHANGE){
void texteditbase::dispatch(WPARAM wparam)
{
if (HIWORD(wparam) == EN_CHANGE)
{
ontextchange(text());
}
}
label::label(mainwindow* parent,const std::wstring& text):control(parent){
winId=CreateWindowEx(0, L"STATIC", text.c_str(), WS_CHILD | WS_VISIBLE,
0,0,0,0, parent->winId , NULL, NULL, NULL);
label::label(mainwindow *parent, const std::wstring &text) : control(parent)
{
winId = CreateWindowEx(0, L"STATIC", text.c_str(), WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
}
listbox::listbox(mainwindow* parent):control(parent){
winId=CreateWindowEx(WS_EX_CLIENTEDGE, L"LISTBOX", L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_NOTIFY|LBS_NOINTEGRALHEIGHT,
0,0,0,0, parent->winId , NULL, NULL, NULL);
listbox::listbox(mainwindow *parent) : control(parent)
{
winId = CreateWindowEx(WS_EX_CLIENTEDGE, L"LISTBOX", L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT,
0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
}
void listbox::dispatch(WPARAM wparam){
if(HIWORD(wparam) == LBN_SELCHANGE){
auto idx=currentidx();
if(idx!=-1)
void listbox::dispatch(WPARAM wparam)
{
if (HIWORD(wparam) == LBN_SELCHANGE)
{
auto idx = currentidx();
if (idx != -1)
oncurrentchange(idx);
}
}
void listbox::setcurrent(int idx){
void listbox::setcurrent(int idx)
{
SendMessage(winId, LB_SETCURSEL, idx, 0);
if(idx!=-1)
if (idx != -1)
oncurrentchange(idx);
}
int listbox::currentidx(){
int listbox::currentidx()
{
return SendMessage(winId, LB_GETCURSEL, 0, 0);
}
std::wstring listbox::text(int idx){
int textLength = SendMessage(winId, LB_GETTEXTLEN, idx,0);
std::wstring listbox::text(int idx)
{
int textLength = SendMessage(winId, LB_GETTEXTLEN, idx, 0);
std::vector<wchar_t> buffer(textLength + 1);
SendMessage(winId, LB_GETTEXT, idx, (LPARAM)buffer.data());
return buffer.data();
}
void listbox::clear(){
void listbox::clear()
{
SendMessage(winId, LB_RESETCONTENT, 0, 0);
}
int listbox::additem(const std::wstring& text){
int listbox::additem(const std::wstring &text)
{
return SendMessage(winId, LB_ADDSTRING, 0, (LPARAM)text.c_str());
}
void listbox::deleteitem(int i){
void listbox::deleteitem(int i)
{
SendMessage(winId, LB_DELETESTRING, (WPARAM)i, (LPARAM)i);
}
void listbox::setdata(int idx,LONG_PTR data){
SendMessage(winId, LB_SETITEMDATA, idx, (LPARAM)data);
void listbox::setdata(int idx, LONG_PTR data)
{
SendMessage(winId, LB_SETITEMDATA, idx, (LPARAM)data);
}
LONG_PTR listbox::getdata(int idx){
LONG_PTR listbox::getdata(int idx)
{
return SendMessage(winId, LB_GETITEMDATA, idx, 0);
}
int listbox::count(){
return SendMessage(winId, LB_GETCOUNT, 0, 0);
int listbox::count()
{
return SendMessage(winId, LB_GETCOUNT, 0, 0);
}
int listbox::insertitem(int i,const std::wstring& t){
int listbox::insertitem(int i, const std::wstring &t)
{
return SendMessage(winId, LB_INSERTSTRING, i, (LPARAM)t.c_str());
}
void listview::deleteitem(int i){
void listview::deleteitem(int i)
{
std::lock_guard _(lockdataidx);
assodata.erase(assodata.begin() + i);
for(auto& data:remapidx){
if(data.second>=i)
data.second-=1;
for (auto &data : remapidx)
{
if (data.second >= i)
data.second -= 1;
}
ListView_DeleteItem(winId,i);
ListView_DeleteItem(winId, i);
}
listview::listview(mainwindow* parent,bool _addicon,bool notheader):control(parent),addicon(_addicon){
auto style=WS_VISIBLE |WS_VSCROLL| WS_CHILD | LVS_REPORT |LVS_SINGLESEL;
if(notheader)style|=LVS_NOCOLUMNHEADER;
winId=CreateWindowEx(0, WC_LISTVIEW, NULL, style , 0,0,0,0, parent->winId, NULL,NULL, NULL);
listview::listview(mainwindow *parent, bool _addicon, bool notheader) : control(parent), addicon(_addicon)
{
auto style = WS_VISIBLE | WS_VSCROLL | WS_CHILD | LVS_REPORT | LVS_SINGLESEL;
if (notheader)
style |= LVS_NOCOLUMNHEADER;
winId = CreateWindowEx(0, WC_LISTVIEW, NULL, style, 0, 0, 0, 0, parent->winId, NULL, NULL, NULL);
ListView_SetExtendedListViewStyle(winId, LVS_EX_FULLROWSELECT); // Set extended styles
if(addicon){
hImageList = ImageList_Create(22,22, //GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
ILC_COLOR32, 1 ,1);
if (addicon)
{
hImageList = ImageList_Create(22, 22, // GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
ILC_COLOR32, 1, 1);
ListView_SetImageList(winId, hImageList, LVSIL_SMALL);
}
}
int listview::insertcol(int i,const std::wstring& text){
int listview::insertcol(int i, const std::wstring &text)
{
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT;
lvc.pszText = const_cast<LPWSTR>(text.c_str());
//lvc.cx = 100;
// lvc.cx = 100;
return ListView_InsertColumn(winId, i, &lvc);
}
void listview::settext(int row,int col,const std::wstring& text){
ListView_SetItemText(winId,row,col,const_cast<LPWSTR>(text.c_str()));
void listview::settext(int row, int col, const std::wstring &text)
{
ListView_SetItemText(winId, row, col, const_cast<LPWSTR>(text.c_str()));
}
int listview::insertitem(int row,const std::wstring& text,HICON hicon){
int listview::insertitem(int row, const std::wstring &text, HICON hicon)
{
LVITEM lvi;
lvi.pszText = const_cast<LPWSTR>(text.c_str());
lvi.iItem = row;
lvi.iSubItem = 0;
lvi.mask=LVIF_TEXT;
if(addicon && hicon && hImageList){
lvi.mask = LVIF_TEXT;
if (addicon && hicon && hImageList)
{
lvi.mask |= LVIF_IMAGE;
lvi.iImage = ImageList_AddIcon(hImageList, hicon);
}
std::lock_guard _(lockdataidx);
assodata.resize(assodata.size()+1);
assodata.resize(assodata.size() + 1);
std::rotate(assodata.begin() + row, assodata.begin() + row + 1, assodata.end());
for(auto& data:remapidx){
if(data.second>=row)
data.second+=1;
for (auto &data : remapidx)
{
if (data.second >= row)
data.second += 1;
}
return ListView_InsertItem(winId, &lvi);
}
int listview::additem(const std::wstring& text,HICON hicon){
return insertitem(count(),text,hicon);
int listview::additem(const std::wstring &text, HICON hicon)
{
return insertitem(count(), text, hicon);
}
LONG_PTR listview::getdata(int idx){
LONG_PTR listview::getdata(int idx)
{
std::lock_guard _(lockdataidx);
return assodata[idx];
}
int listview::querydataidx(LONG_PTR data){
int listview::querydataidx(LONG_PTR data)
{
std::lock_guard _(lockdataidx);
if(remapidx.find(data)==remapidx.end())return -1;
if (remapidx.find(data) == remapidx.end())
return -1;
return remapidx[data];
}
void listview::setdata(int idx,LONG_PTR data){
void listview::setdata(int idx, LONG_PTR data)
{
std::lock_guard _(lockdataidx);
assodata[idx]=data;
remapidx[data]=idx;
assodata[idx] = data;
remapidx[data] = idx;
}
void listview::clear(){
void listview::clear()
{
ListView_DeleteAllItems(winId);
if(addicon && hImageList)
if (addicon && hImageList)
ImageList_RemoveAll(hImageList);
}
int listview::count(){
int listview::count()
{
return ListView_GetItemCount(winId);
}
int listview::currentidx(){
int listview::currentidx()
{
return ListView_GetNextItem(winId, -1, LVNI_SELECTED);
}
void listview::setcurrent(int idx){
ListView_SetItemState(winId,idx,LVIS_SELECTED,LVIS_SELECTED);
void listview::setcurrent(int idx)
{
ListView_SetItemState(winId, idx, LVIS_SELECTED, LVIS_SELECTED);
}
void listview::dispatch_2(WPARAM wParam, LPARAM lParam){
NMHDR* pnmhdr = (NMHDR*)lParam;
switch (pnmhdr->code){
case LVN_ITEMCHANGED:
{
NMLISTVIEW* pnmListView = (NMLISTVIEW*)lParam;
if ((pnmListView->uChanged & LVIF_STATE) && (pnmListView->uNewState & LVIS_SELECTED))
{
oncurrentchange(pnmListView->iItem);
}
break;
}
void listview::dispatch_2(WPARAM wParam, LPARAM lParam)
{
NMHDR *pnmhdr = (NMHDR *)lParam;
switch (pnmhdr->code)
{
case LVN_ITEMCHANGED:
{
NMLISTVIEW *pnmListView = (NMLISTVIEW *)lParam;
if ((pnmListView->uChanged & LVIF_STATE) && (pnmListView->uNewState & LVIS_SELECTED))
{
oncurrentchange(pnmListView->iItem);
}
break;
}
}
}
std::wstring listview::text(int row,int col){
std::wstring text;text.resize(65535);
std::wstring listview::text(int row, int col)
{
std::wstring text;
text.resize(65535);
LV_ITEM _macro_lvi;
_macro_lvi.iSubItem = (col);
_macro_lvi.cchTextMax = (65535);
@ -281,134 +345,149 @@ std::wstring listview::text(int row,int col){
SNDMSG((winId), LVM_GETITEMTEXT, (WPARAM)(row), (LPARAM)(LV_ITEM *)&_macro_lvi);
return text.c_str();
}
void listview::setheader(const std::vector<std::wstring>& headers){
for(int i=0;i<headers.size();i++){
insertcol(i,headers[i]);
void listview::setheader(const std::vector<std::wstring> &headers)
{
for (int i = 0; i < headers.size(); i++)
{
insertcol(i, headers[i]);
}
headernum=headers.size();
headernum = headers.size();
if(headernum==1)
if (headernum == 1)
ListView_SetColumnWidth(winId, 0, LVSCW_AUTOSIZE_USEHEADER);
else if(headernum==2){
else if (headernum == 2)
{
ListView_SetColumnWidth(winId, 0, 0x180);
}
}
void listview::on_size(int w,int){
if(headernum==1)
void listview::on_size(int w, int)
{
if (headernum == 1)
ListView_SetColumnWidth(winId, 0, LVSCW_AUTOSIZE_USEHEADER);
else if(headernum==2){
auto w0= ListView_GetColumnWidth(winId, 0);
ListView_SetColumnWidth(winId, 1, w-w0);
else if (headernum == 2)
{
auto w0 = ListView_GetColumnWidth(winId, 0);
ListView_SetColumnWidth(winId, 1, w - w0);
}
}
void gridlayout::setgeo(int x,int y,int w,int h){
auto dynarow=maxrow;
auto dynacol=maxcol;
for(auto fw:fixedwidth){
dynacol-=1;
w-=fw.second+margin;
void gridlayout::setgeo(int x, int y, int w, int h)
{
auto dynarow = maxrow;
auto dynacol = maxcol;
for (auto fw : fixedwidth)
{
dynacol -= 1;
w -= fw.second + margin;
}
for(auto fh:fixedheight){
dynarow-=1;
h-=fh.second+margin;
for (auto fh : fixedheight)
{
dynarow -= 1;
h -= fh.second + margin;
}
auto wpercol=(w-margin*(dynacol+1))/dynacol;
auto hperrow=(h-margin*(dynarow+1))/dynarow;
for(auto ctr:savecontrol){
int _x=0,_y=0,_w=0,_h=0;
for(int c=0;c<ctr.col+ctr.colrange;c++)
auto wpercol = (w - margin * (dynacol + 1)) / dynacol;
auto hperrow = (h - margin * (dynarow + 1)) / dynarow;
for (auto ctr : savecontrol)
{
int _x = 0, _y = 0, _w = 0, _h = 0;
for (int c = 0; c < ctr.col + ctr.colrange; c++)
{
if(fixedwidth.find(c)!=fixedwidth.end())
if(c<ctr.col)
_x+=fixedwidth[c];
if (fixedwidth.find(c) != fixedwidth.end())
if (c < ctr.col)
_x += fixedwidth[c];
else
_w+=fixedwidth[c];
_w += fixedwidth[c];
else if (c < ctr.col)
_x += wpercol;
else
if(c<ctr.col)
_x+=wpercol;
else
_w+=wpercol;
_w += wpercol;
}
_x+=(ctr.col+1)*margin;
_w+=(ctr.colrange-1)*margin;
for(int r=0;r<ctr.row+ctr.rowrange;r++)
_x += (ctr.col + 1) * margin;
_w += (ctr.colrange - 1) * margin;
for (int r = 0; r < ctr.row + ctr.rowrange; r++)
{
if(fixedheight.find(r)!=fixedheight.end())
if(r<ctr.row)
_y+=fixedheight[r];
if (fixedheight.find(r) != fixedheight.end())
if (r < ctr.row)
_y += fixedheight[r];
else
_h+=fixedheight[r];
_h += fixedheight[r];
else if (r < ctr.row)
_y += hperrow;
else
if(r<ctr.row)
_y+=hperrow;
else
_h+=hperrow;
_h += hperrow;
}
_y+=(ctr.row+1)*margin;
_h+=(ctr.rowrange-1)*margin;
ctr.ctr->setgeo(_x,_y,_w,_h);
_y += (ctr.row + 1) * margin;
_h += (ctr.rowrange - 1) * margin;
ctr.ctr->setgeo(_x, _y, _w, _h);
}
}
void gridlayout::setfixedwidth(int col,int width){
fixedwidth.insert({col,width});
void gridlayout::setfixedwidth(int col, int width)
{
fixedwidth.insert({col, width});
}
void gridlayout::setfixedheigth(int row,int height){
fixedheight.insert({row,height});
void gridlayout::setfixedheigth(int row, int height)
{
fixedheight.insert({row, height});
}
void gridlayout::addcontrol(control* _c,int row,int col,int rowrange,int colrange){
maxrow=max(maxrow,row+rowrange);
maxcol=max(maxcol,col+colrange);
void gridlayout::addcontrol(control *_c, int row, int col, int rowrange, int colrange)
{
maxrow = max(maxrow, row + rowrange);
maxcol = max(maxcol, col + colrange);
savecontrol.push_back(
{_c,row,col,rowrange,colrange}
);
{_c, row, col, rowrange, colrange});
}
gridlayout::gridlayout(int row,int col):control(0){
maxrow=row;
maxcol=col;
margin=10;
gridlayout::gridlayout(int row, int col) : control(0)
{
maxrow = row;
maxcol = col;
margin = 10;
}
void gridlayout::setmargin(int m){
margin=m;
void gridlayout::setmargin(int m)
{
margin = m;
}
void Menu::dispatch(WPARAM wparam){
auto idx=LOWORD(wparam);
void Menu::dispatch(WPARAM wparam)
{
auto idx = LOWORD(wparam);
menu_callbacks[idx].callback();
DestroyMenu(hmenu);
}
HMENU Menu::load(){
HMENU Menu::load()
{
hmenu = CreatePopupMenu();
for(int i=0;i<menu_callbacks.size();i++){
AppendMenuW(hmenu,menu_callbacks[i].type,i,menu_callbacks[i].str.c_str());
for (int i = 0; i < menu_callbacks.size(); i++)
{
AppendMenuW(hmenu, menu_callbacks[i].type, i, menu_callbacks[i].str.c_str());
}
return hmenu;
}
void Menu::add(const std::wstring& str,std::function<void()> callback){
menu_callbacks.push_back({MF_STRING,callback,str});
void Menu::add(const std::wstring &str, std::function<void()> callback)
{
menu_callbacks.push_back({MF_STRING, callback, str});
}
void Menu::add_checkable(const std::wstring& str,bool check,std::function<void(bool)> callback){
menu_callbacks.push_back({(UINT)(MF_STRING|(check?MF_CHECKED:MF_UNCHECKED)),std::bind(callback,!check),str});
void Menu::add_checkable(const std::wstring &str, bool check, std::function<void(bool)> callback)
{
menu_callbacks.push_back({(UINT)(MF_STRING | (check ? MF_CHECKED : MF_UNCHECKED)), std::bind(callback, !check), str});
}
void Menu::add_sep(){
void Menu::add_sep()
{
menu_callbacks.push_back({MF_SEPARATOR});
}
FontSelector::FontSelector(HWND hwnd,const std::wstring& init,std::function<void(const std::wstring&)>callback){
FontSelector::FontSelector(HWND hwnd, const Font &font, std::function<void(const Font &)> callback)
{
CHOOSEFONTW cf;
ZeroMemory(&cf, sizeof(CHOOSEFONTW));
LOGFONT lf = font.logfont();
cf.lStructSize = sizeof(CHOOSEFONTW);
cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | CF_EFFECTS;
LOGFONT lf;
wcscpy_s(lf.lfFaceName,init.c_str());
cf.hwndOwner = hwnd;
cf.lpLogFont = &lf;
cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; // | CF_EFFECTS;
if (ChooseFontW(&cf))
{
callback(lf.lfFaceName);
Font f{lf.lfFaceName, cf.iPointSize / 10.0f, !!(cf.nFontType & BOLD_FONTTYPE), !!(cf.nFontType & ITALIC_FONTTYPE)};
callback(f);
}
}

View File

@ -1,148 +1,165 @@
#ifndef LUNA_BASE_CONTROLS_H
#define LUNA_BASE_CONTROLS_H
#include"window.h"
#include "window.h"
#include <CommCtrl.h>
class Menu{
class Menu
{
public:
void dispatch(WPARAM);
struct menuinfos{
struct menuinfos
{
UINT type;
std::function<void()> callback;
std::wstring str;
};
std::vector<menuinfos>menu_callbacks;
std::vector<menuinfos> menu_callbacks;
HMENU load();
HMENU hmenu;
void add(const std::wstring&,std::function<void()> callback);
void add_checkable(const std::wstring&,bool,std::function<void(bool)> callback);
void add(const std::wstring &, std::function<void()> callback);
void add_checkable(const std::wstring &, bool, std::function<void(bool)> callback);
void add_sep();
};
using maybehavemenu=std::optional<Menu>;
class control:public basewindow{
public:
mainwindow* parent;
control(mainwindow*);
using maybehavemenu = std::optional<Menu>;
class control : public basewindow
{
public:
mainwindow *parent;
control(mainwindow *);
virtual void dispatch(WPARAM);
virtual void dispatch_2(WPARAM wParam, LPARAM lParam);
maybehavemenu menu;
std::function<maybehavemenu()> on_menu=[]()->maybehavemenu{return {};};
std::function<maybehavemenu()> on_menu = []() -> maybehavemenu
{ return {}; };
};
class button:public control{
class button : public control
{
public:
button(mainwindow* parent);
button(mainwindow*,const std::wstring&);//,int,int,int,int,DWORD=BS_PUSHBUTTON);
button(mainwindow *parent);
button(mainwindow *, const std::wstring &); //,int,int,int,int,DWORD=BS_PUSHBUTTON);
void dispatch(WPARAM);
std::function<void()> onclick=[](){};
std::function<void()> onclick = []() {};
};
class checkbox:public button{
class checkbox : public button
{
public:
checkbox(mainwindow*,const std::wstring&);//,int,int,int,int);
checkbox(mainwindow *, const std::wstring &); //,int,int,int,int);
bool ischecked();
void setcheck(bool);
};
class texteditbase:public control{
class texteditbase : public control
{
public:
texteditbase(mainwindow*);
texteditbase(mainwindow *);
void dispatch(WPARAM);
std::function<void(const std::wstring&)> ontextchange=[&](const std::wstring &text){};
void appendtext(const std::wstring&);
std::function<void(const std::wstring &)> ontextchange = [&](const std::wstring &text) {};
void appendtext(const std::wstring &);
void scrolltoend();
void setreadonly(bool);
};
class multilineedit:public texteditbase{
class multilineedit : public texteditbase
{
public:
multilineedit(mainwindow*);
multilineedit(mainwindow *);
std::wstring getsel();
};
class lineedit:public texteditbase{
class lineedit : public texteditbase
{
public:
lineedit(mainwindow*);
lineedit(mainwindow *);
};
class spinbox:public control{
class spinbox : public control
{
HWND hUpDown;
int minv,maxv;
public:
int minv, maxv;
public:
void dispatch(WPARAM);
spinbox(mainwindow*,int);
void setminmax(int,int);
std::pair<int,int>getminmax();
spinbox(mainwindow *, int);
void setminmax(int, int);
std::pair<int, int> getminmax();
void setcurr(int);
int getcurr();
std::function<void(int)> onvaluechange=[&](int){};
void setgeo(int,int,int,int);
std::function<void(int)> onvaluechange = [&](int) {};
void setgeo(int, int, int, int);
};
class label:public control{
class label : public control
{
public:
label(mainwindow*,const std::wstring&);
label(mainwindow *, const std::wstring &);
};
class listbox:public control{
class listbox : public control
{
public:
listbox(mainwindow*);
listbox(mainwindow *);
void dispatch(WPARAM);
int currentidx();
std::wstring text(int);
std::function<void(int)> oncurrentchange=[](int){};
std::function<void(int)> oncurrentchange = [](int) {};
void clear();
int additem(const std::wstring&);
int additem(const std::wstring &);
void deleteitem(int);
void setdata(int,LONG_PTR);
void setdata(int, LONG_PTR);
void setcurrent(int idx);
int insertitem(int,const std::wstring&);
int insertitem(int, const std::wstring &);
LONG_PTR getdata(int);
int count();
};
class listview:public control{
int headernum=1;
class listview : public control
{
int headernum = 1;
bool addicon;
HIMAGELIST hImageList;
std::vector<LONG_PTR>assodata;
std::map<LONG_PTR,int>remapidx;
std::vector<LONG_PTR> assodata;
std::map<LONG_PTR, int> remapidx;
std::mutex lockdataidx;
public:
listview(mainwindow*,bool,bool);
int insertitem(int,const std::wstring&,HICON hicon=NULL);
void settext(int,int,const std::wstring&);
int insertcol(int,const std::wstring& );
listview(mainwindow *, bool, bool);
int insertitem(int, const std::wstring &, HICON hicon = NULL);
void settext(int, int, const std::wstring &);
int insertcol(int, const std::wstring &);
void clear();
int count();
int currentidx();
void setcurrent(int idx);
std::function<void(int)> oncurrentchange=[](int){};
std::wstring text(int,int=0);
void setheader(const std::vector<std::wstring>&);
std::function<void(int)> oncurrentchange = [](int) {};
std::wstring text(int, int = 0);
void setheader(const std::vector<std::wstring> &);
void deleteitem(int);
int additem(const std::wstring&,HICON hicon=NULL);
int additem(const std::wstring &, HICON hicon = NULL);
LONG_PTR getdata(int);
void setdata(int,LONG_PTR);
void setdata(int, LONG_PTR);
int querydataidx(LONG_PTR);
void dispatch_2(WPARAM wParam, LPARAM lParam);
void on_size(int,int);
void on_size(int, int);
};
class gridlayout:public control{
struct _c{
control* ctr;
int row,col,rowrange,colrange;
class gridlayout : public control
{
struct _c
{
control *ctr;
int row, col, rowrange, colrange;
};
int margin;
int maxrow,maxcol;
std::vector<_c>savecontrol;
std::map<int,int>fixedwidth,fixedheight;
public:
void setgeo(int,int,int,int);
void setfixedwidth(int col,int width);
void setfixedheigth(int row,int height);
void addcontrol(control*,int row,int col,int rowrange=1,int colrange=1);
gridlayout(int row=0,int col=0);
void setmargin(int m=10);
};
int maxrow, maxcol;
std::vector<_c> savecontrol;
std::map<int, int> fixedwidth, fixedheight;
class FontSelector{
public:
FontSelector(HWND hwnd,const std::wstring& init,std::function<void(const std::wstring&)>callback);
void setgeo(int, int, int, int);
void setfixedwidth(int col, int width);
void setfixedheigth(int row, int height);
void addcontrol(control *, int row, int col, int rowrange = 1, int colrange = 1);
gridlayout(int row = 0, int col = 0);
void setmargin(int m = 10);
};
class FontSelector
{
public:
FontSelector(HWND hwnd, const Font &, std::function<void(const Font &)> callback);
};
#endif

View File

@ -4,18 +4,17 @@ using InternetHandle = AutoHandle<Functor<WinHttpCloseHandle>>;
struct HttpRequest
{
HttpRequest(
const wchar_t* agentName,
const wchar_t* serverName,
const wchar_t* action,
const wchar_t* objectName,
const wchar_t *agentName,
const wchar_t *serverName,
const wchar_t *action,
const wchar_t *objectName,
std::string body = "",
const wchar_t* headers = NULL,
const wchar_t *headers = NULL,
DWORD port = INTERNET_DEFAULT_PORT,
const wchar_t* referrer = NULL,
const wchar_t *referrer = NULL,
DWORD requestFlags = WINHTTP_FLAG_SECURE | WINHTTP_FLAG_ESCAPE_DISABLE,
const wchar_t* httpVersion = NULL,
const wchar_t** acceptTypes = NULL
);
const wchar_t *httpVersion = NULL,
const wchar_t **acceptTypes = NULL);
operator bool() { return errorCode == ERROR_SUCCESS; }
std::wstring response;
@ -26,21 +25,21 @@ struct HttpRequest
};
HttpRequest::HttpRequest(
const wchar_t* agentName,
const wchar_t* serverName,
const wchar_t* action,
const wchar_t* objectName,
const wchar_t *agentName,
const wchar_t *serverName,
const wchar_t *action,
const wchar_t *objectName,
std::string body,
const wchar_t* headers,
const wchar_t *headers,
DWORD port,
const wchar_t* referrer,
const wchar_t *referrer,
DWORD requestFlags,
const wchar_t* httpVersion,
const wchar_t** acceptTypes
)
const wchar_t *httpVersion,
const wchar_t **acceptTypes)
{
static std::atomic<HINTERNET> internet = NULL;
if (!internet) internet = WinHttpOpen(agentName, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0);
if (!internet)
internet = WinHttpOpen(agentName, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0);
if (internet)
if (InternetHandle connection = WinHttpConnect(internet, serverName, port, 0))
if (InternetHandle request = WinHttpOpenRequest(connection, action, objectName, httpVersion, referrer, acceptTypes, requestFlags))
@ -48,17 +47,18 @@ HttpRequest::HttpRequest(
{
WinHttpReceiveResponse(request, NULL);
//DWORD size = 0;
//WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &size, WINHTTP_NO_HEADER_INDEX);
//this->headers.resize(size);
//WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, this->headers.data(), &size, WINHTTP_NO_HEADER_INDEX);
// DWORD size = 0;
// WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &size, WINHTTP_NO_HEADER_INDEX);
// this->headers.resize(size);
// WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, this->headers.data(), &size, WINHTTP_NO_HEADER_INDEX);
std::string data;
DWORD availableSize, downloadedSize;
do
{
availableSize = 0;
WinHttpQueryDataAvailable(request, &availableSize);
if (!availableSize) break;
if (!availableSize)
break;
std::vector<char> buffer(availableSize);
WinHttpReadData(request, buffer.data(), availableSize, &downloadedSize);
data.append(buffer.data(), downloadedSize);
@ -67,8 +67,12 @@ HttpRequest::HttpRequest(
this->connection = std::move(connection);
this->request = std::move(request);
}
else errorCode = GetLastError();
else errorCode = GetLastError();
else errorCode = GetLastError();
else errorCode = GetLastError();
else
errorCode = GetLastError();
else
errorCode = GetLastError();
else
errorCode = GetLastError();
else
errorCode = GetLastError();
}

View File

@ -1,28 +1,35 @@
template<class T>
class lockedqueue{
template <class T>
class lockedqueue
{
std::mutex lock;
std::queue<T>data;
std::queue<T> data;
HANDLE hsema;
public:
lockedqueue(){
hsema=CreateSemaphore(NULL,0,65535,NULL);
public:
lockedqueue()
{
hsema = CreateSemaphore(NULL, 0, 65535, NULL);
}
~lockedqueue(){
~lockedqueue()
{
CloseHandle(hsema);
}
void push(T _){
void push(T _)
{
std::lock_guard _l(lock);
data.push(std::move(_));
ReleaseSemaphore(hsema,1,NULL);
ReleaseSemaphore(hsema, 1, NULL);
}
T pop(){
WaitForSingleObject(hsema,INFINITE);
T pop()
{
WaitForSingleObject(hsema, INFINITE);
std::lock_guard _l(lock);
auto _=data.front();
auto _ = data.front();
data.pop();
return _;
}
bool empty(){
bool empty()
{
std::lock_guard _l(lock);
return data.empty();
}

View File

@ -1,5 +1,6 @@
#include"LunaHost.h"
int main(){
#include "LunaHost.h"
int main()
{
SetProcessDPIAware();
LunaHost _lunahost;
_lunahost.show();

View File

@ -1,15 +1,16 @@
#include"pluginmanager.h"
#include<filesystem>
#include"Plugin/extension.h"
#include<fstream>
#include "pluginmanager.h"
#include <filesystem>
#include "Plugin/extension.h"
#include <fstream>
#include <commdlg.h>
#include"LunaHost.h"
#include"Lang/Lang.h"
#include"host.h"
#include "LunaHost.h"
#include "Lang/Lang.h"
#include "host.h"
std::optional<std::wstring>SelectFile(HWND hwnd,LPCWSTR lpstrFilter){
std::optional<std::wstring> SelectFile(HWND hwnd, LPCWSTR lpstrFilter)
{
OPENFILENAME ofn;
wchar_t szFileName[MAX_PATH] = { 0 };
wchar_t szFileName[MAX_PATH] = {0};
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
@ -23,221 +24,268 @@ std::optional<std::wstring>SelectFile(HWND hwnd,LPCWSTR lpstrFilter){
{
return szFileName;
}
else return {};
else
return {};
}
typedef std::vector<HMODULE>* (*QtLoadLibrary_t)(std::vector<std::wstring>* dlls);
typedef std::vector<HMODULE>* (*QtLoadLibraryBatch_t)(std::vector<std::wstring>* dlls);
typedef std::vector<HMODULE> *(*QtLoadLibrary_t)(std::vector<std::wstring> *dlls);
typedef std::vector<HMODULE> *(*QtLoadLibraryBatch_t)(std::vector<std::wstring> *dlls);
typedef void (*QtFreeLibrary_t)(HMODULE hd);
void tryaddqttoenv(std::vector<std::wstring>&collectQtplugs){
static HMODULE qt5core=0;
if(qt5core==0)
void tryaddqttoenv(std::vector<std::wstring> &collectQtplugs)
{
static HMODULE qt5core = 0;
if (qt5core == 0)
{
wchar_t env[65535];
GetEnvironmentVariableW(L"PATH",env,65535);
auto envs=std::wstring(env);
for(auto&p:collectQtplugs){
envs+=L";";envs+=std::filesystem::path(p).parent_path();
GetEnvironmentVariableW(L"PATH", env, 65535);
auto envs = std::wstring(env);
for (auto &p : collectQtplugs)
{
envs += L";";
envs += std::filesystem::path(p).parent_path();
}
SetEnvironmentVariableW(L"PATH",envs.c_str());
qt5core= LoadLibrary(L"Qt5Core.dll");
SetEnvironmentVariableW(L"PATH", envs.c_str());
qt5core = LoadLibrary(L"Qt5Core.dll");
}
}
std::vector<HMODULE>loadqtdllsX(std::vector<std::wstring>&collectQtplugs){
if(collectQtplugs.empty())return {};
std::vector<HMODULE> loadqtdllsX(std::vector<std::wstring> &collectQtplugs)
{
if (collectQtplugs.empty())
return {};
tryaddqttoenv(collectQtplugs);
#if 1
HMODULE base=GetModuleHandle(0);
#else
HMODULE base=LoadLibrary((std::filesystem::current_path()/(x64?"plugin64":"plugin32")/"QtLoader.dll").wstring().c_str());
#endif
//auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(base, "QtLoadLibrary");
auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(base, "QtLoadLibraryBatch");
auto modules=QtLoadLibrary(&collectQtplugs);
#if 1
HMODULE base = GetModuleHandle(0);
#else
HMODULE base = LoadLibrary((std::filesystem::current_path() / (x64 ? "plugin64" : "plugin32") / "QtLoader.dll").wstring().c_str());
#endif
// auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(base, "QtLoadLibrary");
auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(base, "QtLoadLibraryBatch");
auto modules = QtLoadLibrary(&collectQtplugs);
std::vector<HMODULE> _{*modules};
delete modules;
return _;
}
HMODULE loadqtdllsX(const std::wstring&collectQtplugs){
std::vector<std::wstring> _ {collectQtplugs};
HMODULE loadqtdllsX(const std::wstring &collectQtplugs)
{
std::vector<std::wstring> _{collectQtplugs};
return loadqtdllsX(_)[0];
}
void Pluginmanager::loadqtdlls(std::vector<std::wstring>&collectQtplugs){
auto modules=loadqtdllsX(collectQtplugs);
for(int i=0;i<collectQtplugs.size();i++){
OnNewSentenceS[collectQtplugs[i]]={collectQtplugs[i],this,true,modules[i]};
void Pluginmanager::loadqtdlls(std::vector<std::wstring> &collectQtplugs)
{
auto modules = loadqtdllsX(collectQtplugs);
for (int i = 0; i < collectQtplugs.size(); i++)
{
OnNewSentenceS[collectQtplugs[i]] = {collectQtplugs[i], this, true, modules[i]};
}
}
Pluginmanager::Pluginmanager(LunaHost* _host):host(_host),configs(_host->configs){
try {
Pluginmanager::Pluginmanager(LunaHost *_host) : host(_host), configs(_host->configs)
{
try
{
std::scoped_lock lock(OnNewSentenceSLock);
std::vector<std::wstring>collectQtplugs;
for (auto i=0;i<count();i++) {
auto plg=get(i);
bool isqt=plg.isQt;
auto path=plg.wpath();
OnNewSentenceS[path]={};
if(isqt){
if(plg.enable==false)continue;
std::vector<std::wstring> collectQtplugs;
for (auto i = 0; i < count(); i++)
{
auto plg = get(i);
bool isqt = plg.isQt;
auto path = plg.wpath();
OnNewSentenceS[path] = {};
if (isqt)
{
if (plg.enable == false)
continue;
collectQtplugs.push_back((path));
}
else{
auto base=LoadLibraryW(path.c_str());
OnNewSentenceS[path]={path,this,false,base};
else
{
auto base = LoadLibraryW(path.c_str());
OnNewSentenceS[path] = {path, this, false, base};
}
}
loadqtdlls(collectQtplugs);
OnNewSentenceS[L"InternalClipBoard"]={L"",this,false,GetModuleHandle(0)};//内部链接的剪贴板插件
} catch (const std::exception& ex) {
OnNewSentenceS[L"InternalClipBoard"] = {L"", this, false, GetModuleHandle(0)}; // 内部链接的剪贴板插件
}
catch (const std::exception &ex)
{
std::wcerr << "Error: " << ex.what() << std::endl;
}
}
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());
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(int i=0;i<count()+1;i++){
for (int i = 0; i < count() + 1; i++)
{
std::wstring path;
if(i==count())path=L"InternalClipBoard";
else {
if(getenable(i)==false)continue;
path=getname(i);
if (i == count())
path = L"InternalClipBoard";
else
{
if (getenable(i) == false)
continue;
path = getname(i);
}
auto funptr=OnNewSentenceS[path].OnNewSentence;
if(funptr==0)continue;
auto funptr = OnNewSentenceS[path].OnNewSentence;
if (funptr == 0)
continue;
if (!*(sentenceBuffer = funptr(sentenceBuffer, sentenceInfo)))
break;
}
sentence = sentenceBuffer;
HeapFree(GetProcessHeap(), 0, sentenceBuffer);
return !sentence.empty();
sentence = sentenceBuffer;
HeapFree(GetProcessHeap(), 0, sentenceBuffer);
return !sentence.empty();
}
void Pluginmanager::add(const pluginitem& item){
void Pluginmanager::add(const pluginitem &item)
{
configs->configs["plugins"].push_back(item.dump());
}
int Pluginmanager::count(){
int Pluginmanager::count()
{
return configs->configs["plugins"].size();
}
pluginitem Pluginmanager::get(int i){
pluginitem Pluginmanager::get(int i)
{
return pluginitem{configs->configs["plugins"][i]};
}
void Pluginmanager::set(int i,const pluginitem& item){
configs->configs["plugins"][i]=item.dump();
void Pluginmanager::set(int i, const pluginitem &item)
{
configs->configs["plugins"][i] = item.dump();
}
pluginitem::pluginitem(const nlohmann::json& js){
path=js["path"];
isQt=safequeryjson(js,"isQt",false);
isref=safequeryjson(js,"isref",false);
enable=safequeryjson(js,"enable",true);
vissetting=safequeryjson(js,"vissetting",true);
pluginitem::pluginitem(const nlohmann::json &js)
{
path = js["path"];
isQt = safequeryjson(js, "isQt", false);
isref = safequeryjson(js, "isref", false);
enable = safequeryjson(js, "enable", true);
vissetting = safequeryjson(js, "vissetting", true);
}
std::wstring pluginitem::wpath(){
auto wp=StringToWideString(path);
if(isref)return std::filesystem::current_path()/wp;
else return wp;
std::wstring pluginitem::wpath()
{
auto wp = StringToWideString(path);
if (isref)
return std::filesystem::current_path() / wp;
else
return wp;
}
std::pair<std::wstring,bool> castabs2ref(const std::wstring&p){
auto curr=std::filesystem::current_path().wstring();
if(startWith(p,curr)){
return {p.substr(curr.size()+1),true};
std::pair<std::wstring, bool> castabs2ref(const std::wstring &p)
{
auto curr = std::filesystem::current_path().wstring();
if (startWith(p, curr))
{
return {p.substr(curr.size() + 1), true};
}
return {p,false};
return {p, false};
}
pluginitem::pluginitem(const std::wstring& pabs,bool _isQt){
isQt=_isQt;
auto [p,_isref]=castabs2ref(pabs);
isref=_isref;
path=WideStringToString(p);
enable=true;
vissetting=true;
pluginitem::pluginitem(const std::wstring &pabs, bool _isQt)
{
isQt = _isQt;
auto [p, _isref] = castabs2ref(pabs);
isref = _isref;
path = WideStringToString(p);
enable = true;
vissetting = true;
}
nlohmann::json pluginitem::dump() const{
nlohmann::json pluginitem::dump() const
{
return {
{"path",path},
{"isQt",isQt},
{"isref",isref},
{"enable",enable},
{"vissetting",vissetting}
};
}
bool Pluginmanager::getvisible_setable(int idx){
{"path", path},
{"isQt", isQt},
{"isref", isref},
{"enable", enable},
{"vissetting", vissetting}};
}
bool Pluginmanager::getvisible_setable(int idx)
{
return OnNewSentenceS[getname(idx)].VisSetting;
}
bool Pluginmanager::getvisible(int idx){
bool Pluginmanager::getvisible(int idx)
{
return get(idx).vissetting;
}
void Pluginmanager::setvisible(int idx,bool vis){
auto item=get(idx);
item.vissetting=vis;
set(idx,item);
void Pluginmanager::setvisible(int idx, bool vis)
{
auto item = get(idx);
item.vissetting = vis;
set(idx, item);
OnNewSentenceS[getname(idx)].VisSetting(vis);
}
bool Pluginmanager::getenable(int idx){
bool Pluginmanager::getenable(int idx)
{
return get(idx).enable;
}
void Pluginmanager::setenable(int idx,bool en){
auto item=get(idx);
item.enable=en;
set(idx,item);
void Pluginmanager::setenable(int idx, bool en)
{
auto item = get(idx);
item.enable = en;
set(idx, item);
}
std::wstring Pluginmanager::getname(int idx){
std::wstring Pluginmanager::getname(int idx)
{
return get(idx).wpath();
}
bool Pluginmanager::checkisdump(const std::wstring& dll){
for(auto& p:OnNewSentenceS){
if(p.first==dll)return true;
bool Pluginmanager::checkisdump(const std::wstring &dll)
{
for (auto &p : OnNewSentenceS)
{
if (p.first == dll)
return true;
}
return false;
}
void Pluginmanager::unload(const std::wstring& wss){
auto hm=OnNewSentenceS[wss].hmodule;
if(OnNewSentenceS[wss].isQt && hm){
((QtFreeLibrary_t)GetProcAddress(GetModuleHandle(0),"QtFreeLibrary"))(hm);
void Pluginmanager::unload(const std::wstring &wss)
{
auto hm = OnNewSentenceS[wss].hmodule;
if (OnNewSentenceS[wss].isQt && hm)
{
((QtFreeLibrary_t)GetProcAddress(GetModuleHandle(0), "QtFreeLibrary"))(hm);
}
else
FreeLibrary(hm);
OnNewSentenceS[wss].clear();
}
void plugindata::clear(){
hmodule=0;
OnNewSentence=0;
VisSetting=0;
void plugindata::clear()
{
hmodule = 0;
OnNewSentence = 0;
VisSetting = 0;
}
void Pluginmanager::remove(const std::wstring& wss){
void Pluginmanager::remove(const std::wstring &wss)
{
unload(wss);
auto s=WideStringToString(wss);
auto &plgs=configs->configs["plugins"];
auto it=std::remove_if(plgs.begin(),plgs.end(),[&](auto&t){
auto s = WideStringToString(wss);
auto &plgs = configs->configs["plugins"];
auto it = std::remove_if(plgs.begin(), plgs.end(), [&](auto &t)
{
std::string p=t["path"];
return p==s;
});
return p==s; });
plgs.erase(it, plgs.end());
OnNewSentenceS.erase(wss);
}
std::optional<std::wstring>Pluginmanager::selectpluginfile(){
return SelectFile(0,L"Plugin Files\0*.dll;*.xdll\0");
std::optional<std::wstring> Pluginmanager::selectpluginfile()
{
return SelectFile(0, L"Plugin Files\0*.dll;*.xdll\0");
}
void Pluginmanager::swaprank(int a,int b){
auto &plgs=configs->configs["plugins"];
auto _b=plgs[b];
plgs[b]=plgs[a];
plgs[a]=_b;
void Pluginmanager::swaprank(int a, int b)
{
auto &plgs = configs->configs["plugins"];
auto _b = plgs[b];
plgs[b] = plgs[a];
plgs[a] = _b;
}
DWORD Rva2Offset(DWORD rva, PIMAGE_SECTION_HEADER psh, PIMAGE_NT_HEADERS pnt)
{
@ -251,167 +299,190 @@ DWORD Rva2Offset(DWORD rva, PIMAGE_SECTION_HEADER psh, PIMAGE_NT_HEADERS pnt)
for (i = 0; i < pnt->FileHeader.NumberOfSections; i++)
{
if (rva >= pSeh->VirtualAddress && rva < pSeh->VirtualAddress +
pSeh->Misc.VirtualSize)
pSeh->Misc.VirtualSize)
{
break;
}
pSeh++;
}
if(pSeh->VirtualAddress==0||pSeh->PointerToRawData==0)return -1;
if (pSeh->VirtualAddress == 0 || pSeh->PointerToRawData == 0)
return -1;
return (rva - pSeh->VirtualAddress + pSeh->PointerToRawData);
}
std::set<std::string> getimporttable(const std::wstring&pe){
}
std::set<std::string> getimporttable(const std::wstring &pe)
{
AutoHandle handle = CreateFile(pe.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(!handle)return {};
if (!handle)
return {};
DWORD byteread, size = GetFileSize(handle, NULL);
PVOID virtualpointer = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
if(!virtualpointer) return {};
if (!virtualpointer)
return {};
ReadFile(handle, virtualpointer, size, &byteread, NULL);
struct __{
PVOID _ptr;DWORD size;
__(PVOID ptr,DWORD sz):_ptr(ptr),size(sz){}
~__(){
struct __
{
PVOID _ptr;
DWORD size;
__(PVOID ptr, DWORD sz) : _ptr(ptr), size(sz) {}
~__()
{
VirtualFree(_ptr, size, MEM_DECOMMIT);
}
}_(virtualpointer,size);
} _(virtualpointer, size);
if(PIMAGE_DOS_HEADER(virtualpointer)->e_magic!=0x5a4d)
return {};
if (PIMAGE_DOS_HEADER(virtualpointer)->e_magic != 0x5a4d)
return {};
PIMAGE_NT_HEADERS ntheaders = (PIMAGE_NT_HEADERS)(PCHAR(virtualpointer) + PIMAGE_DOS_HEADER(virtualpointer)->e_lfanew);
PIMAGE_NT_HEADERS ntheaders = (PIMAGE_NT_HEADERS)(PCHAR(virtualpointer) + PIMAGE_DOS_HEADER(virtualpointer)->e_lfanew);
auto magic=ntheaders->OptionalHeader.Magic;
if(x64 && (magic!=IMAGE_NT_OPTIONAL_HDR64_MAGIC))return {};
if((!x64)&&(magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC))return {};
auto magic = ntheaders->OptionalHeader.Magic;
if (x64 && (magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC))
return {};
if ((!x64) && (magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC))
return {};
PIMAGE_SECTION_HEADER pSech = IMAGE_FIRST_SECTION(ntheaders);//Pointer to first section header
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; //Pointer to import descriptor
PIMAGE_SECTION_HEADER pSech = IMAGE_FIRST_SECTION(ntheaders); // Pointer to first section header
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; // Pointer to import descriptor
if (ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0)/*if size of the table is 0 - Import Table does not exist */
if (ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0) /*if size of the table is 0 - Import Table does not exist */
return {};
std::set<std::string> ret;
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtualpointer + \
Rva2Offset(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, pSech, ntheaders));
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtualpointer +
Rva2Offset(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, pSech, ntheaders));
while (pImportDescriptor->Name != NULL)
{
//Get the name of each DLL
auto nameoffset=Rva2Offset(pImportDescriptor->Name, pSech, ntheaders);
if(nameoffset==(DWORD)-1)
//无导入
// Get the name of each DLL
auto nameoffset = Rva2Offset(pImportDescriptor->Name, pSech, ntheaders);
if (nameoffset == (DWORD)-1)
// 无导入
return {};
ret.insert((PCHAR)((DWORD_PTR)virtualpointer + nameoffset ));
pImportDescriptor++; //advance to next IMAGE_IMPORT_DESCRIPTOR
ret.insert((PCHAR)((DWORD_PTR)virtualpointer + nameoffset));
pImportDescriptor++; // advance to next IMAGE_IMPORT_DESCRIPTOR
}
return ret;
}
bool qtchecker(const std::set<std::string>& dll)
bool qtchecker(const std::set<std::string> &dll)
{
for(auto qt5:{"Qt5Widgets.dll","Qt5Gui.dll","Qt5Core.dll"})
if(dll.find(qt5)!=dll.end())
for (auto qt5 : {"Qt5Widgets.dll", "Qt5Gui.dll", "Qt5Core.dll"})
if (dll.find(qt5) != dll.end())
return true;
return false;
}
addpluginresult Pluginmanager::load(const std::wstring& p,bool*isqt){
auto importtable=getimporttable(p);
if(importtable.empty())return addpluginresult::invaliddll;
auto isQt=qtchecker(importtable);
if(isqt)*isqt=isQt;
addpluginresult Pluginmanager::load(const std::wstring &p, bool *isqt)
{
auto importtable = getimporttable(p);
if (importtable.empty())
return addpluginresult::invaliddll;
auto isQt = qtchecker(importtable);
if (isqt)
*isqt = isQt;
HMODULE base;
if(isQt){
base=loadqtdllsX(p);
if (isQt)
{
base = loadqtdllsX(p);
}
else{
base=LoadLibraryW(p.c_str());
}
if(base==0)return addpluginresult::invaliddll;
else
{
base = LoadLibraryW(p.c_str());
}
if (base == 0)
return addpluginresult::invaliddll;
std::scoped_lock lock(OnNewSentenceSLock);
OnNewSentenceS[p]={p,this,isQt,base};
if(!OnNewSentenceS[p].valid())
OnNewSentenceS[p] = {p, this, isQt, base};
if (!OnNewSentenceS[p].valid())
return addpluginresult::isnotaplugins;
return addpluginresult::success;
}
bool plugindata::valid(){
bool plugindata::valid()
{
return OnNewSentence;
}
plugindata::plugindata(const std::wstring& p,Pluginmanager* manager,bool _isQt,HMODULE hm){
hmodule=hm;
isQt=_isQt;
OnNewSentence=(OnNewSentence_t)GetProcAddress(hm,"OnNewSentence");
VisSetting=(VisSetting_t)GetProcAddress(hm,"VisSetting");
refpath=p;
if(VisSetting)
plugindata::plugindata(const std::wstring &p, Pluginmanager *manager, bool _isQt, HMODULE hm)
{
hmodule = hm;
isQt = _isQt;
OnNewSentence = (OnNewSentence_t)GetProcAddress(hm, "OnNewSentence");
VisSetting = (VisSetting_t)GetProcAddress(hm, "VisSetting");
refpath = p;
if (VisSetting)
{
auto vis=true;
if(auto plg=manager->get(p))
vis=plg.value().vissetting;
auto vis = true;
if (auto plg = manager->get(p))
vis = plg.value().vissetting;
VisSetting(vis);
}
}
void plugindata::initstatus(const pluginitem& plg){
if(plg.vissetting && VisSetting)
void plugindata::initstatus(const pluginitem &plg)
{
if (plg.vissetting && VisSetting)
VisSetting(true);
}
std::optional<pluginitem> Pluginmanager::get(const std::wstring&p){
for(int i=0;i<count();i++)
std::optional<pluginitem> Pluginmanager::get(const std::wstring &p)
{
for (int i = 0; i < count(); i++)
{
if(getname(i)==p){
if (getname(i) == p)
{
return get(i);
}
}
return {};
}
addpluginresult Pluginmanager::addplugin(const std::wstring& p){
if(checkisdump(p))return addpluginresult::dumplicate;
addpluginresult Pluginmanager::addplugin(const std::wstring &p)
{
if (checkisdump(p))
return addpluginresult::dumplicate;
bool isQt;
auto ret=load(p,&isQt);
if(ret==addpluginresult::success){
add({p,isQt});
auto ret = load(p, &isQt);
if (ret == addpluginresult::success)
{
add({p, isQt});
}
return ret;
}
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)
void (*AddText)(int64_t, const wchar_t *) = [](int64_t number, const wchar_t *text)
{
if (TextThread* thread = Host::GetThread(number)) thread->Push(text);
if (TextThread *thread = Host::GetThread(number))
thread->Push(text);
};
void (*AddSentence)(int64_t, const wchar_t*) = [](int64_t number, const wchar_t* sentence)
void (*AddSentence)(int64_t, const wchar_t *) = [](int64_t number, const wchar_t *sentence)
{
if (TextThread* thread = Host::GetThread(number)) thread->AddSentence(sentence);;
if (TextThread *thread = Host::GetThread(number))
thread->AddSentence(sentence);
;
};
static DWORD SelectedProcessId;
auto currthread=(TextThread*)host->currentselect;
SelectedProcessId=(currthread!=0)?currthread->tp.processId:0;
DWORD (*GetSelectedProcessId)() = [] { return SelectedProcessId; };
auto currthread = (TextThread *)host->currentselect;
SelectedProcessId = (currthread != 0) ? currthread->tp.processId : 0;
DWORD (*GetSelectedProcessId)
() = []
{ return SelectedProcessId; };
return
{ {
{ "HostHWND",(int64_t)host->winId },
{ "toclipboard", host->check_toclipboard },
{ "current select", &thread == currthread },
{ "text number", thread.handle },
{ "process id", thread.tp.processId },
{ "hook address", (int64_t)thread.tp.addr },
{ "text handle", thread.handle },
{ "text name", (int64_t)thread.name.c_str() },
{ "add sentence", (int64_t)AddSentence },
{ "add text", (int64_t)AddText },
{ "get selected process id", (int64_t)GetSelectedProcessId },
{ "void (*AddSentence)(int64_t number, const wchar_t* sentence)", (int64_t)AddSentence },
{ "void (*AddText)(int64_t number, const wchar_t* text)", (int64_t)AddText },
{ "DWORD (*GetSelectedProcessId)()", (int64_t)GetSelectedProcessId },
{ nullptr, 0 } // nullptr marks end of info array
} };
return {{
{"HostHWND", (int64_t)host->winId},
{"toclipboard", host->check_toclipboard},
{"current select", &thread == currthread},
{"text number", thread.handle},
{"process id", thread.tp.processId},
{"hook address", (int64_t)thread.tp.addr},
{"text handle", thread.handle},
{"text name", (int64_t)thread.name.c_str()},
{"add sentence", (int64_t)AddSentence},
{"add text", (int64_t)AddText},
{"get selected process id", (int64_t)GetSelectedProcessId},
{"void (*AddSentence)(int64_t number, const wchar_t* sentence)", (int64_t)AddSentence},
{"void (*AddText)(int64_t number, const wchar_t* text)", (int64_t)AddText},
{"DWORD (*GetSelectedProcessId)()", (int64_t)GetSelectedProcessId},
{nullptr, 0} // nullptr marks end of info array
}};
}

View File

@ -1,30 +1,33 @@
#ifndef LUNA_PLUGINMANAGER_H
#define LUNA_PLUGINMANAGER_H
#include"Plugin/extension.h"
#include"textthread.h"
#include<nlohmann/json.hpp>
#include "Plugin/extension.h"
#include "textthread.h"
#include <nlohmann/json.hpp>
class LunaHost;
class confighelper;
enum class addpluginresult{
enum class addpluginresult
{
success,
invaliddll,
isnotaplugins,
dumplicate
};
struct pluginitem{
struct pluginitem
{
std::string path;
bool isQt;
bool isref;
bool enable;
bool vissetting;
pluginitem(const nlohmann::json&);
pluginitem(const std::wstring&,bool);
pluginitem(const nlohmann::json &);
pluginitem(const std::wstring &, bool);
std::wstring wpath();
nlohmann::json dump() const;
};
class Pluginmanager;
struct plugindata{
typedef wchar_t* (*OnNewSentence_t)(wchar_t*, const InfoForExtension*);
struct plugindata
{
typedef wchar_t *(*OnNewSentence_t)(wchar_t *, const InfoForExtension *);
typedef void (*VisSetting_t)(bool);
std::wstring refpath;
bool isQt;
@ -33,39 +36,41 @@ struct plugindata{
HMODULE hmodule;
void clear();
plugindata(){};
plugindata(const std::wstring&,Pluginmanager*,bool,HMODULE);
plugindata(const std::wstring &, Pluginmanager *, bool, HMODULE);
bool valid();
void initstatus(const pluginitem&);
void initstatus(const pluginitem &);
};
class Pluginmanager{
std::unordered_map<std::wstring,plugindata>OnNewSentenceS;
class Pluginmanager
{
std::unordered_map<std::wstring, plugindata> OnNewSentenceS;
concurrency::reader_writer_lock OnNewSentenceSLock;
bool checkisdump(const std::wstring&);
confighelper* configs;
LunaHost* host;
std::array<InfoForExtension, 20> GetSentenceInfo(TextThread& thread);
void loadqtdlls(std::vector<std::wstring>&collectQtplugs);
bool checkisdump(const std::wstring &);
confighelper *configs;
LunaHost *host;
std::array<InfoForExtension, 20> GetSentenceInfo(TextThread &thread);
void loadqtdlls(std::vector<std::wstring> &collectQtplugs);
public:
Pluginmanager(LunaHost*);
bool dispatch(TextThread&, std::wstring& sentence);
addpluginresult addplugin(const std::wstring&);
std::optional<std::wstring>selectpluginfile();
Pluginmanager(LunaHost *);
bool dispatch(TextThread &, std::wstring &sentence);
addpluginresult addplugin(const std::wstring &);
std::optional<std::wstring> selectpluginfile();
pluginitem get(int);
std::optional<pluginitem> get(const std::wstring&);
std::optional<pluginitem> get(const std::wstring &);
std::wstring getname(int);
bool getenable(int);
void set(int,const pluginitem&);
void setenable(int ,bool);
void set(int, const pluginitem &);
void setenable(int, bool);
int count();
void add(const pluginitem&);
void remove(const std::wstring&);
void unload(const std::wstring&);
addpluginresult load(const std::wstring&,bool*isqt=0);
void swaprank(int,int);
void add(const pluginitem &);
void remove(const std::wstring &);
void unload(const std::wstring &);
addpluginresult load(const std::wstring &, bool *isqt = 0);
void swaprank(int, int);
bool getvisible(int);
bool getvisible_setable(int);
void setvisible(int,bool);
void setvisible(int, bool);
};
#endif

View File

@ -1,13 +1,13 @@
#include <CommCtrl.h>
#include <TlHelp32.h>
#include"host.h"
#include"LunaHost.h"
#include"Lang/Lang.h"
#include<shellapi.h>
std::unordered_map<std::wstring,std::vector<int>> getprocesslist()
#include "host.h"
#include "LunaHost.h"
#include "Lang/Lang.h"
#include <shellapi.h>
std::unordered_map<std::wstring, std::vector<int>> getprocesslist()
{
std::unordered_map<std::wstring,std::vector<int>>exe_pid;
std::unordered_map<std::wstring, std::vector<int>> exe_pid;
AutoHandle<> hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return {};
@ -15,30 +15,32 @@ std::unordered_map<std::wstring,std::vector<int>> getprocesslist()
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
wchar_t buff[65535];
auto currpid=GetCurrentProcessId();
auto currpid = GetCurrentProcessId();
if (Process32First(hSnapshot, &pe32))
{
do
{
auto PROCESS_INJECT_ACCESS = (
PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ);
if(pe32.th32ProcessID==currpid)continue;
auto PROCESS_INJECT_ACCESS = (PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ);
if (pe32.th32ProcessID == currpid)
continue;
AutoHandle<> handle = OpenProcess(PROCESS_INJECT_ACCESS, 0, pe32.th32ProcessID);
if (handle == 0)continue;
if (handle == 0)
continue;
DWORD sz = 65535;
QueryFullProcessImageNameW(handle, 0, buff, &sz);
auto buffs=std::wstring(buff);
auto str=stolower(buffs);
if(str.find(L":\\windows\\")!=str.npos || str.find(L"\\microsoft")!=str.npos|| str.find(L"\\windowsapps")!=str.npos)continue;
if(exe_pid.find(buffs)==exe_pid.end()){
exe_pid.insert({buffs,{}});
auto buffs = std::wstring(buff);
auto str = stolower(buffs);
if (str.find(L":\\windows\\") != str.npos || str.find(L"\\microsoft") != str.npos || str.find(L"\\windowsapps") != str.npos)
continue;
if (exe_pid.find(buffs) == exe_pid.end())
{
exe_pid.insert({buffs, {}});
}
exe_pid[buffs].push_back(pe32.th32ProcessID);
} while (Process32Next(hSnapshot, &pe32));
@ -46,64 +48,79 @@ std::unordered_map<std::wstring,std::vector<int>> getprocesslist()
return exe_pid;
}
void processlistwindow::PopulateProcessList(listview* _listbox,std::unordered_map<std::wstring,std::vector<int>>&exe_pid){
void processlistwindow::PopulateProcessList(listview *_listbox, std::unordered_map<std::wstring, std::vector<int>> &exe_pid)
{
_listbox->clear();
for(auto& exe:exe_pid){
auto hicon=GetExeIcon(exe.first);
_listbox->additem(exe.first,hicon);
for (auto &exe : exe_pid)
{
auto hicon = GetExeIcon(exe.first);
_listbox->additem(exe.first, hicon);
DestroyIcon(hicon);
}
}
processlistwindow::processlistwindow(mainwindow* p):mainwindow(p){
processlistwindow::processlistwindow(mainwindow *p) : mainwindow(p)
{
g_hEdit = new lineedit(this);
g_hButton=new button(this,BtnAttach);
g_refreshbutton =new button(this,BtnRefresh);
g_hButton->onclick=[&](){
auto str=g_hEdit->text();
if(str.size()){
g_hButton = new button(this, BtnAttach);
g_refreshbutton = new button(this, BtnRefresh);
g_hButton->onclick = [&]()
{
auto str = g_hEdit->text();
if (str.size())
{
close();
for(auto _s:strSplit(str,L",")){
DWORD pid=0;
try{
pid=std::stoi(_s);
}catch(std::exception&){}
if(pid)
for (auto _s : strSplit(str, L","))
{
DWORD pid = 0;
try
{
pid = std::stoi(_s);
}
catch (std::exception &)
{
}
if (pid)
Host::InjectProcess(pid);
}
}
};
g_refreshbutton->onclick=[&](){
g_exe_pid=getprocesslist();
PopulateProcessList(g_hListBox,g_exe_pid);
g_refreshbutton->onclick = [&]()
{
g_exe_pid = getprocesslist();
PopulateProcessList(g_hListBox, g_exe_pid);
};
g_hListBox = new listview(this,true,true);
g_hListBox = new listview(this, true, true);
g_hListBox->setheader({L""});
g_hListBox->oncurrentchange=[&](int idx){
auto pids=g_exe_pid[g_hListBox->text(idx)];
g_hListBox->oncurrentchange = [&](int idx)
{
auto pids = g_exe_pid[g_hListBox->text(idx)];
std::wstring _;
bool _1=false;
for(auto &p:pids){
if(_1)_+=L",";
_+=std::to_wstring(p);
_1=true;
}
bool _1 = false;
for (auto &p : pids)
{
if (_1)
_ += L",";
_ += std::to_wstring(p);
_1 = true;
}
g_hEdit->settext(_);
};
settext(WndSelectProcess);
mainlayout=new gridlayout();
mainlayout->addcontrol(g_hEdit,0,0,1,2);
mainlayout->addcontrol(g_hButton,0,2);
mainlayout->addcontrol(g_refreshbutton,0,3);
mainlayout->addcontrol(g_hListBox,1,0,1,4);
mainlayout->setfixedheigth(0,30);
mainlayout = new gridlayout();
mainlayout->addcontrol(g_hEdit, 0, 0, 1, 2);
mainlayout->addcontrol(g_hButton, 0, 2);
mainlayout->addcontrol(g_refreshbutton, 0, 3);
mainlayout->addcontrol(g_hListBox, 1, 0, 1, 4);
mainlayout->setfixedheigth(0, 30);
setlayout(mainlayout);
setcentral(800,400);
setcentral(800, 400);
}
void processlistwindow::on_show(){
void processlistwindow::on_show()
{
g_hEdit->settext(L"");
g_exe_pid=getprocesslist();
PopulateProcessList(g_hListBox,g_exe_pid);
g_exe_pid = getprocesslist();
PopulateProcessList(g_hListBox, g_exe_pid);
}

View File

@ -1,193 +1,225 @@
#include"window.h"
#include"controls.h"
#include"Lang/Lang.h"
#include<shellapi.h>
HICON GetExeIcon(const std::wstring& filePath) {
#include "window.h"
#include "controls.h"
#include "Lang/Lang.h"
#include <shellapi.h>
HICON GetExeIcon(const std::wstring &filePath)
{
SHFILEINFO fileInfo;
HICON hIcon = NULL;
if (SHGetFileInfo(filePath.c_str(), 0, &fileInfo, sizeof(fileInfo), SHGFI_ICON | SHGFI_LARGEICON)) {
if (SHGetFileInfo(filePath.c_str(), 0, &fileInfo, sizeof(fileInfo), SHGFI_ICON | SHGFI_LARGEICON))
{
hIcon = fileInfo.hIcon;
}
return hIcon;
}
void mainwindow::visfont(){
if(hfont==0)hfont=parent->hfont;
if(hfont){
for(auto ctr:controls){
void mainwindow::visfont()
{
if (hfont == 0)
hfont = parent->hfont;
if (hfont)
{
for (auto ctr : controls)
{
SendMessage(ctr->winId, WM_SETFONT, (LPARAM)hfont, TRUE);
}
}
}
void mainwindow::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, fn);
void mainwindow::setfont(const Font &font)
{
hfont = font.hfont();
SendMessage(winId, WM_SETFONT, (WPARAM)hfont, TRUE);
visfont();
for(auto child:childrens){
child->setfont(sz,fn);
for (auto child : childrens)
{
child->setfont(font);
}
}
std::wstring basewindow::text(){
std::wstring basewindow::text()
{
int textLength = GetWindowTextLength(winId);
std::vector<wchar_t> buffer(textLength + 1);
GetWindowText(winId, buffer.data(), buffer.size());
return buffer.data();
}
void basewindow::settext(const std::wstring& text){
SetWindowText(winId,text.c_str());
void basewindow::settext(const std::wstring &text)
{
SetWindowText(winId, text.c_str());
}
void basewindow::setgeo(int x,int y,int w,int h){
MoveWindow(winId,x,y,w,h,TRUE);
on_size(w,h);
void basewindow::setgeo(int x, int y, int w, int h)
{
MoveWindow(winId, x, y, w, h, TRUE);
on_size(w, h);
}
RECT basewindow::getgeo(){
RECT basewindow::getgeo()
{
RECT rect;
GetWindowRect(winId,&rect);
GetWindowRect(winId, &rect);
return rect;
}
LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SHOWWINDOW:
case WM_SHOWWINDOW:
{
on_show();
visfont();
break;
}
case WM_SIZE:
{
int width = LOWORD(lParam);
int height = HIWORD(lParam);
on_size(width, height);
break;
}
case WM_NOTIFY:
{
NMHDR *pnmhdr = (NMHDR *)lParam;
for (auto ctl : controls)
{
on_show();
visfont();
break;
}
case WM_SIZE:
{
int width = LOWORD(lParam);
int height = HIWORD(lParam);
on_size(width,height);
break;
}
case WM_NOTIFY:
{
NMHDR* pnmhdr = (NMHDR*)lParam;
for(auto ctl:controls)
if (pnmhdr->hwndFrom == ctl->winId)
{
if(pnmhdr->hwndFrom==ctl->winId)
ctl->dispatch_2(wParam, lParam);
break;
}
}
}
case WM_COMMAND:
{
if (lParam == 0)
{
for (auto ctl : controls)
{
if (lastcontexthwnd == ctl->winId)
{
ctl->dispatch_2(wParam,lParam);break;
}
}
}
case WM_COMMAND:
{
if(lParam==0){
for(auto ctl:controls){
if(lastcontexthwnd==ctl->winId){
if(ctl->menu)
ctl->menu.value().dispatch(wParam);
break;
}
}
}
else
for(auto ctl:controls){
if((HWND)lParam==ctl->winId){
ctl->dispatch(wParam);break;
}
}
break;
}
case WM_CONTEXTMENU:
{
bool succ=false;lastcontexthwnd=0;
for(auto ctl:controls){
if((HWND)wParam==ctl->winId){
auto hm=ctl->on_menu();
ctl->menu=hm;
if(hm){
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
TrackPopupMenu(hm.value().load(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
xPos, yPos, 0, winId, NULL);
lastcontexthwnd=ctl->winId;
succ=true;
}
if (ctl->menu)
ctl->menu.value().dispatch(wParam);
break;
}
}
if(succ==false)return DefWindowProc(winId, message, wParam, lParam);
break;
}
case WM_CLOSE:
{
on_close();
if(parent==0)PostQuitMessage(0);
else ShowWindow(winId,SW_HIDE);
break;
}
default:
return DefWindowProc(winId, message, wParam, lParam);
else
for (auto ctl : controls)
{
if ((HWND)lParam == ctl->winId)
{
ctl->dispatch(wParam);
break;
}
}
break;
}
case WM_CONTEXTMENU:
{
bool succ = false;
lastcontexthwnd = 0;
for (auto ctl : controls)
{
if ((HWND)wParam == ctl->winId)
{
auto hm = ctl->on_menu();
ctl->menu = hm;
if (hm)
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
TrackPopupMenu(hm.value().load(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
xPos, yPos, 0, winId, NULL);
lastcontexthwnd = ctl->winId;
succ = true;
}
break;
}
}
if (succ == false)
return DefWindowProc(winId, message, wParam, lParam);
break;
}
case WM_CLOSE:
{
on_close();
if (parent == 0)
PostQuitMessage(0);
else
ShowWindow(winId, SW_HIDE);
break;
}
default:
return DefWindowProc(winId, message, wParam, lParam);
}
return 0;
}
std::pair<int,int>mainwindow::calculateXY(int w,int h){
int cx,cy;
if(parent==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;
else
{
auto rect = parent->getgeo();
cx = (rect.left + rect.right) / 2;
cy = (rect.top + rect.bottom) / 2;
}
return {cx-w/2,cy-h/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);
void mainwindow::setcentral(int w, int h)
{
auto [x, y] = calculateXY(w, h);
setgeo(x, y, w, h);
}
void mainwindow::setlayout(control* _l){
layout=_l;
void mainwindow::setlayout(control *_l)
{
layout = _l;
}
mainwindow::mainwindow(mainwindow* _parent){
layout=0;
const wchar_t CLASS_NAME[] = L"LunaHostWindow";
mainwindow::mainwindow(mainwindow *_parent)
{
layout = 0;
const wchar_t CLASS_NAME[] = L"LunaHostWindow";
WNDCLASS wc = {};
wc.lpfnWndProc = [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
mainwindow* _window = reinterpret_cast<mainwindow *>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
if ((!_window)||(_window->winId!=hWnd)) return DefWindowProc(hWnd, message, wParam, lParam);
return _window->wndproc(message,wParam,lParam);
mainwindow *_window = reinterpret_cast<mainwindow *>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
if ((!_window) || (_window->winId != hWnd))
return DefWindowProc(hWnd, message, wParam, lParam);
return _window->wndproc(message, wParam, lParam);
};
wc.hInstance = GetModuleHandle(0);
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW );
wc.hIcon= GetExeIcon(getModuleFilename().value());//LoadIconW(GetModuleHandle(0),L"IDI_ICON1");
static auto _=RegisterClass(&wc);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.hIcon = GetExeIcon(getModuleFilename().value()); // LoadIconW(GetModuleHandle(0),L"IDI_ICON1");
static auto _ = RegisterClass(&wc);
HWND hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,CLASS_NAME,CLASS_NAME,WS_OVERLAPPEDWINDOW,
WS_EX_CLIENTEDGE, CLASS_NAME, CLASS_NAME, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
_parent?_parent->winId:NULL,NULL,GetModuleHandle(0),this
);
_parent ? _parent->winId : NULL, NULL, GetModuleHandle(0), this);
winId = hWnd;
parent=_parent;
if(parent)
parent = _parent;
if (parent)
parent->childrens.push_back(this);
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)this);
}
void mainwindow::show(){
void mainwindow::show()
{
ShowWindow(winId, SW_SHOW);
SetForegroundWindow(winId);
}
void mainwindow::close(){
void mainwindow::close()
{
ShowWindow(winId, SW_HIDE);
}
void mainwindow::run(){
void mainwindow::run()
{
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
@ -196,12 +228,13 @@ void mainwindow::run(){
}
}
void mainwindow::on_close(){}
void mainwindow::on_show(){}
void mainwindow::on_size(int w,int h){
if(layout)
void mainwindow::on_close() {}
void mainwindow::on_show() {}
void mainwindow::on_size(int w, int h)
{
if (layout)
{
layout->setgeo(0,0,w,h);
layout->setgeo(0, 0, w, h);
}
}
void basewindow::on_size(int w,int h){}
void basewindow::on_size(int w, int h) {}

View File

@ -1,37 +1,67 @@
#ifndef LUNA_BASE_WINDOW_H
#define LUNA_BASE_WINDOW_H
class control;
class basewindow{
class basewindow
{
public:
HWND winId;
virtual void setgeo(int,int,int,int);
virtual void on_size(int w,int h);
virtual void setgeo(int, int, int, int);
virtual void on_size(int w, int h);
RECT getgeo();
std::wstring text();
void settext(const std::wstring&);
operator HWND(){return winId;}
void settext(const std::wstring &);
operator HWND() { return winId; }
};
class mainwindow:public basewindow{
HFONT hfont=0;
struct Font
{
std::wstring fontfamily;
float fontsize;
bool bold;
bool italic;
float calc_height() const
{
return MulDiv(fontsize, GetDeviceCaps(GetDC(NULL), LOGPIXELSY), 72);
}
HFONT hfont() const
{
return CreateFontIndirect(&logfont());
}
LOGFONT logfont() const
{
LOGFONT lf;
ZeroMemory(&lf, sizeof(LOGFONT));
wcscpy_s(lf.lfFaceName, fontfamily.c_str());
if (bold)
lf.lfWeight = FW_BOLD;
lf.lfItalic = italic;
lf.lfHeight = calc_height();
return lf;
}
};
class mainwindow : public basewindow
{
HFONT hfont = 0;
public:
void setfont(int,LPCWSTR fn=0);
void setfont(const Font &);
void visfont();
std::vector<control*>controls;
std::vector<mainwindow*>childrens;
mainwindow* parent;
std::vector<control *> controls;
std::vector<mainwindow *> childrens;
mainwindow *parent;
HWND lastcontexthwnd;
control* layout;
control *layout;
virtual void on_show();
virtual void on_close();
void on_size(int w,int h);
mainwindow(mainwindow* _parent=0);
void on_size(int w, int h);
mainwindow(mainwindow *_parent = 0);
LRESULT wndproc(UINT message, WPARAM wParam, LPARAM lParam);
static void run();
void show();
void close();
void setcentral(int,int);
std::pair<int,int>calculateXY(int w,int h);
void setlayout(control*);
void setcentral(int, int);
std::pair<int, int> calculateXY(int w, int h);
void setlayout(control *);
};
HICON GetExeIcon(const std::wstring& filePath);
HICON GetExeIcon(const std::wstring &filePath);
#endif