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{

View File

@ -10,8 +10,10 @@
#include "Lang/Lang.h"
#include "http.hpp"
bool sendclipboarddata_i(const std::wstring&text,HWND hwnd){
if (!OpenClipboard((HWND)hwnd)) return false;
bool sendclipboarddata_i(const std::wstring &text, HWND hwnd)
{
if (!OpenClipboard((HWND)hwnd))
return false;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (text.size() + 1) * sizeof(wchar_t));
memcpy(GlobalLock(hMem), text.c_str(), (text.size() + 1) * sizeof(wchar_t));
EmptyClipboard();
@ -20,20 +22,25 @@ bool sendclipboarddata_i(const std::wstring&text,HWND hwnd){
CloseClipboard();
return true;
}
bool sendclipboarddata(const std::wstring&text,HWND hwnd){
for (int loop = 0; loop < 10; loop++) {
bool sendclipboarddata(const std::wstring &text, HWND hwnd)
{
for (int loop = 0; loop < 10; loop++)
{
auto succ = sendclipboarddata_i(text, hwnd);
if(succ)return true;
if (succ)
return true;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
return false;
}
void LunaHost::on_close(){
void LunaHost::on_close()
{
hasstoped = true;
savesettings();
delete configs;
auto _attachedprocess = attachedprocess;
for(auto pid:_attachedprocess){
for (auto pid : _attachedprocess)
{
Host::DetachProcess(pid);
}
if (_attachedprocess.size())
@ -53,10 +60,17 @@ void LunaHost::savesettings()
configs->set("defaultCodepage", Host::defaultCodepage);
configs->set("autoattachexes", autoattachexes);
configs->set("savedhookcontext", savedhookcontext);
configs->set("DefaultFont",defaultFont);
configs->set("DefaultFont2", WideStringToString(uifont.fontfamily));
configs->set("fontsize", uifont.fontsize);
configs->set("font_italic", uifont.italic);
configs->set("font_bold", uifont.bold);
}
void LunaHost::loadsettings(){
defaultFont=configs->get("DefaultFont",std::wstring(DefaultFont));
void LunaHost::loadsettings()
{
uifont.italic = configs->get("font_italic", false);
uifont.bold = configs->get("font_bold", false);
uifont.fontsize = configs->get("fontsize", 14);
uifont.fontfamily = StringToWideString(configs->get("DefaultFont2", WideStringToString(std::wstring(DefaultFont))));
check_toclipboard_selection = configs->get("ToClipboardSelection", false);
check_toclipboard = configs->get("ToClipboard", false);
autoattach = configs->get("AutoAttach", false);
@ -74,17 +88,23 @@ std::unordered_map<std::wstring,std::vector<int>> getprocesslist();
void LunaHost::doautoattach()
{
if(autoattach==false&&autoattach_savedonly==false)return;
if (autoattach == false && autoattach_savedonly == false)
return;
if(autoattachexes.empty())return;
if (autoattachexes.empty())
return;
for (auto [pexe, pids] : getprocesslist())
{
auto &&u8procname = WideStringToString(pexe);
if(autoattachexes.find(u8procname)==autoattachexes.end())continue;
if(autoattach_savedonly && savedhookcontext.find(u8procname)==savedhookcontext.end())continue;
for(auto pid:pids){
if(userdetachedpids.find(pid)!=userdetachedpids.end())continue;
if (autoattachexes.find(u8procname) == autoattachexes.end())
continue;
if (autoattach_savedonly && savedhookcontext.find(u8procname) == savedhookcontext.end())
continue;
for (auto pid : pids)
{
if (userdetachedpids.find(pid) != userdetachedpids.end())
continue;
if (attachedprocess.find(pid) == attachedprocess.end())
Host::InjectProcess(pid);
@ -92,7 +112,6 @@ void LunaHost::doautoattach()
break;
}
}
void LunaHost::on_proc_disconnect(DWORD pid)
@ -108,9 +127,11 @@ void LunaHost::on_proc_connect(DWORD pid)
{
autoattachexes.insert(WideStringToString(pexe.value()));
auto u8procname = WideStringToString(pexe.value());
if(savedhookcontext.find(u8procname)!=savedhookcontext.end()){
if (savedhookcontext.find(u8procname) != savedhookcontext.end())
{
std::string name = safequeryjson(savedhookcontext[u8procname], "name", std::string());
if(startWith(name,"UserHook")){
if (startWith(name, "UserHook"))
{
if (auto hp = HookCode::Parse(StringToWideString(savedhookcontext[u8procname]["hookcode"])))
Host::InsertHook(pid, hp.value());
}
@ -156,20 +177,23 @@ bool queryversion(WORD *_1, WORD *_2, WORD *_3, WORD *_4)
return true;
}
LunaHost::LunaHost(){
LunaHost::LunaHost()
{
configs = new confighelper;
loadsettings();
setfont(25,defaultFont.c_str());
setfont(uifont);
btnshowsettionwindow = new button(this, BtnShowSettingWindow);
g_selectprocessbutton = new button(this, BtnSelectProcess);
// btnsavehook=new button(this,BtnSaveHook,10,10,10,10);
// btnsavehook->onclick=std::bind(&LunaHost::btnsavehookscallback,this);
btndetachall = new button(this, BtnDetach);
btndetachall->onclick=[&](){
for(auto pid:attachedprocess){
btndetachall->onclick = [&]()
{
for (auto pid : attachedprocess)
{
Host::DetachProcess(pid);
userdetachedpids.insert(pid);
}
@ -179,34 +203,45 @@ LunaHost::LunaHost(){
btnplugin = new button(this, BtnPlugin);
plugins = new Pluginmanager(this);
btnplugin->onclick=[&](){
if(pluginwindow==0) pluginwindow=new Pluginwindow(this,plugins);
btnplugin->onclick = [&]()
{
if (pluginwindow == 0)
pluginwindow = new Pluginwindow(this, plugins);
pluginwindow->show();
};
g_hButton_insert = new button(this, BtnInsertUserHook);
btnshowsettionwindow->onclick=[&](){
if(settingwindow==0) settingwindow=new Settingwindow(this);
btnshowsettionwindow->onclick = [&]()
{
if (settingwindow == 0)
settingwindow = new Settingwindow(this);
settingwindow->show();
};
g_selectprocessbutton->onclick=[&](){
if(_processlistwindow==0) _processlistwindow=new processlistwindow(this);
g_selectprocessbutton->onclick = [&]()
{
if (_processlistwindow == 0)
_processlistwindow = new processlistwindow(this);
_processlistwindow->show();
};
g_hButton_insert->onclick=[&](){
g_hButton_insert->onclick = [&]()
{
auto hp = HookCode::Parse(std::move(g_hEdit_userhook->text()));
if(hp){
for(auto _:attachedprocess){
if (hp)
{
for (auto _ : attachedprocess)
{
Host::InsertHook(_, hp.value());
}
}
else{
else
{
showtext(NotifyInvalidHookCode, false);
}
};
g_hListBox_listtext = new listview(this, false, false);
g_hListBox_listtext->setheader({LIST_HOOK, LIST_TEXT});
g_hListBox_listtext->oncurrentchange=[&](int idx){
g_hListBox_listtext->oncurrentchange = [&](int idx)
{
auto thread_p = g_hListBox_listtext->getdata(idx);
std::wstring get;
currentselect = thread_p;
@ -214,32 +249,35 @@ LunaHost::LunaHost(){
strReplace(copy, L"\n", L"\r\n");
showtext(copy, true);
};
g_hListBox_listtext->on_menu=[&]()->maybehavemenu{
g_hListBox_listtext->on_menu = [&]() -> maybehavemenu
{
auto tt = (TextThread *)g_hListBox_listtext->getdata(g_hListBox_listtext->currentidx());
Menu menu;
menu.add(MenuCopyHookCode,[&,tt](){sendclipboarddata(tt->hp.hookcode,winId);});
menu.add(MenuCopyHookCode, [&, tt]()
{ sendclipboarddata(tt->hp.hookcode, winId); });
menu.add_sep();
menu.add(MenuRemoveHook,[&,tt](){Host::RemoveHook(tt->tp.processId,tt->tp.addr);});
menu.add(MenuDetachProcess,[&,tt](){
menu.add(MenuRemoveHook, [&, tt]()
{ Host::RemoveHook(tt->tp.processId, tt->tp.addr); });
menu.add(MenuDetachProcess, [&, tt]()
{
Host::DetachProcess(tt->tp.processId);
userdetachedpids.insert(tt->tp.processId);
});
userdetachedpids.insert(tt->tp.processId); });
menu.add_sep();
menu.add(MenuRemeberSelect,[&,tt](){
menu.add(MenuRemeberSelect, [&, tt]()
{
if(auto pexe=getModuleFilename(tt->tp.processId))
savedhookcontext[WideStringToString(pexe.value())]={
{"hookcode",WideStringToString(tt->hp.hookcode)},
{"ctx1",tt->tp.ctx},
{"ctx2",tt->tp.ctx2},
{"name",WideStringToString(tt->name)}
};
});
menu.add(MenuForgetSelect,[&,tt](){
}; });
menu.add(MenuForgetSelect, [&, tt]()
{
if(auto pexe=getModuleFilename(tt->tp.processId))
savedhookcontext.erase(WideStringToString(pexe.value()));
});
savedhookcontext.erase(WideStringToString(pexe.value())); });
return menu;
};
@ -247,8 +285,10 @@ LunaHost::LunaHost(){
g_showtexts->setreadonly(true);
btnsearchhooks = new button(this, BtnSearchHook);
btnsearchhooks->onclick=[&](){
if(hooksearchwindow==0) hooksearchwindow=new Hooksearchwindow(this);
btnsearchhooks->onclick = [&]()
{
if (hooksearchwindow == 0)
hooksearchwindow = new Hooksearchwindow(this);
hooksearchwindow->show();
};
@ -257,8 +297,7 @@ LunaHost::LunaHost(){
std::bind(&LunaHost::on_proc_disconnect, this, std::placeholders::_1),
std::bind(&LunaHost::on_thread_create, this, std::placeholders::_1),
std::bind(&LunaHost::on_thread_delete, this, std::placeholders::_1),
std::bind(&LunaHost::on_text_recv,this,std::placeholders::_1,std::placeholders::_2)
);
std::bind(&LunaHost::on_text_recv, this, std::placeholders::_1, std::placeholders::_2));
mainlayout = new gridlayout();
mainlayout->addcontrol(g_selectprocessbutton, 0, 0);
@ -279,7 +318,8 @@ LunaHost::LunaHost(){
std::wstring title = WndLunaHostGui;
settext(title);
std::thread([&](){
std::thread([&]()
{
//https://lunatranslator.xyz/Github/LunaHook/issues/14
std::wstring sel;
while(1)
@ -294,24 +334,26 @@ LunaHost::LunaHost(){
sendclipboarddata(sel,winId);
}
}
}
}).detach();
} })
.detach();
std::thread([&]{
std::thread([&]
{
while(1){
doautoattach();
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}).detach();
} })
.detach();
WORD _1, _2, _3, _4;
WCHAR vs[32];
if(queryversion(&_1,&_2,&_3,&_4)){
if (queryversion(&_1, &_2, &_3, &_4))
{
wsprintf(vs, L" | %s v%d.%d.%d", VersionCurrent, _1, _2, _3);
title += vs;
settext(title);
std::thread([&](){
std::thread([&]()
{
if (HttpRequest httpRequest{
L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
L"lunatranslator.xyz",
@ -325,8 +367,8 @@ LunaHost::LunaHost(){
settext(text()+L" | "+VersionLatest+L" "+ StringToWideString(ver));
}
catch(std::exception&e){}
}
}).detach();
} })
.detach();
}
}
void LunaHost::on_text_recv_checkissaved(TextThread &thread)
@ -334,7 +376,8 @@ void LunaHost::on_text_recv_checkissaved(TextThread& thread)
if (auto exe = getModuleFilename(thread.tp.processId))
{
auto exea = WideStringToString(exe.value());
if(savedhookcontext.find(exea)==savedhookcontext.end())return;
if (savedhookcontext.find(exea) == savedhookcontext.end())
return;
std::string hc = savedhookcontext[exea]["hookcode"];
uint64_t ctx1 = savedhookcontext[exea]["ctx1"];
@ -350,21 +393,20 @@ void LunaHost::on_text_recv_checkissaved(TextThread& thread)
break;
}
}
}
}
}
}
}
std::wstring sanitize(const std::wstring& s1) {
std::wstring sanitize(const std::wstring &s1)
{
std::wstring s = s1;
s.erase(std::remove_if(s.begin(), s.end(), [](wchar_t ch) {
return (ch >= 0xD800 && ch <= 0xDBFF) || (ch >= 0xDC00 && ch <= 0xDFFF);
}), s.end());
s.erase(std::remove_if(s.begin(), s.end(), [](wchar_t ch)
{ return (ch >= 0xD800 && ch <= 0xDBFF) || (ch >= 0xDC00 && ch <= 0xDFFF); }),
s.end());
return s;
}
void LunaHost::showtext(const std::wstring&text,bool clear){
void LunaHost::showtext(const std::wstring &text, bool clear)
{
auto output = sanitize(text);
strReplace(output, L"\n", L"\r\n");
if (clear)
@ -372,34 +414,43 @@ void LunaHost::showtext(const std::wstring&text,bool clear){
g_showtexts->settext(output);
g_showtexts->scrolltoend();
}
else{
else
{
g_showtexts->scrolltoend();
g_showtexts->appendtext(output);
}
}
void LunaHost::updatelisttext(const std::wstring&text,LONG_PTR data){
void LunaHost::updatelisttext(const std::wstring &text, LONG_PTR data)
{
auto idx = g_hListBox_listtext->querydataidx(data);
if(idx>=0){
if (idx >= 0)
{
auto __output = sanitize(text);
strReplace(__output, L"\n", L" ");
if(__output.size()>0x40){
if (__output.size() > 0x40)
{
__output = __output.substr(0, 0x40) + L"...";
}
g_hListBox_listtext->settext(idx, 1, __output);
}
}
bool LunaHost::on_text_recv(TextThread& thread, std::wstring& output){
if(hasstoped)return true;
if(!plugins->dispatch(thread,output))return false;
bool LunaHost::on_text_recv(TextThread &thread, std::wstring &output)
{
if (hasstoped)
return true;
if (!plugins->dispatch(thread, output))
return false;
updatelisttext(output, (LONG_PTR)&thread);
if(currentselect==(LONG_PTR)&thread){
if (currentselect == (LONG_PTR)&thread)
{
showtext(output, false);
}
return true;
}
void LunaHost::on_thread_create(TextThread& thread){
void LunaHost::on_thread_create(TextThread &thread)
{
wchar_t buff[65535];
swprintf_s(buff, L"%I64X:%s:%s:%I32X:%I64X:%I64X",
thread.handle,
@ -407,57 +458,67 @@ void LunaHost::on_thread_create(TextThread& thread){
thread.hp.hookcode,
thread.tp.processId,
thread.tp.ctx,
thread.tp.ctx2
);
thread.tp.ctx2);
int index = g_hListBox_listtext->additem(buff, NULL);
g_hListBox_listtext->setdata(index, (LONG_PTR)&thread);
on_text_recv_checkissaved(thread);
}
void LunaHost::on_thread_delete(TextThread& thread){
void LunaHost::on_thread_delete(TextThread &thread)
{
if (currentselect == (LONG_PTR)&thread)
currentselect = 0;
int count = g_hListBox_listtext->count();
for (int i = 0; i < count; i++) {
for (int i = 0; i < count; i++)
{
auto thread_p = g_hListBox_listtext->getdata(i);
if (thread_p== (LONG_PTR)&thread) {
if (thread_p == (LONG_PTR)&thread)
{
g_hListBox_listtext->deleteitem(i);
break;
}
}
}
Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
int height=30;int curry=10;int space=10;
int labelwidth=300;int spinwidth=200;
Settingwindow::Settingwindow(LunaHost *host) : mainwindow(host)
{
int height = 30;
int curry = 10;
int space = 10;
int labelwidth = 300;
int spinwidth = 200;
g_timeout = new spinbox(this, TextThread::flushDelay);
g_codepage = new spinbox(this, Host::defaultCodepage);
spinmaxbuffsize = new spinbox(this, TextThread::maxBufferSize);
;curry+=height+space;
;
curry += height + space;
spinmaxbuffsize->onvaluechange=[=](int v){
spinmaxbuffsize->onvaluechange = [=](int v)
{
TextThread::maxBufferSize = v;
};
spinmaxhistsize = new spinbox(this, TextThread::maxHistorySize);
;curry+=height+space;
;
curry += height + space;
spinmaxhistsize->onvaluechange=[=](int v){
spinmaxhistsize->onvaluechange = [=](int v)
{
TextThread::maxHistorySize = v;
};
ckbfilterrepeat = new checkbox(this, LblFilterRepeat);
ckbfilterrepeat->onclick=[=](){
ckbfilterrepeat->onclick = [=]()
{
TextThread::filterRepetition = ckbfilterrepeat->ischecked();
};
ckbfilterrepeat->setcheck(TextThread::filterRepetition);
g_check_clipboard = new checkbox(this, BtnToClipboard);
g_check_clipboard->onclick=[=](){
g_check_clipboard->onclick = [=]()
{
host->check_toclipboard = g_check_clipboard->ischecked();
};
g_check_clipboard->setcheck(host->check_toclipboard);
@ -469,45 +530,51 @@ Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
// copyselect->setcheck(host->check_toclipboard_selection);
autoattach = new checkbox(this, LblAutoAttach);
autoattach->onclick=[=](){
autoattach->onclick = [=]()
{
host->autoattach = autoattach->ischecked();
};
autoattach->setcheck(host->autoattach);
autoattach_so = new checkbox(this, LblAutoAttach_savedonly);
autoattach_so->onclick=[=](){
autoattach_so->onclick = [=]()
{
host->autoattach_savedonly = autoattach_so->ischecked();
};
autoattach_so->setcheck(host->autoattach_savedonly);
readonlycheck = new checkbox(this, BtnReadOnly);
readonlycheck->onclick=[=](){
readonlycheck->onclick = [=]()
{
host->g_showtexts->setreadonly(readonlycheck->ischecked());
};
readonlycheck->setcheck(true);
g_timeout->onvaluechange=[=](int v){
g_timeout->onvaluechange = [=](int v)
{
TextThread::flushDelay = v;
};
g_codepage->onvaluechange=[=](int v){
if(IsValidCodePage(v)){
g_codepage->onvaluechange = [=](int v)
{
if (IsValidCodePage(v))
{
Host::defaultCodepage = v;
}
};
g_codepage->setminmax(0, CP_UTF8);
showfont = new lineedit(this);
showfont->settext(host->defaultFont);
showfont->settext(host->uifont.fontfamily);
showfont->setreadonly(true);
selectfont = new button(this, FONTSELECT);
selectfont->onclick=[=](){
FontSelector(winId,host->defaultFont, [=](const std::wstring& _t){
showfont->settext(_t);
host->defaultFont=_t;
host->setfont(25,_t.c_str());
});
selectfont->onclick = [=]()
{
FontSelector(winId, host->uifont, [=](const Font &f)
{
host->uifont=f;
showfont->settext(f.fontfamily);
host->setfont(f); });
};
mainlayout = new gridlayout();
@ -535,15 +602,19 @@ Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
setcentral(600, 500);
settext(WndSetting);
}
void Pluginwindow::on_size(int w,int h){
void Pluginwindow::on_size(int w, int h)
{
listplugins->setgeo(10, 10, w - 20, h - 20);
}
void Pluginwindow::pluginrankmove(int moveoffset){
void Pluginwindow::pluginrankmove(int moveoffset)
{
auto idx = listplugins->currentidx();
if(idx==-1)return;
if (idx == -1)
return;
auto idx2 = idx + moveoffset;
auto a = min(idx, idx2), b = max(idx, idx2);
if(a<0||b>=listplugins->count())return;
if (a < 0 || b >= listplugins->count())
return;
pluginmanager->swaprank(a, b);
auto pa = ((LPCWSTR)listplugins->getdata(a));
@ -553,18 +624,23 @@ void Pluginwindow::pluginrankmove(int moveoffset){
listplugins->insertitem(b, std::filesystem::path(pa).stem());
listplugins->setdata(b, (LONG_PTR)pa);
}
Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginmanager(pl){
Pluginwindow::Pluginwindow(mainwindow *p, Pluginmanager *pl) : mainwindow(p), pluginmanager(pl)
{
static auto listadd=[&](const std::wstring& s){
static auto listadd = [&](const std::wstring &s)
{
auto idx = listplugins->additem(std::filesystem::path(s).stem());
auto _s=new wchar_t[s.size()+1];wcscpy(_s,s.c_str());
auto _s = new wchar_t[s.size() + 1];
wcscpy(_s, s.c_str());
listplugins->setdata(idx, (LONG_PTR)_s);
};
listplugins = new listbox(this);
listplugins->on_menu=[&](){
listplugins->on_menu = [&]()
{
Menu menu;
menu.add(MenuAddPlugin,[&](){
menu.add(MenuAddPlugin, [&]()
{
if(auto f=pluginmanager->selectpluginfile())
switch (auto res=pluginmanager->addplugin(f.value()))
{
@ -578,48 +654,49 @@ Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginm
{addpluginresult::dumplicate,InvalidDump},
};
MessageBoxW(winId,errorlog[res],MsgError,0);
}
});
} });
auto idx = listplugins->currentidx();
if (idx != -1)
{
menu.add(MenuRemovePlugin,[&,idx](){
menu.add(MenuRemovePlugin, [&, idx]()
{
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx));
listplugins->deleteitem(idx);
});
listplugins->deleteitem(idx); });
menu.add_sep();
menu.add(MenuPluginRankUp, std::bind(&Pluginwindow::pluginrankmove, this, -1));
menu.add(MenuPluginRankDown, std::bind(&Pluginwindow::pluginrankmove, this, 1));
menu.add_sep();
menu.add_checkable(MenuPluginEnable,pluginmanager->getenable(idx),[&,idx](bool check){
menu.add_checkable(MenuPluginEnable, pluginmanager->getenable(idx), [&, idx](bool check)
{
pluginmanager->setenable(idx,check);
if(check)
pluginmanager->load((LPCWSTR)listplugins->getdata(idx));
else
pluginmanager->unload((LPCWSTR)listplugins->getdata(idx));
});
pluginmanager->unload((LPCWSTR)listplugins->getdata(idx)); });
if (pluginmanager->getvisible_setable(idx))
menu.add_checkable(MenuPluginVisSetting,pluginmanager->getvisible(idx),[&,idx](bool check){
pluginmanager->setvisible(idx,check);
});
menu.add_checkable(MenuPluginVisSetting, pluginmanager->getvisible(idx), [&, idx](bool check)
{ pluginmanager->setvisible(idx, check); });
}
return menu;
};
for(int i=0;i<pluginmanager->count();i++){
for (int i = 0; i < pluginmanager->count(); i++)
{
listadd(pluginmanager->getname(i));
}
settext(WndPlugins);
setcentral(500, 400);
}
void HooksearchText::call(std::set<DWORD>pids){
void HooksearchText::call(std::set<DWORD> pids)
{
edittext->settext(L"");
checkok->onclick=[&,pids](){
checkok->onclick = [&, pids]()
{
close();
auto cp = codepage->getcurr();
if(!IsValidCodePage(cp)) return;
if (!IsValidCodePage(cp))
return;
SearchParam sp = {};
sp.codepage = cp;
wcsncpy_s(sp.text, edittext->text().c_str(), PATTERN_SIZE - 1);
@ -628,7 +705,8 @@ void HooksearchText::call(std::set<DWORD>pids){
};
show();
}
HooksearchText::HooksearchText(mainwindow* p):mainwindow(p){
HooksearchText::HooksearchText(mainwindow *p) : mainwindow(p)
{
codepage = new spinbox(this, Host::defaultCodepage);
codepage->setminmax(0, CP_UTF8);
@ -643,19 +721,22 @@ HooksearchText::HooksearchText(mainwindow* p):mainwindow(p){
setlayout(layout);
setcentral(500, 200);
}
std::wstring tohex(BYTE* bs,int len){
std::wstring tohex(BYTE *bs, int len)
{
std::wstring buffer;
for (int i = 0; i < len; i += 1){
for (int i = 0; i < len; i += 1)
{
buffer.append(FormatString(L"%02hX ", bs[i]));
}
return buffer;
}
std::wstring addr2hex(uintptr_t addr){
std::wstring addr2hex(uintptr_t addr)
{
return FormatString(L"%p", addr);
}
void realcallsearchhooks(std::set<DWORD>pids,std::wstring filter,SearchParam sp){
void realcallsearchhooks(std::set<DWORD> pids, std::wstring filter, SearchParam sp)
{
auto hooks = std::make_shared<std::vector<std::wstring>>();
@ -666,17 +747,18 @@ void realcallsearchhooks(std::set<DWORD>pids,std::wstring filter,SearchParam sp)
[hooks, filter](HookParam hp, std::wstring text)
{
std::wsmatch matches;
if (std::regex_search(text, matches, std::wregex(filter))) {
if (std::regex_search(text, matches, std::wregex(filter)))
{
hooks->emplace_back(std::wstring(hp.hookcode) + L"=>" + text);
}
});
}
catch (std::exception &e) {
catch (std::exception &e)
{
// std::wcout<<e.what();
return;
}
std::thread([hooks]
{
for (int lastSize = 0; hooks->size() == 0 || hooks->size() != lastSize; Sleep(2000)) lastSize = hooks->size();
@ -685,10 +767,11 @@ void realcallsearchhooks(std::set<DWORD>pids,std::wstring filter,SearchParam sp)
of.open("savehooks.txt");
for (auto line:*hooks) of<<WideStringToString(line)<<"\n";
of.close();
hooks->clear();
}).detach();
hooks->clear(); })
.detach();
}
Hooksearchsetting::Hooksearchsetting(mainwindow* p):mainwindow(p){
Hooksearchsetting::Hooksearchsetting(mainwindow *p) : mainwindow(p)
{
layout = new gridlayout();
SearchParam sp{};
spinduration = new spinbox(this, sp.searchTime);
@ -731,30 +814,36 @@ Hooksearchsetting::Hooksearchsetting(mainwindow* p):mainwindow(p){
setlayout(layout);
setcentral(1000, 600);
}
std::vector<BYTE> hexStringToBytes(const std::wstring& hexString_) {
std::vector<BYTE> hexStringToBytes(const std::wstring &hexString_)
{
auto hexString = hexString_;
strReplace(hexString, L" ", L"");
strReplace(hexString, L"??", FormatString(L"%02hX", XX));
std::vector<BYTE> bytes;
if (hexString.length() % 2 != 0) {
if (hexString.length() % 2 != 0)
{
return {};
}
for (int i = 0; i < hexString.size() / 2; i++) {
for (int i = 0; i < hexString.size() / 2; i++)
{
auto byteValue = std::stoi(hexString.substr(i * 2, 2), nullptr, 16);
bytes.push_back(byteValue);
}
return bytes;
}
void Hooksearchsetting::call(std::set<DWORD>pids,std::wstring reg){
if(pids.empty())return;
void Hooksearchsetting::call(std::set<DWORD> pids, std::wstring reg)
{
if (pids.empty())
return;
if (auto filename = getModuleFilename(*pids.begin()))
editmodule->settext(std::filesystem::path(filename.value()).filename().wstring());
editregex->settext(reg);
spincodepage->setcurr(Host::defaultCodepage);
start->onclick=[&,pids](){
start->onclick = [&, pids]()
{
close();
SearchParam sp{};
sp.searchTime = spinduration->getcurr();
@ -762,12 +851,14 @@ void Hooksearchsetting::call(std::set<DWORD>pids,std::wstring reg){
sp.maxRecords = spincap->getcurr();
sp.codepage = spincodepage->getcurr();
if(editpattern->text().find(L".")==std::wstring::npos){
if (editpattern->text().find(L".") == std::wstring::npos)
{
auto hex = hexStringToBytes(editpattern->text());
memcpy(sp.pattern, hex.data(), hex.size());
sp.length = hex.size();
}
else{
else
{
wcsncpy_s(sp.exportModule, editpattern->text().c_str(), MAX_MODULE_SIZE - 1);
sp.length = 1;
}
@ -780,7 +871,8 @@ void Hooksearchsetting::call(std::set<DWORD>pids,std::wstring reg){
};
show();
}
Hooksearchwindow::Hooksearchwindow(LunaHost* host):mainwindow(host){
Hooksearchwindow::Hooksearchwindow(LunaHost *host) : mainwindow(host)
{
cjkcheck = new checkbox(this, SEARCH_CJK);
hs_default = new button(this, HS_START_HOOK_SEARCH);
@ -803,14 +895,14 @@ Hooksearchwindow::Hooksearchwindow(LunaHost* host):mainwindow(host){
close();
if (type == 1)
{
if(hooksearchText==0) hooksearchText=new HooksearchText(this);
if (hooksearchText == 0)
hooksearchText = new HooksearchText(this);
hooksearchText->call(host->attachedprocess);
return;
}
auto filter = (cjkcheck->ischecked() ? L"[\\u3000-\\ua000]{4,}" : L"[\\u0020-\\u1000]{4,}");
if (type == 0)
{
SearchParam sp = {};
@ -820,11 +912,11 @@ Hooksearchwindow::Hooksearchwindow(LunaHost* host):mainwindow(host){
}
else if (type == 2)
{
if(hooksearchsetting==0) hooksearchsetting=new Hooksearchsetting(this);
if (hooksearchsetting == 0)
hooksearchsetting = new Hooksearchsetting(this);
hooksearchsetting->call(host->attachedprocess, filter);
return;
}
};
hs_default->onclick = std::bind(dohooksearchdispatch, 0);

View File

@ -4,15 +4,18 @@
#include "pluginmanager.h"
#include "confighelper.h"
class LunaHost;
class Pluginwindow:public mainwindow{
class Pluginwindow : public mainwindow
{
listbox *listplugins;
Pluginmanager *pluginmanager;
public:
Pluginwindow(mainwindow *, Pluginmanager *);
void on_size(int w, int h);
void pluginrankmove(int);
};
class Settingwindow:public mainwindow{
class Settingwindow : public mainwindow
{
checkbox *ckbfilterrepeat;
spinbox *g_timeout;
spinbox *g_codepage;
@ -26,11 +29,13 @@ class Settingwindow:public mainwindow{
gridlayout *mainlayout;
lineedit *showfont;
button *selectfont;
public:
Settingwindow(LunaHost *);
};
class processlistwindow:public mainwindow{
class processlistwindow : public mainwindow
{
gridlayout *mainlayout;
lineedit *g_hEdit;
button *g_hButton;
@ -38,20 +43,24 @@ class processlistwindow:public mainwindow{
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);
void on_show();
};
class HooksearchText:public mainwindow{
class HooksearchText : public mainwindow
{
gridlayout *layout;
lineedit *edittext;
button *checkok;
spinbox *codepage;
public:
HooksearchText(mainwindow *);
void call(std::set<DWORD> pids);
};
class Hooksearchsetting:public mainwindow{
class Hooksearchsetting : public mainwindow
{
gridlayout *layout;
spinbox *spinduration;
spinbox *spinoffset;
@ -64,20 +73,24 @@ class Hooksearchsetting:public mainwindow{
spinbox *spinpadding;
lineedit *editregex;
button *start;
public:
Hooksearchsetting(mainwindow *);
void call(std::set<DWORD> pids, std::wstring);
};
class Hooksearchwindow:public mainwindow{
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);
};
class LunaHost:public mainwindow{
class LunaHost : public mainwindow
{
Pluginwindow *pluginwindow = 0;
std::set<DWORD> attachedprocess;
lineedit *g_hEdit_userhook;
@ -106,12 +119,13 @@ class LunaHost:public mainwindow{
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;
bool check_toclipboard_selection;
std::wstring defaultFont;
Font uifont;
bool autoattach;
bool autoattach_savedonly;
std::set<std::string> autoattachexes;
@ -121,10 +135,10 @@ public:
LunaHost();
friend class Settingwindow;
friend class Hooksearchwindow;
private:
void loadsettings();
void savesettings();
void doautoattach();
};

View File

@ -33,20 +33,21 @@
#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;
bool checkqterror(){
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(){
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;
if (Qt5Core == 0 || Qt5Gui == 0 || Qt5Widgets == 0)
return;
QString_fromStdWString = GetProcAddress(Qt5Core, fnQString_fromStdWString);
QCoreApplication_addLibraryPath = GetProcAddress(Qt5Core, fnQCoreApplication_addLibraryPath);
@ -59,7 +60,8 @@ void loadqtdlls(){
QApplication_dtor = GetProcAddress(Qt5Widgets, fnQApplication_dtor);
QApplication_processEvents = GetProcAddress(Qt5Core, fnQApplication_processEvents);
}
struct info{
struct info
{
int type;
std::wstring dll;
HMODULE hdll;
@ -67,18 +69,23 @@ struct info{
lockedqueue<info> waitingtask;
lockedqueue<HMODULE> waitingresult;
extern "C" __declspec(dllexport) void QtStartUp(std::vector<std::wstring>* dlls){
extern "C" __declspec(dllexport) void QtStartUp(std::vector<std::wstring> *dlls)
{
static bool once = false;
if(once)return;
if (once)
return;
loadqtdlls();
once = !checkqterror();
if(!once)return;
std::thread([=](){
if (!once)
return;
std::thread([=]()
{
static void *qapp; // 必须static
void *qstring;
void *qfont;
for(int i=0;i<dlls->size();i++){
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);
@ -117,31 +124,33 @@ extern "C" __declspec(dllexport) void QtStartUp(std::vector<std::wstring>* dlls)
// ((void(*)())QApplication_exec)();
// ((void(THISCALL*)(void*))QApplication_dtor)(&qapp);
}).detach();
})
.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()){
for (int i = 0; i < dlls->size(); i++)
{
if (checkqterror())
{
hdlls->push_back(0);
}
else{
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});
}

View File

@ -1,9 +1,11 @@
#include "confighelper.h"
#include "stringutils.h"
std::string readfile(const wchar_t* fname) {
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);
@ -13,28 +15,33 @@ std::string readfile(const wchar_t* fname) {
fclose(f);
return buff;
}
void writefile(const wchar_t* fname,const std::string& s){
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(){
confighelper::confighelper()
{
configpath = std::filesystem::current_path() / (x64 ? "config64.json" : "config32.json");
try{
try
{
configs = nlohmann::json::parse(readfile(configpath.c_str()));
}
catch(std::exception &){
catch (std::exception &)
{
configs = {};
}
if(configs.find("plugins")==configs.end()){
if (configs.find("plugins") == configs.end())
{
configs["plugins"] = {};
}
}
confighelper::~confighelper(){
confighelper::~confighelper()
{
writefile(configpath.c_str(), configs.dump(4));
}

View File

@ -2,25 +2,32 @@
#define LUNA_CONFIG_HELPER
#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;
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){
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()){
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,8 +1,10 @@
#include "controls.h"
#include "window.h"
#include <commdlg.h>
control::control(mainwindow*_parent){
if(_parent==0)return;
control::control(mainwindow *_parent)
{
if (_parent == 0)
return;
parent = _parent;
parent->controls.push_back(this);
}
@ -14,12 +16,15 @@ 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);
}
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);
}
@ -28,13 +33,16 @@ 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);
}
void checkbox::setcheck(bool b){
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){
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);
@ -51,215 +59,269 @@ void spinbox::setgeo(int x,int y,int w,int h)
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{
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;
}
else if(value<minv){
else if (value < minv)
{
setcurr(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};
}
void spinbox::setminmax(int min,int max){
void spinbox::setminmax(int min, int max)
{
SendMessage(hUpDown, UDM_SETRANGE32, min, max);
std::tie(minv, maxv) = getminmax();
}
multilineedit::multilineedit(mainwindow* parent):texteditbase(parent){
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);
}
lineedit::lineedit(mainwindow* parent):texteditbase(parent){
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){
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){
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){
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){
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){
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)
oncurrentchange(idx);
}
int listbox::currentidx(){
int listbox::currentidx()
{
return SendMessage(winId, LB_GETCURSEL, 0, 0);
}
std::wstring listbox::text(int idx){
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){
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(){
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){
for (auto &data : remapidx)
{
if (data.second >= i)
data.second -= 1;
}
ListView_DeleteItem(winId, i);
}
listview::listview(mainwindow* parent,bool _addicon,bool notheader):control(parent),addicon(_addicon){
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;
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){
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;
return ListView_InsertColumn(winId, i, &lvc);
}
void listview::settext(int row,int col,const std::wstring& text){
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){
if (addicon && hicon && hImageList)
{
lvi.mask |= LVIF_IMAGE;
lvi.iImage = ImageList_AddIcon(hImageList, hicon);
}
std::lock_guard _(lockdataidx);
assodata.resize(assodata.size() + 1);
std::rotate(assodata.begin() + row, assodata.begin() + row + 1, assodata.end());
for(auto& data:remapidx){
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){
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;
}
void listview::clear(){
void listview::clear()
{
ListView_DeleteAllItems(winId);
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){
void listview::setcurrent(int idx)
{
ListView_SetItemState(winId, idx, LVIS_SELECTED, LVIS_SELECTED);
}
void listview::dispatch_2(WPARAM wParam, LPARAM lParam){
void listview::dispatch_2(WPARAM wParam, LPARAM lParam)
{
NMHDR *pnmhdr = (NMHDR *)lParam;
switch (pnmhdr->code){
switch (pnmhdr->code)
{
case LVN_ITEMCHANGED:
{
@ -272,8 +334,10 @@ void listview::dispatch_2(WPARAM wParam, LPARAM lParam){
}
}
}
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,43 +345,51 @@ 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++){
void listview::setheader(const std::vector<std::wstring> &headers)
{
for (int i = 0; i < headers.size(); i++)
{
insertcol(i, headers[i]);
}
headernum = headers.size();
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){
void listview::on_size(int w, int)
{
if (headernum == 1)
ListView_SetColumnWidth(winId, 0, LVSCW_AUTOSIZE_USEHEADER);
else if(headernum==2){
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){
void gridlayout::setgeo(int x, int y, int w, int h)
{
auto dynarow = maxrow;
auto dynacol = maxcol;
for(auto fw:fixedwidth){
for (auto fw : fixedwidth)
{
dynacol -= 1;
w -= fw.second + margin;
}
for(auto fh:fixedheight){
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){
for (auto ctr : savecontrol)
{
int _x = 0, _y = 0, _w = 0, _h = 0;
for (int c = 0; c < ctr.col + ctr.colrange; c++)
@ -327,12 +399,10 @@ void gridlayout::setgeo(int x,int y,int w,int h){
_x += fixedwidth[c];
else
_w += fixedwidth[c];
else
if(c<ctr.col)
else if (c < ctr.col)
_x += wpercol;
else
_w += wpercol;
}
_x += (ctr.col + 1) * margin;
_w += (ctr.colrange - 1) * margin;
@ -343,8 +413,7 @@ void gridlayout::setgeo(int x,int y,int w,int h){
_y += fixedheight[r];
else
_h += fixedheight[r];
else
if(r<ctr.row)
else if (r < ctr.row)
_y += hperrow;
else
_h += hperrow;
@ -355,60 +424,70 @@ void gridlayout::setgeo(int x,int y,int w,int h){
ctr.ctr->setgeo(_x, _y, _w, _h);
}
}
void gridlayout::setfixedwidth(int col,int width){
void gridlayout::setfixedwidth(int col, int width)
{
fixedwidth.insert({col, width});
}
void gridlayout::setfixedheigth(int row,int 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){
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){
gridlayout::gridlayout(int row, int col) : control(0)
{
maxrow = row;
maxcol = col;
margin = 10;
}
void gridlayout::setmargin(int m){
void gridlayout::setmargin(int m)
{
margin = m;
}
void Menu::dispatch(WPARAM 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++){
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){
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){
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

@ -2,10 +2,12 @@
#define LUNA_BASE_CONTROLS_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;
@ -19,31 +21,35 @@ public:
};
using maybehavemenu = std::optional<Menu>;
class control:public basewindow{
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);
void dispatch(WPARAM);
std::function<void()> onclick = []() {};
};
class checkbox:public button{
class checkbox : public button
{
public:
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 *);
void dispatch(WPARAM);
@ -52,18 +58,22 @@ public:
void scrolltoend();
void setreadonly(bool);
};
class multilineedit:public texteditbase{
class multilineedit : public texteditbase
{
public:
multilineedit(mainwindow *);
std::wstring getsel();
};
class lineedit:public texteditbase{
class lineedit : public texteditbase
{
public:
lineedit(mainwindow *);
};
class spinbox:public control{
class spinbox : public control
{
HWND hUpDown;
int minv, maxv;
public:
void dispatch(WPARAM);
spinbox(mainwindow *, int);
@ -74,12 +84,14 @@ class spinbox:public control{
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 &);
};
class listbox:public control{
class listbox : public control
{
public:
listbox(mainwindow *);
void dispatch(WPARAM);
@ -95,13 +107,15 @@ public:
LONG_PTR getdata(int);
int count();
};
class listview:public control{
class listview : public control
{
int headernum = 1;
bool addicon;
HIMAGELIST hImageList;
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);
@ -123,8 +137,10 @@ public:
void dispatch_2(WPARAM wParam, LPARAM lParam);
void on_size(int, int);
};
class gridlayout:public control{
struct _c{
class gridlayout : public control
{
struct _c
{
control *ctr;
int row, col, rowrange, colrange;
};
@ -132,6 +148,7 @@ class gridlayout:public control{
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);
@ -140,9 +157,9 @@ public:
gridlayout(int row = 0, int col = 0);
void setmargin(int m = 10);
};
class FontSelector{
class FontSelector
{
public:
FontSelector(HWND hwnd,const std::wstring& init,std::function<void(const std::wstring&)>callback);
FontSelector(HWND hwnd, const Font &, std::function<void(const Font &)> callback);
};
#endif

View File

@ -14,8 +14,7 @@ struct HttpRequest
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 **acceptTypes = NULL);
operator bool() { return errorCode == ERROR_SUCCESS; }
std::wstring response;
@ -36,11 +35,11 @@ HttpRequest::HttpRequest(
const wchar_t *referrer,
DWORD requestFlags,
const wchar_t *httpVersion,
const wchar_t** acceptTypes
)
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))
@ -58,7 +57,8 @@ HttpRequest::HttpRequest(
{
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{
class lockedqueue
{
std::mutex lock;
std::queue<T> data;
HANDLE hsema;
public:
lockedqueue(){
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);
}
T pop(){
T pop()
{
WaitForSingleObject(hsema, INFINITE);
std::lock_guard _l(lock);
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(){
int main()
{
SetProcessDPIAware();
LunaHost _lunahost;
_lunahost.show();

View File

@ -7,7 +7,8 @@
#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};
@ -23,27 +24,33 @@ 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 void (*QtFreeLibrary_t)(HMODULE hd);
void tryaddqttoenv(std::vector<std::wstring>&collectQtplugs){
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();
for (auto &p : collectQtplugs)
{
envs += L";";
envs += std::filesystem::path(p).parent_path();
}
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);
@ -60,31 +67,40 @@ std::vector<HMODULE>loadqtdllsX(std::vector<std::wstring>&collectQtplugs){
delete modules;
return _;
}
HMODULE loadqtdllsX(const 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){
void Pluginmanager::loadqtdlls(std::vector<std::wstring> &collectQtplugs)
{
auto modules = loadqtdllsX(collectQtplugs);
for(int i=0;i<collectQtplugs.size();i++){
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++) {
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;
if (isqt)
{
if (plg.enable == false)
continue;
collectQtplugs.push_back((path));
}
else{
else
{
auto base = LoadLibraryW(path.c_str());
OnNewSentenceS[path] = {path, this, false, base};
}
@ -92,29 +108,35 @@ Pluginmanager::Pluginmanager(LunaHost* _host):host(_host),configs(_host->configs
loadqtdlls(collectQtplugs);
OnNewSentenceS[L"InternalClipBoard"] = {L"", this, false, GetModuleHandle(0)}; // 内部链接的剪贴板插件
} catch (const std::exception& ex) {
}
catch (const std::exception &ex)
{
std::wcerr << "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(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;
if (i == count())
path = L"InternalClipBoard";
else
{
if (getenable(i) == false)
continue;
path = getname(i);
}
auto funptr = OnNewSentenceS[path].OnNewSentence;
if(funptr==0)continue;
if (funptr == 0)
continue;
if (!*(sentenceBuffer = funptr(sentenceBuffer, sentenceInfo)))
break;
}
@ -124,40 +146,51 @@ bool Pluginmanager::dispatch(TextThread& thread, std::wstring& sentence){
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){
void Pluginmanager::set(int i, const pluginitem &item)
{
configs->configs["plugins"][i] = item.dump();
}
pluginitem::pluginitem(const nlohmann::json& js){
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(){
std::wstring pluginitem::wpath()
{
auto wp = StringToWideString(path);
if(isref)return std::filesystem::current_path()/wp;
else return wp;
if (isref)
return std::filesystem::current_path() / wp;
else
return wp;
}
std::pair<std::wstring,bool> castabs2ref(const std::wstring&p){
std::pair<std::wstring, bool> castabs2ref(const std::wstring &p)
{
auto curr = std::filesystem::current_path().wstring();
if(startWith(p,curr)){
if (startWith(p, curr))
{
return {p.substr(curr.size() + 1), true};
}
return {p, false};
}
pluginitem::pluginitem(const std::wstring& pabs,bool _isQt){
pluginitem::pluginitem(const std::wstring &pabs, bool _isQt)
{
isQt = _isQt;
auto [p, _isref] = castabs2ref(pabs);
isref = _isref;
@ -165,47 +198,58 @@ pluginitem::pluginitem(const std::wstring& pabs,bool _isQt){
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}
};
{"vissetting", vissetting}};
}
bool Pluginmanager::getvisible_setable(int idx){
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){
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){
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){
void Pluginmanager::unload(const std::wstring &wss)
{
auto hm = OnNewSentenceS[wss].hmodule;
if(OnNewSentenceS[wss].isQt && hm){
if (OnNewSentenceS[wss].isQt && hm)
{
((QtFreeLibrary_t)GetProcAddress(GetModuleHandle(0), "QtFreeLibrary"))(hm);
}
else
@ -213,27 +257,31 @@ void Pluginmanager::unload(const std::wstring& wss){
OnNewSentenceS[wss].clear();
}
void plugindata::clear(){
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 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(){
std::optional<std::wstring> Pluginmanager::selectpluginfile()
{
return SelectFile(0, L"Plugin Files\0*.dll;*.xdll\0");
}
void Pluginmanager::swaprank(int a,int b){
void Pluginmanager::swaprank(int a, int b)
{
auto &plgs = configs->configs["plugins"];
auto _b = plgs[b];
plgs[b] = plgs[a];
@ -257,44 +305,51 @@ DWORD Rva2Offset(DWORD rva, PIMAGE_SECTION_HEADER psh, PIMAGE_NT_HEADERS pnt)
}
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;
struct __
{
PVOID _ptr;
DWORD size;
__(PVOID ptr, DWORD sz) : _ptr(ptr), size(sz) {}
~__(){
~__()
{
VirtualFree(_ptr, size, MEM_DECOMMIT);
}
} _(virtualpointer, size);
if (PIMAGE_DOS_HEADER(virtualpointer)->e_magic != 0x5a4d)
return {};
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 {};
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
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 + \
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtualpointer +
Rva2Offset(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, pSech, ntheaders));
while (pImportDescriptor->Name != NULL)
@ -309,7 +364,6 @@ std::set<std::string> getimporttable(const std::wstring&pe){
pImportDescriptor++; // advance to next IMAGE_IMPORT_DESCRIPTOR
}
return ret;
}
bool qtchecker(const std::set<std::string> &dll)
{
@ -318,20 +372,26 @@ bool qtchecker(const std::set<std::string>& dll)
return true;
return false;
}
addpluginresult Pluginmanager::load(const std::wstring& p,bool*isqt){
addpluginresult Pluginmanager::load(const std::wstring &p, bool *isqt)
{
auto importtable = getimporttable(p);
if(importtable.empty())return addpluginresult::invaliddll;
if (importtable.empty())
return addpluginresult::invaliddll;
auto isQt = qtchecker(importtable);
if(isqt)*isqt=isQt;
if (isqt)
*isqt = isQt;
HMODULE base;
if(isQt){
if (isQt)
{
base = loadqtdllsX(p);
}
else{
else
{
base = LoadLibraryW(p.c_str());
}
if(base==0)return addpluginresult::invaliddll;
if (base == 0)
return addpluginresult::invaliddll;
std::scoped_lock lock(OnNewSentenceSLock);
@ -340,10 +400,12 @@ addpluginresult Pluginmanager::load(const std::wstring& p,bool*isqt){
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){
plugindata::plugindata(const std::wstring &p, Pluginmanager *manager, bool _isQt, HMODULE hm)
{
hmodule = hm;
isQt = _isQt;
OnNewSentence = (OnNewSentence_t)GetProcAddress(hm, "OnNewSentence");
@ -357,47 +419,56 @@ plugindata::plugindata(const std::wstring& p,Pluginmanager* manager,bool _isQt,H
VisSetting(vis);
}
}
void plugindata::initstatus(const pluginitem& plg){
void plugindata::initstatus(const pluginitem &plg)
{
if (plg.vissetting && VisSetting)
VisSetting(true);
}
std::optional<pluginitem> Pluginmanager::get(const std::wstring&p){
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){
if (ret == addpluginresult::success)
{
add({p, isQt});
}
return ret;
}
std::array<InfoForExtension, 20> Pluginmanager::GetSentenceInfo(TextThread &thread)
{
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)
{
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; };
DWORD (*GetSelectedProcessId)
() = []
{ return SelectedProcessId; };
return
{ {
return {{
{"HostHWND", (int64_t)host->winId},
{"toclipboard", host->check_toclipboard},
{"current select", &thread == currthread},

View File

@ -5,13 +5,15 @@
#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;
@ -23,7 +25,8 @@ struct pluginitem{
nlohmann::json dump() const;
};
class Pluginmanager;
struct plugindata{
struct plugindata
{
typedef wchar_t *(*OnNewSentence_t)(wchar_t *, const InfoForExtension *);
typedef void (*VisSetting_t)(bool);
std::wstring refpath;
@ -37,7 +40,8 @@ struct plugindata{
bool valid();
void initstatus(const pluginitem &);
};
class Pluginmanager{
class Pluginmanager
{
std::unordered_map<std::wstring, plugindata> OnNewSentenceS;
concurrency::reader_writer_lock OnNewSentenceSLock;
bool checkisdump(const std::wstring &);
@ -45,6 +49,7 @@ class Pluginmanager{
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);

View File

@ -20,24 +20,26 @@ std::unordered_map<std::wstring,std::vector<int>> getprocesslist()
{
do
{
auto PROCESS_INJECT_ACCESS = (
PROCESS_CREATE_THREAD |
auto PROCESS_INJECT_ACCESS = (PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ);
if(pe32.th32ProcessID==currpid)continue;
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 (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()){
if (exe_pid.find(buffs) == exe_pid.end())
{
exe_pid.insert({buffs, {}});
}
exe_pid[buffs].push_back(pe32.th32ProcessID);
@ -46,47 +48,61 @@ 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){
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=[&](){
g_hButton->onclick = [&]()
{
auto str = g_hEdit->text();
if(str.size()){
if (str.size())
{
close();
for(auto _s:strSplit(str,L",")){
for (auto _s : strSplit(str, L","))
{
DWORD pid = 0;
try{
try
{
pid = std::stoi(_s);
}catch(std::exception&){}
}
catch (std::exception &)
{
}
if (pid)
Host::InjectProcess(pid);
}
}
};
g_refreshbutton->onclick=[&](){
g_refreshbutton->onclick = [&]()
{
g_exe_pid = getprocesslist();
PopulateProcessList(g_hListBox, g_exe_pid);
};
g_hListBox = new listview(this, true, true);
g_hListBox->setheader({L""});
g_hListBox->oncurrentchange=[&](int 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",";
for (auto &p : pids)
{
if (_1)
_ += L",";
_ += std::to_wstring(p);
_1 = true;
}
@ -102,7 +118,8 @@ processlistwindow::processlistwindow(mainwindow* p):mainwindow(p){
setlayout(mainlayout);
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);

View File

@ -2,55 +2,64 @@
#include "controls.h"
#include "Lang/Lang.h"
#include <shellapi.h>
HICON GetExeIcon(const std::wstring& filePath) {
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){
void basewindow::settext(const std::wstring &text)
{
SetWindowText(winId, text.c_str());
}
void basewindow::setgeo(int x,int y,int w,int 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);
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:
@ -73,15 +82,19 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
{
if (pnmhdr->hwndFrom == ctl->winId)
{
ctl->dispatch_2(wParam,lParam);break;
ctl->dispatch_2(wParam, lParam);
break;
}
}
}
case WM_COMMAND:
{
if(lParam==0){
for(auto ctl:controls){
if(lastcontexthwnd==ctl->winId){
if (lParam == 0)
{
for (auto ctl : controls)
{
if (lastcontexthwnd == ctl->winId)
{
if (ctl->menu)
ctl->menu.value().dispatch(wParam);
break;
@ -89,21 +102,28 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
}
}
else
for(auto ctl:controls){
if((HWND)lParam==ctl->winId){
ctl->dispatch(wParam);break;
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){
bool succ = false;
lastcontexthwnd = 0;
for (auto ctl : controls)
{
if ((HWND)wParam == ctl->winId)
{
auto hm = ctl->on_menu();
ctl->menu = hm;
if(hm){
if (hm)
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
TrackPopupMenu(hm.value().load(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
@ -114,14 +134,17 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
break;
}
}
if(succ==false)return DefWindowProc(winId, message, wParam, lParam);
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);
if (parent == 0)
PostQuitMessage(0);
else
ShowWindow(winId, SW_HIDE);
break;
}
default:
@ -130,29 +153,35 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){
return 0;
}
std::pair<int,int>mainwindow::calculateXY(int w,int h){
std::pair<int, int> mainwindow::calculateXY(int w, int h)
{
int cx, cy;
if(parent==0){
if (parent == 0)
{
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
cx = screenWidth / 2;
cy = screenHeight / 2;
}
else{
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){
void mainwindow::setcentral(int w, int h)
{
auto [x, y] = calculateXY(w, h);
setgeo(x, y, w, h);
}
void mainwindow::setlayout(control* _l){
void mainwindow::setlayout(control *_l)
{
layout = _l;
}
mainwindow::mainwindow(mainwindow* _parent){
mainwindow::mainwindow(mainwindow *_parent)
{
layout = 0;
const wchar_t CLASS_NAME[] = L"LunaHostWindow";
@ -160,7 +189,8 @@ mainwindow::mainwindow(mainwindow* _parent){
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);
if ((!_window) || (_window->winId != hWnd))
return DefWindowProc(hWnd, message, wParam, lParam);
return _window->wndproc(message, wParam, lParam);
};
wc.hInstance = GetModuleHandle(0);
@ -172,22 +202,24 @@ mainwindow::mainwindow(mainwindow* _parent){
HWND hWnd = CreateWindowEx(
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->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))
{
@ -198,7 +230,8 @@ void mainwindow::run(){
void mainwindow::on_close() {}
void mainwindow::on_show() {}
void mainwindow::on_size(int w,int h){
void mainwindow::on_size(int w, int h)
{
if (layout)
{
layout->setgeo(0, 0, w, h);

View File

@ -1,7 +1,8 @@
#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);
@ -11,10 +12,39 @@ public:
void settext(const std::wstring &);
operator HWND() { return winId; }
};
class mainwindow:public basewindow{
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;