vista style & Qtloader & other

Update CMakeLists.txt

Update README.md
This commit is contained in:
恍兮惚兮 2024-02-09 19:38:12 +08:00
parent 5262bd42b0
commit 0a3904df4f
15 changed files with 207 additions and 96 deletions

View File

@ -59,6 +59,8 @@
#define MenuAddPlugin L"Add Plugin"
#define MenuAddQtPlugin L"Add Qt Plugin"
#define MenuRemovePlugin L"Remove Plugin"
#define MenuPluginRankUp L"Up"
#define MenuPluginRankDown L"Down"
#define DefaultFont L"Arial"
#define InVaildPlugin L"InVaild Plugin"
#define CantLoadQtLoader L"Can't Load QtLoader.dll"

View File

@ -1,6 +1,5 @@
add_executable(LunaHost WIN32 confighelper.cpp controls.cpp main.cpp processlistwindow.cpp LunaHost.cpp window.cpp luna.rc pluginmanager.cpp Plugin/pluginexample.cpp)
add_executable(LunaHost WIN32 confighelper.cpp controls.cpp main.cpp processlistwindow.cpp LunaHost.cpp window.cpp luna.rc pluginmanager.cpp Plugin/pluginexample.cpp app.manifest)
target_precompile_headers(LunaHost REUSE_FROM pch)
set_target_properties(LunaHost PROPERTIES OUTPUT_NAME "LunaHost${bitappendix}")
target_link_libraries(LunaHost pch host ${YY_Thunks_for_WinXP})
add_subdirectory(Plugin)

View File

@ -198,29 +198,20 @@ Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
};
g_check_clipboard->setcheck(host->configs->get("ToClipboard",false));
g_timeout = new textedit(this,std::to_wstring(host->configs->get("flushDelay",TextThread::flushDelay)).c_str(),160, 10, 100, 40) ;
g_codepage = new textedit(this,std::to_wstring(host->configs->get("codepage",Host::defaultCodepage)).c_str(),160, 60, 100, 40) ;
g_timeout->ontextchange=[=](const std::wstring &text){
try{
auto fla=std::stoi(text);
TextThread::flushDelay=fla;
host->configs->set("flushDelay",fla);
}
catch(std::exception&){}
g_timeout = new spinbox(this,std::to_wstring(host->configs->get("flushDelay",TextThread::flushDelay)).c_str(),160, 10, 100, 40) ;
g_codepage = new spinbox(this,std::to_wstring(host->configs->get("codepage",Host::defaultCodepage)).c_str(),160, 60, 100, 40) ;
g_timeout->onvaluechange=[=](int v){
TextThread::flushDelay=v;
host->configs->set("flushDelay",v);
};
g_codepage->ontextchange=[=](const std::wstring &text){
try {
auto cp=std::stoi(text);
if(IsValidCodePage(cp)){
Host::defaultCodepage= cp;
printf("%d",Host::defaultCodepage);
host->configs->set("codepage",cp);
g_timeout->setminmax(0,9999);
g_codepage->onvaluechange=[=](int v){
if(IsValidCodePage(v)){
Host::defaultCodepage= v;
host->configs->set("codepage",v);
}
}
catch (const std::invalid_argument& e) {
}
};
g_codepage->setminmax(0,CP_UTF8);
setcentral(300,300);
settext(WndSetting);
}
@ -233,43 +224,66 @@ Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p){
new label(this,LblPluginRemove, 10,40,500,30);
static auto listadd=[&](const std::wstring& s){
auto idx=listplugins->additem(std::filesystem::path(s).stem().c_str());
listplugins->setdata(idx,(LONG_PTR)s.c_str());
auto _s=new wchar_t[s.size()+1];wcscpy(_s,s.c_str());
listplugins->setdata(idx,(LONG_PTR)_s);
};
listplugins = new listbox(this,10, 10,360,340);
#define IDM_ADD_PLUGIN 1004
#define IDM_ADD_QT_PLUGIN 1005
#define IDM_REMOVE_PLUGIN 1006
#define IDM_RANK_UP 1007
#define IDM_RANK_DOWN 1008
listplugins->oncontextmenu=[](){
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING, IDM_ADD_PLUGIN, MenuAddPlugin);
AppendMenu(hMenu, MF_STRING, IDM_ADD_QT_PLUGIN, MenuAddQtPlugin);
AppendMenu(hMenu, MF_STRING, IDM_REMOVE_PLUGIN, MenuRemovePlugin);
AppendMenu(hMenu, MF_STRING, IDM_RANK_UP, MenuPluginRankUp);
AppendMenu(hMenu, MF_STRING, IDM_RANK_DOWN, MenuPluginRankDown);
return hMenu;
};
listplugins->oncontextmenucallback=[&](WPARAM wparam){
listplugins->currentidx() ;
switch (LOWORD(wparam)) {
case IDM_RANK_DOWN:
case IDM_RANK_UP:
{
auto idx=listplugins->currentidx();
if(idx==-1)break;
auto idx2=idx+(
(LOWORD(wparam)==IDM_RANK_UP)?-1:1
);
auto a=min(idx,idx2),b=max(idx,idx2);
if(a<0||b>=listplugins->count())break;
pluginmanager->swaprank(a,b);
auto pa=((LPCWSTR)listplugins->getdata(a));
auto pb=((LPCWSTR)listplugins->getdata(b));
listplugins->deleteitem(a);
listplugins->insertitem(b,std::filesystem::path(pa).stem().c_str());
listplugins->setdata(b,(LONG_PTR)pa);
break;
}
case IDM_ADD_PLUGIN:
case IDM_ADD_QT_PLUGIN:
{
auto f=pluginmanager->selectpluginfile();
if(f.has_value()){
if(pluginmanager->addplugin(f.value(),LOWORD(wparam)==IDM_ADD_QT_PLUGIN)){
listadd(f.value());
}
{
auto f=pluginmanager->selectpluginfile();
if(f.has_value()){
if(pluginmanager->addplugin(f.value(),LOWORD(wparam)==IDM_ADD_QT_PLUGIN)){
listadd(f.value());
}
break;
}
break;
}
case IDM_REMOVE_PLUGIN:
{
auto idx=listplugins->currentidx();
if(idx==0)break;
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx));
listplugins->deleteitem(idx-1);
break;
}
{
auto idx=listplugins->currentidx();
if(idx==-1)break;
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx));
listplugins->deleteitem(idx);
break;
}
}
};
for(int i=0;i<pluginmanager->PluginRank.size();i++){

View File

@ -14,8 +14,8 @@ public:
};
class Settingwindow:public mainwindow{
checkbox* ckbfilterrepeat;
textedit* g_timeout;
textedit* g_codepage;
spinbox* g_timeout;
spinbox* g_codepage;
checkbox* g_check_clipboard;
public:
Settingwindow(LunaHost*);

View File

@ -5,37 +5,15 @@
#include<thread>
#include<mutex>
#include<Shlwapi.h>
void GetCommandLineArguments(int& argc, char**& argv)
{
LPWSTR* wideArgv = NULL;
int wideArgc = 0;
#include<filesystem>
LPWSTR commandLine = GetCommandLine();
wideArgv = CommandLineToArgvW(commandLine, &wideArgc);
if (wideArgv != NULL)
{
argv = new char*[wideArgc];
argc = wideArgc;
for (int i = 0; i < wideArgc; i++)
{
int length = WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, NULL, 0, NULL, NULL);
argv[i] = new char[length];
WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, argv[i], length, NULL, NULL);
}
LocalFree(wideArgv);
}
}
extern "C" __declspec(dllexport) HMODULE* QtLoadLibrary(LPCWSTR* dlls,int num){
auto hdlls=new HMODULE[num];
auto mutex=CreateSemaphoreW(0,0,1,0);
std::thread([=](){
int argc;
char** argv;
GetCommandLineArguments(argc, argv);
QApplication app(argc, nullptr);
int _=0;
QApplication::addLibraryPath(QString::fromStdWString(std::filesystem::path(dlls[0]).parent_path()));
QApplication app(_, nullptr);
app.setFont(QFont("MS Shell Dlg 2", 10));
for(int i=0;i<num;i++)
hdlls[i]=LoadLibraryW(dlls[i]);

15
LunaHost/GUI/app.manifest Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

View File

@ -28,6 +28,11 @@ confighelper::confighelper(){
catch(std::exception &){
configs={};
}
if(configs.find("plugins")==configs.end()){
configs["plugins"]={};
}
}
confighelper::~confighelper(){
@ -41,18 +46,18 @@ void confighelper::pluginsremove(const std::string&s){
});
plgs.erase(it, plgs.end());
}
void confighelper::pluginrankswap(int a,int b){
auto &plgs=configs["plugins"];
auto _b=plgs[b];
plgs[b]=plgs[a];
plgs[a]=_b;
}
void confighelper::pluginsadd(const std::string& p,bool isQt){
if(configs.find("plugins")==configs.end()){
configs["plugins"]={};
}
configs["plugins"].push_back({
{"path",p},
{"isQt",isQt}
});
}
nlohmann::json confighelper::pluginsget(){
if(configs.find("plugins")==configs.end()){
return {};
}
return configs["plugins"];
}

View File

@ -10,6 +10,7 @@ public:
nlohmann::json pluginsget();
void pluginsadd(const std::string&,bool);
void pluginsremove(const std::string&);
void pluginrankswap(int,int);
template<class T>
T get(const std::string&key,T default1){
if(configs.find(key)==configs.end())return default1;

View File

@ -1,5 +1,7 @@
#include"controls.h"
#include"window.h"
#include <CommCtrl.h>
control::control(mainwindow*_parent){
parent=_parent;
parent->controls.push_back(this);
@ -24,6 +26,52 @@ checkbox::checkbox(mainwindow* parent,LPCWSTR text,int x,int y,int w,int h):butt
void checkbox::setcheck(bool b){
SendMessage(winId, BM_SETCHECK, (WPARAM)BST_CHECKED*b, 0);
}
spinbox::spinbox(mainwindow* parent,LPCWSTR text,int x,int y,int w,int h,DWORD stype):control(parent){
winId=CreateWindowEx(0, L"EDIT", text, WS_CHILD | WS_VISIBLE | WS_BORDER|ES_NUMBER ,
x, y, w, h, 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);
SendMessage(hUpDown, UDM_SETBUDDY, (WPARAM)winId, 0);
std::tie(minv,maxv)= getminmax();
}
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;
}
catch(std::exception&){}
if(ok){
if(value>maxv){
setcurr(maxv);
value=maxv;
}
else if(value<minv){
setcurr(minv);
value=minv;
}
else{
onvaluechange(value);
}
}
}
}
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){
SendMessage(hUpDown, UDM_SETRANGE32,min, max);
std::tie(minv,maxv)= getminmax();
}
textedit::textedit(mainwindow* parent,LPCWSTR text,int x,int y,int w,int h,DWORD stype):control(parent){
winId=CreateWindowEx(0, L"EDIT", text, WS_CHILD | WS_VISIBLE | WS_BORDER|stype ,
x, y, w, h, parent->winId, NULL, NULL, NULL);
@ -55,7 +103,9 @@ listbox::listbox(mainwindow* parent,int x,int y,int w,int h):control(parent){
}
void listbox::dispatch(WPARAM wparam){
if(HIWORD(wparam) == LBN_SELCHANGE){
oncurrentchange(currentidx());
auto idx=currentidx();
if(idx!=-1)
oncurrentchange(idx);
}
}
@ -85,4 +135,7 @@ LONG_PTR listbox::getdata(int idx){
}
int listbox::count(){
return SendMessage(winId, LB_GETCOUNT, 0, 0);
}
int listbox::insertitem(int i,LPCWSTR t){
return SendMessage(winId, LB_INSERTSTRING, i, (LPARAM)t);
}

View File

@ -31,7 +31,17 @@ public:
void appendtext(const std::wstring&);
void scrolltoend();
};
class spinbox:public control{
HWND hUpDown;
int minv,maxv;
public:
void dispatch(WPARAM);
spinbox(mainwindow*,LPCWSTR,int,int,int,int,DWORD stype=0);
void setminmax(int,int);
std::pair<int,int>getminmax();
void setcurr(int);
std::function<void(int)> onvaluechange=[&](int){};
};
class label:public control{
public:
label(mainwindow*,LPCWSTR,int,int,int,int);
@ -48,6 +58,7 @@ public:
int additem(LPCWSTR);
void deleteitem(int);
void setdata(int,LONG_PTR);
int insertitem(int,LPCWSTR);
LONG_PTR getdata(int);
int count();
};

View File

@ -1,15 +1,11 @@
#include"LunaHost.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
//int main()
{
SetProcessDPIAware();
LunaHost _lunahost;
_lunahost.show();
mainwindow::run();
}
int main(){
SetProcessDPIAware();
LunaHost _lunahost;
_lunahost.show();
mainwindow::run();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
main();
}

View File

@ -26,17 +26,32 @@ std::optional<std::wstring>SelectFile(HWND hwnd,LPCWSTR lpstrFilter){
else return {};
}
typedef HMODULE*(*QtLoadLibrary_t)(LPWSTR*,int);
QtLoadLibrary_t loadqtloader(){
auto QtLoaderPath=std::filesystem::current_path()/(x64?"plugin64":"plugin32")/"QtLoader.dll";
QtLoadLibrary_t loadqtloader(const std::filesystem::path&pluginpath){
auto QtLoaderPath=pluginpath/"QtLoader.dll";
auto helper=LoadLibrary(QtLoaderPath.c_str());
if(helper==0)return 0;
auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(helper, "QtLoadLibrary");
return QtLoadLibrary;
}
struct pathhelper{
wchar_t currdll[MAX_PATH],currdir[MAX_PATH];
pathhelper(LPCWSTR p){
GetDllDirectoryW(MAX_PATH,currdll);GetCurrentDirectoryW(MAX_PATH,currdll);
SetDllDirectoryW(p);SetCurrentDirectoryW(p);
}
~pathhelper(){
SetDllDirectoryW(currdll);SetCurrentDirectoryW(currdll);
}
};
void Pluginmanager::loadqtdlls(std::vector<std::wstring>&collectQtplugs){
auto QtLoadLibrary = loadqtloader();
if(collectQtplugs.size()==0)return;
auto pluginpath=std::filesystem::current_path()/(x64?"plugin64":"plugin32");
auto _h=new pathhelper(pluginpath.c_str());//若加载Qt插件不需要恢复路径不然会有很多杂乱的文件。
auto QtLoadLibrary = loadqtloader(pluginpath);
if(!QtLoadLibrary){
MessageBoxW(host->winId,CantLoadQtLoader,L"Error",0);
delete _h;
return ;
}
std::vector<wchar_t*>saves;
@ -54,7 +69,7 @@ void Pluginmanager::loadqtdlls(std::vector<std::wstring>&collectQtplugs){
Pluginmanager::Pluginmanager(LunaHost* _host):host(_host){
try {
std::scoped_lock lock(OnNewSentenceSLock);
PluginRank.push_back(L"InternalClipBoard");
OnNewSentenceS[L"InternalClipBoard"]=GetProcAddress(GetModuleHandle(0),"OnNewSentence");//内部链接的剪贴板插件
auto plgs=host->configs->pluginsget();
std::vector<std::wstring>collectQtplugs;
@ -69,9 +84,7 @@ Pluginmanager::Pluginmanager(LunaHost* _host):host(_host){
}
OnNewSentenceS[path]=GetProcAddress(LoadLibraryW(path.c_str()),"OnNewSentence");
}
if(collectQtplugs.size()){
loadqtdlls(collectQtplugs);
}
loadqtdlls(collectQtplugs);
} catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
@ -83,11 +96,17 @@ bool Pluginmanager::dispatch(TextThread& thread, std::wstring& sentence){
wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, (sentence.size() + 1) * sizeof(wchar_t));
wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str());
concurrency::reader_writer_lock::scoped_lock_read readLock(OnNewSentenceSLock);
for (const auto& path : PluginRank){
auto funptr=OnNewSentenceS[path];
if(funptr==0)continue;
if (!*(sentenceBuffer = ((OnNewSentence_t)funptr)(sentenceBuffer, sentenceInfo))) break;
bool interupt=false;
for (const auto& pathl :{std::vector<std::wstring>{L"InternalClipBoard"}, PluginRank}){
for(const auto&path:pathl){
auto funptr=OnNewSentenceS[path];
if(funptr==0)continue;
if (!*(sentenceBuffer = ((OnNewSentence_t)funptr)(sentenceBuffer, sentenceInfo))){interupt=true;break;};
}
if(interupt)break;
}
sentence = sentenceBuffer;
HeapFree(GetProcessHeap(), 0, sentenceBuffer);
return !sentence.empty();
@ -125,6 +144,13 @@ void Pluginmanager::remove(const std::wstring& ss){
std::optional<std::wstring>Pluginmanager::selectpluginfile(){
return SelectFile(host->winId,L"Plugin Files\0*.dll;*.xdll\0");
}
void Pluginmanager::swaprank(int a,int b){
std::scoped_lock lock(OnNewSentenceSLock);
auto _b=PluginRank[b];
PluginRank[b]=PluginRank[a];
PluginRank[a]=_b;
host->configs->pluginrankswap(a,b);
}
bool Pluginmanager::addplugin(const std::wstring& p,bool isQt){
if(isQt){
host->configs->pluginsadd(WideStringToString(p),isQt);

View File

@ -16,6 +16,7 @@ public:
Pluginmanager(LunaHost*);
bool dispatch(TextThread&, std::wstring& sentence);
bool addplugin(const std::wstring&,bool isQt=false);
void swaprank(int,int);
void remove(const std::wstring&);
std::optional<std::wstring>selectpluginfile();
};

View File

@ -57,8 +57,14 @@ processlistwindow::processlistwindow(mainwindow* p):mainwindow(p){
auto str=g_hEdit->text();
if(str.size()){
close();
for(auto _s:strSplit(str,L",")){
Host::InjectProcess(std::stoi(_s));
DWORD pid=0;
try{
pid=std::stoi(_s);
}catch(std::exception&){}
if(pid)
Host::InjectProcess(pid);
}
}
};

View File

@ -1 +1,5 @@
Core Text Hook Module For [LunaTranslator](https://github.com/HIllya51/LunaTranslator)
Core Text Hook Module For [LunaTranslator](https://github.com/HIllya51/LunaTranslator)
Can also be used separately
Compatible with Textractor plugin