diff --git a/AppInstallerReset.sln b/AppInstallerReset.sln index 70084bb..9454f7b 100644 --- a/AppInstallerReset.sln +++ b/AppInstallerReset.sln @@ -28,6 +28,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "appinstaller", "appinstalle EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings", "settings\settings.vcxproj", "{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}" + ProjectSection(ProjectDependencies) = postProject + {3AE2A022-ED83-41F1-948A-12A7593CBD00} = {3AE2A022-ED83-41F1-948A-12A7593CBD00} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reslib", "reslib\reslib.vcxproj", "{3AE2A022-ED83-41F1-948A-12A7593CBD00}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -117,6 +122,16 @@ Global {AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x64.Build.0 = Release|x64 {AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x86.ActiveCfg = Release|Win32 {AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x86.Build.0 = Release|Win32 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x64.ActiveCfg = Debug|x64 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x64.Build.0 = Debug|x64 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x86.ActiveCfg = Debug|Win32 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x86.Build.0 = Debug|Win32 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|Any CPU.ActiveCfg = Release|Win32 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x64.ActiveCfg = Release|x64 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x64.Build.0 = Release|x64 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x86.ActiveCfg = Release|Win32 + {3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/appinstaller/filepath.h b/appinstaller/filepath.h index 3a9f5ea..0887e3e 100644 --- a/appinstaller/filepath.h +++ b/appinstaller/filepath.h @@ -925,6 +925,7 @@ public ref class _I_Path void set (String ^dir) { SetCurrentDirectoryW (MPStringToStdW (dir).c_str ()); } } property String ^Program { String ^get () { return CStringToMPString (GetCurrentProgramPathW ()); } } + property String ^Root { String ^get () { return CStringToMPString (GetFileDirectoryW (GetCurrentProgramPathW ())); }} String ^Combine (String ^l, String ^r) { return CStringToMPString (CombinePath (MPStringToStdW (l), MPStringToStdW (r))); } String ^GetName (String ^path) { diff --git a/appinstaller/main.cpp b/appinstaller/main.cpp index 984b889..a38d37c 100644 --- a/appinstaller/main.cpp +++ b/appinstaller/main.cpp @@ -169,12 +169,12 @@ public ref class _I_Bridge_Base { protected: _I_String ^str = gcnew _I_String (); - _I_Package ^pkg = gcnew _I_Package (); _I_InitConfig ^initconfig = gcnew _I_InitConfig (); + _I_Storage ^storage; public: property _I_String ^String { _I_String ^get () { return str; }} - property _I_Package ^Package { _I_Package ^get () { return pkg; }} property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }} + property _I_Storage ^Storage { _I_Storage ^get () { return storage; }} }; [ComVisible (true)] public interface class IScriptBridge diff --git a/appinstaller/resmap.h b/appinstaller/resmap.h index db7628e..89d5ee3 100644 --- a/appinstaller/resmap.h +++ b/appinstaller/resmap.h @@ -118,9 +118,21 @@ public ref class _I_Resources String ^GetFromOthers (String ^filepath, unsigned int resid) { HMODULE module = nullptr; - if (filepath && IsNormalizeStringEmpty (MPStringToStdW (filepath))) module = GetModuleHandleW (MPStringToStdW (filepath).c_str ()); + bool needrel = false; + if (filepath && !IsNormalizeStringEmpty (MPStringToStdW (filepath))) + { + HMODULE hRes = LoadLibraryExW ( + MPStringToStdW (filepath).c_str (), + NULL, + LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE + ); + needrel = hRes; + module = hRes; + } else module = GetModuleHandleW (NULL); - return GetRCStringCli (resid, module); + auto ret = GetRCStringCli (resid, module); + if (needrel && module) FreeLibrary (module); + return ret; } }; #endif \ No newline at end of file diff --git a/reslib/ReadMe.txt b/reslib/ReadMe.txt new file mode 100644 index 0000000..068568e --- /dev/null +++ b/reslib/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:reslib 项目概述 +======================================================================== + +应用程序向导已为您创建了此 reslib DLL。 + +本文件概要介绍组成 reslib 应用程序的每个文件的内容。 + + +reslib.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +reslib.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +reslib.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 reslib.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/reslib/dllmain.cpp b/reslib/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/reslib/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : DLL Ӧóڵ㡣 +#include "stdafx.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/reslib/reslib.cpp b/reslib/reslib.cpp new file mode 100644 index 0000000..96d7844 --- /dev/null +++ b/reslib/reslib.cpp @@ -0,0 +1,23 @@ +// reslib.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "reslib.h" +#include "resource.h" + + +// ǵһʾ +RESLIB_API int nreslib=0; + +// ǵһʾ +RESLIB_API int fnreslib(void) +{ + return 42; +} + +// ѵĹ캯 +// йඨϢ reslib.h +Creslib::Creslib() +{ + return; +} diff --git a/reslib/reslib.h b/reslib/reslib.h new file mode 100644 index 0000000..1038b35 --- /dev/null +++ b/reslib/reslib.h @@ -0,0 +1,22 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ RESLIB_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// RESLIB_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef RESLIB_EXPORTS +#define RESLIB_API __declspec(dllexport) +#else +#define RESLIB_API __declspec(dllimport) +#endif + +// Ǵ reslib.dll +class RESLIB_API Creslib { +public: + Creslib(void); + // TODO: ڴķ +}; + +extern RESLIB_API int nreslib; + +RESLIB_API int fnreslib(void); diff --git a/uishell/app.rc b/reslib/reslib.rc similarity index 56% rename from uishell/app.rc rename to reslib/reslib.rc index e289d26..5ef5947 100644 Binary files a/uishell/app.rc and b/reslib/reslib.rc differ diff --git a/uishell/uishell.vcxproj b/reslib/reslib.vcxproj similarity index 67% rename from uishell/uishell.vcxproj rename to reslib/reslib.vcxproj index 8c87eef..2de487b 100644 --- a/uishell/uishell.vcxproj +++ b/reslib/reslib.vcxproj @@ -19,10 +19,9 @@ - {278BD63A-C1F0-4D9A-90CD-EEB2EBED0ABF} - v4.5 - ManagedCProj - uishell + {3AE2A022-ED83-41F1-948A-12A7593CBD00} + Win32Proj + reslib 8.1 @@ -30,28 +29,26 @@ DynamicLibrary true v140 - true Unicode DynamicLibrary false v140 - true + true Unicode DynamicLibrary true v140 - true Unicode DynamicLibrary false v140 - true + true Unicode @@ -86,77 +83,98 @@ + Use Level3 Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - Use + WIN32;_DEBUG;_WINDOWS;_USRDLL;RESLIB_EXPORTS;%(PreprocessorDefinitions) + true - shlwapi.lib;version.lib;dwmapi.lib;%(AdditionalDependencies) + Windows + true + Use Level3 Disabled - _DEBUG;%(PreprocessorDefinitions) - Use + _DEBUG;_WINDOWS;_USRDLL;RESLIB_EXPORTS;%(PreprocessorDefinitions) + true - + Windows + true Level3 - WIN32;NDEBUG;%(PreprocessorDefinitions) Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;RESLIB_EXPORTS;%(PreprocessorDefinitions) + true - shlwapi.lib;version.lib;dwmapi.lib;%(AdditionalDependencies) + Windows + true + true + true Level3 - NDEBUG;%(PreprocessorDefinitions) Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;RESLIB_EXPORTS;%(PreprocessorDefinitions) + true - + Windows + true + true + true - - - - - + - + - - + + - - + + false + + + false + + + false + + + false + + + + + Create Create Create Create - - - - - - - - + diff --git a/uishell/uishell.vcxproj.filters b/reslib/reslib.vcxproj.filters similarity index 78% rename from uishell/uishell.vcxproj.filters rename to reslib/reslib.vcxproj.filters index d06ca7e..cb4d5e7 100644 --- a/uishell/uishell.vcxproj.filters +++ b/reslib/reslib.vcxproj.filters @@ -15,41 +15,36 @@ - + + + + 头文件 - + + 头文件 + + 头文件 头文件 - - 头文件 - - + 源文件 - + 源文件 - + 源文件 - - - - + 资源文件 - - - 资源文件 - - \ No newline at end of file diff --git a/reslib/resource.h b/reslib/resource.h new file mode 100644 index 0000000..050914c Binary files /dev/null and b/reslib/resource.h differ diff --git a/reslib/stdafx.cpp b/reslib/stdafx.cpp new file mode 100644 index 0000000..4e50f22 --- /dev/null +++ b/reslib/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// reslib.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/reslib/stdafx.h b/reslib/stdafx.h new file mode 100644 index 0000000..93c8be7 --- /dev/null +++ b/reslib/stdafx.h @@ -0,0 +1,16 @@ +// stdafx.h : ׼ϵͳļİļ +// Ǿʹõĵ +// ضĿİļ +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ +// Windows ͷļ: +#include + + + +// TODO: ڴ˴óҪͷļ diff --git a/reslib/targetver.h b/reslib/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/reslib/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/settings/filepath.h b/settings/filepath.h index 3a9f5ea..824f631 100644 --- a/settings/filepath.h +++ b/settings/filepath.h @@ -925,6 +925,11 @@ public ref class _I_Path void set (String ^dir) { SetCurrentDirectoryW (MPStringToStdW (dir).c_str ()); } } property String ^Program { String ^get () { return CStringToMPString (GetCurrentProgramPathW ()); } } + property String ^Root { String ^get () { + std::wstring program = GetCurrentProgramPathW (); + std::wstring path = GetFileDirectoryW (program); + return CStringToMPString (GetFileDirectoryW (GetCurrentProgramPathW ())); + }} String ^Combine (String ^l, String ^r) { return CStringToMPString (CombinePath (MPStringToStdW (l), MPStringToStdW (r))); } String ^GetName (String ^path) { diff --git a/settings/main.cpp b/settings/main.cpp index 9589bfd..5d87bbb 100644 --- a/settings/main.cpp +++ b/settings/main.cpp @@ -130,14 +130,115 @@ public ref class _I_InitConfig Win32::InitConfig ^GetConfig () { return Create (CStringToMPString (g_initfile.filepath)); } }; [ComVisible (true)] +public ref class _I_VisualElement +{ + protected: + String ^appid; + public: + _I_VisualElement (String ^appid): appid (appid) {} + _I_VisualElement (): appid (String::Empty) {} + property String ^Id { String ^get () { return appid; } void set (String ^value) { appid = value; } } +#define PROPERTY_VELEMENT(_PropertyName_, _MethodName_) \ + property String ^_PropertyName_ { \ + String ^get() { \ + return CStringToMPString(g_vemani._MethodName_(MPStringToStdW(appid))); \ + } \ + } + PROPERTY_VELEMENT (DisplayName, display_name) + PROPERTY_VELEMENT (Logo, logo) + PROPERTY_VELEMENT (SmallLogo, small_logo) + property String ^ForegroundText { String ^get () { return g_vemani.foreground_text (MPStringToStdW (appid)) == vemanifest::TextColor::light ? "light" : "dark"; }} + PROPERTY_VELEMENT (Lnk32x32Logo, lnk_32x32_logo) + PROPERTY_VELEMENT (ItemDisplayLogo, item_display_logo) + property bool ShowNameOnTile { bool get () { return g_vemani.show_name_on_tile (MPStringToStdW (appid)); }} + PROPERTY_VELEMENT (BackgroundColor, background_color) + PROPERTY_VELEMENT (SplashScreenImage, splash_screen_image) + PROPERTY_VELEMENT (SplashScreenBackgroundColor, splash_screen_backgroundcolor) + PROPERTY_VELEMENT (SplashScreenBackgroundColorDarkMode, splash_screen_backgroundcolor_darkmode) + #ifdef PROPERTY_VELEMENT + #undef PROPERTY_VELEMENT + #endif + Object ^Get (String ^propertyName) + { + String ^str = propertyName->ToLower ()->Trim (); + if (str == "displayname") return DisplayName; + else if (str == "logo") return Logo; + else if (str == "smalllogo") return SmallLogo; + else if (str == "foregroundtext") return ForegroundText; + else if (str == "lnk32x32logo") return Lnk32x32Logo; + else if (str == "shownameontile") return ShowNameOnTile; + else if (str == "backgroundcolor") return BackgroundColor; + else if (str == "splashscreenimage") return SplashScreenImage; + else if (str == "splashscreenbackgroundcolor") return SplashScreenBackgroundColor; + else if (str == "splashscreenbackgroundcolordarkmode") return SplashScreenBackgroundColorDarkMode; + return String::Empty; + } + Object ^operator [] (String ^propertyName) { return Get (propertyName); } +}; +[ComVisible (true)] +public ref class _I_VisualElements +{ + public: + array ^GetIds () + { + std::vector res; + g_vemani.app_ids (res); + auto ret = gcnew array (res.size ()); + for (size_t i = 0; i < res.size (); i ++) ret [i] = CStringToMPString (res [i]); + return ret; + } + String ^GetIdsToJson () { return StringArrayToJson (GetIds ()); } + _I_VisualElement ^Get (String ^id) { return gcnew _I_VisualElement (id); } + _I_VisualElement ^operator [] (String ^id) { return Get (id); } +#define ATTRIBUTE_METHODS(_FunctionName_, _MethodName_) \ +String^ _FunctionName_(String^ appid) { \ + return CStringToMPString(g_vemani._MethodName_(MPStringToStdW(appid))); \ +} + ATTRIBUTE_METHODS (DisplayName, display_name) + ATTRIBUTE_METHODS (Logo, logo) + ATTRIBUTE_METHODS (SmallLogo, small_logo) + String ^ForegroundText (String ^appid) + { + return g_vemani.foreground_text (MPStringToStdW (appid)) == vemanifest::TextColor::light ? "light" : "dark"; + } + ATTRIBUTE_METHODS (Lnk32x32Logo, lnk_32x32_logo) + ATTRIBUTE_METHODS (ItemDisplayLogo, item_display_logo) + bool ShowNameOnTile (String ^appid) { return g_vemani.show_name_on_tile (MPStringToStdW (appid)); } + ATTRIBUTE_METHODS (BackgroundColor, background_color) + ATTRIBUTE_METHODS (SplashScreenImage, splash_screen_image) + ATTRIBUTE_METHODS (SplashScreenBackgroundColor, splash_screen_backgroundcolor) + ATTRIBUTE_METHODS (SplashScreenBackgroundColorDarkMode, splash_screen_backgroundcolor_darkmode) + #ifdef ATTRIBUTE_METHODS + #undef ATTRIBUTE_METHODS + #endif + Object ^GetValue (String ^appid, String ^attributeName) + { + auto attr = attributeName->ToLower ()->Trim (); + if (attr == "displayname") return DisplayName (appid); + else if (attr == "logo") return Logo (appid); + else if (attr == "smalllogo") return SmallLogo (appid); + else if (attr == "foregroundtext") return ForegroundText (appid); + else if (attr == "lnk32x32logo") return Lnk32x32Logo (appid); + else if (attr == "itemdisplaylogo") return ItemDisplayLogo (appid); + else if (attr == "shownameontile") return ShowNameOnTile (appid); + else if (attr == "backgroundcolor") return BackgroundColor (appid); + else if (attr == "splashscreenimage") return SplashScreenImage (appid); + else if (attr == "splashscreenbackgroundcolor") return SplashScreenBackgroundColor (appid); + else if (attr == "splashscreenbackgroundcolordarkmode") return SplashScreenBackgroundColorDarkMode (appid); + else return String::Empty; + } +}; +[ComVisible (true)] public ref class _I_Bridge_Base { protected: _I_String ^str = gcnew _I_String (); _I_InitConfig ^initconfig = gcnew _I_InitConfig (); + _I_Storage ^storage; public: property _I_String ^String { _I_String ^get () { return str; }} property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }} + property _I_Storage ^Storage { _I_Storage ^get () { return storage; }} }; [ComVisible (true)] public interface class IScriptBridge @@ -541,6 +642,12 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScrip void FadeOutSplash () { wndinst->SplashScreen->FadeOut (); } }; [ComVisible (true)] + ref class _I_VisualElements2: public _I_VisualElements + { + public: + property _I_VisualElement ^Current {_I_VisualElement ^get () { return Get (CStringToMPString (g_idInVe)); }} + }; + [ComVisible (true)] ref class IBridge: public _I_Bridge_Base2 { private: @@ -574,17 +681,18 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScrip private: _I_IEFrame ^ieframe; _I_System3 ^sys; - _I_Storage ^storage; + _I_VisualElements2 ^ve; public: IBridge (MainHtmlWnd ^wnd): wndinst (wnd), _I_Bridge_Base2 (wnd) { ieframe = gcnew _I_IEFrame (wnd); sys = gcnew _I_System3 (wnd); storage = gcnew _I_Storage (); + ve = gcnew _I_VisualElements2 (); } property _I_IEFrame ^IEFrame { _I_IEFrame ^get () { return ieframe; }} property _I_System3 ^System { _I_System3 ^get () { return sys; }} - property _I_Storage ^Storage { _I_Storage ^get () { return storage; }} + property _I_VisualElements2 ^VisualElements { _I_VisualElements2 ^get () { return ve; } } }; protected: property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } } diff --git a/settings/resmap.h b/settings/resmap.h index 555d321..2b2a132 100644 --- a/settings/resmap.h +++ b/settings/resmap.h @@ -9,7 +9,12 @@ std::map g_nameToId = { MAKENAMEIDMAP (IDS_DEFAULTWIDTH), MAKENAMEIDMAP (IDS_DEFAULTHEIGHT), MAKENAMEIDMAP (IDS_MINWIDTH), - MAKENAMEIDMAP (IDS_MINHIEHGT) + MAKENAMEIDMAP (IDS_MINHIEHGT), + MAKENAMEIDMAP (IDS_TITLE), + MAKENAMEIDMAP (IDS_GUIDE), + MAKENAMEIDMAP (IDS_GUIDETEXT), + MAKENAMEIDMAP (IDS_TITLEFORMAT), + MAKENAMEIDMAP (IDS_GUIDETEXT_COMMON) }; #ifdef MAKENAMEIDMAP @@ -39,9 +44,21 @@ public ref class _I_Resources String ^GetFromOthers (String ^filepath, unsigned int resid) { HMODULE module = nullptr; - if (filepath && !IsNormalizeStringEmpty (MPStringToStdW (filepath))) module = GetModuleHandleW (MPStringToStdW (filepath).c_str ()); + bool needrel = false; + if (filepath && !IsNormalizeStringEmpty (MPStringToStdW (filepath))) + { + HMODULE hRes = LoadLibraryExW ( + MPStringToStdW (filepath).c_str (), + NULL, + LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE + ); + needrel = hRes; + module = hRes; + } else module = GetModuleHandleW (NULL); - return GetRCStringCli (resid, module); + auto ret = GetRCStringCli (resid, module); + if (needrel && module) FreeLibrary (module); + return ret; } }; #endif \ No newline at end of file diff --git a/settings/resource.h b/settings/resource.h index 5f1305c..446a9c1 100644 Binary files a/settings/resource.h and b/settings/resource.h differ diff --git a/settings/settings.rc b/settings/settings.rc index 6d4d4fa..acc90a9 100644 Binary files a/settings/settings.rc and b/settings/settings.rc differ diff --git a/shared/html/js/bridge.js b/shared/html/js/bridge.js index ed9d50e..3e7ac28 100644 --- a/shared/html/js/bridge.js +++ b/shared/html/js/bridge.js @@ -39,6 +39,9 @@ byid: function(resid) { return ext.System.Resources.GetById(resid); }, nameToId: function(resname) { return ext.System.Resources.ToId(resname); }, idToName: function(resid) { return ext.System.Resources.ToName(resid); }, + fromOthers: function(filepath, resid) { return ext.System.Resources.GetFromOthers(filepath, resid); }, + fromFile: function(filepath, resid) { return ext.System.Resources.GetFromOthers(filepath, resid); }, + fromfile: function(filepath, resid) { return ext.System.Resources.GetFromOthers(filepath, resid); }, }, Package: { filepaths: function() { diff --git a/shared/html/js/color.js b/shared/html/js/color.js index cadb847..fa7b171 100644 --- a/shared/html/js/color.js +++ b/shared/html/js/color.js @@ -482,5 +482,65 @@ var json = JSON.parse(window.external.IEFrame.ParseHtmlColor(str)); return new Color(json.r, json.g, json.b, json.a); } + Color.getSuitableForegroundTextColor = function(backgroundColor, foregroundColorArray) { + // 将 0–255 转为 W3C 的 0–1,并做 gamma 校正 + function gammaCorrect(c) { + c /= 255; + if (c <= 0.03928) return c / 12.92; + return Math.pow((c + 0.055) / 1.055, 2.4); + } + // 计算相对亮度 L(0–1) + function relativeLuminance(color) { + var R = gammaCorrect(color.red); + var G = gammaCorrect(color.green); + var B = gammaCorrect(color.blue); + return 0.2126 * R + 0.7152 * G + 0.0722 * B; + } + // 计算对比度 (L1+0.05)/(L2+0.05) + function contrastRatio(l1, l2) { + var light = Math.max(l1, l2); + var dark = Math.min(l1, l2); + return (light + 0.05) / (dark + 0.05); + } + // 混合背景透明度:背景 alpha 与白色混合 + function blendWithWhite(color) { + const a = (color.alpha !== undefined ? color.alpha : 255) / 255; + return { + red: color.red * a + 255 * (1 - a), + green: color.green * a + 255 * (1 - a), + blue: color.blue * a + 255 * (1 - a), + alpha: 255 + }; + } + // 透明背景视为与白色叠加 + const bg = blendWithWhite(backgroundColor); + const bgL = relativeLuminance(bg); + // 找出和背景对比度最高的前景色 + let bestColor = null; + let bestContrast = -1; + for (var i = 0; i < foregroundColorArray.length; i++) { + var fg = foregroundColorArray[i]; + var fgBlended = blendWithWhite(fg); // 若前景也有透明度 + var fgL = relativeLuminance(fgBlended); + var cr = contrastRatio(bgL, fgL); + if (cr > bestContrast) { + bestContrast = cr; + bestColor = fg; + } + } + return bestColor; + } + Color.Const = { + white: new Color(255, 255, 255), + black: new Color(0, 0, 0), + red: new Color(255, 0, 0), + green: new Color(0, 255, 0), + blue: new Color(0, 0, 255), + yellow: new Color(255, 255, 0), + cyan: new Color(0, 255, 255), + magenta: new Color(255, 0, 255), + transparent: new Color(0, 0, 0, 0), + }; + module.exports = { Color: Color }; })(this); \ No newline at end of file diff --git a/shared/html/js/init.js b/shared/html/js/init.js index 528cf6d..e06c54d 100644 --- a/shared/html/js/init.js +++ b/shared/html/js/init.js @@ -1,5 +1,17 @@ (function(global) { "use strict"; + var storage = Bridge.External.Storage; + var path = storage.path; + var root = path.getDir(path.program); + var respath = path.combine(root, "reslib.dll"); + var res = Bridge.Resources; + global.respath = respath; + global.getPublicRes = function(resId) { + return res.fromfile(respath, resId); + } + global.publicRes = function(resId) { + return getFileResPair(respath, resId); + } function ready(e) { function nextstep() { diff --git a/shared/html/js/resources.js b/shared/html/js/resources.js index 389318f..5041557 100644 --- a/shared/html/js/resources.js +++ b/shared/html/js/resources.js @@ -12,17 +12,27 @@ } var byName = el.getAttribute('data-res-byname'); var byId = el.getAttribute('data-res-byid'); - if ((byName && !Bridge.NString.empty(byName)) || (byId && parseInt(byId, 10) > 0)) { + var fromFile = el.getAttribute('data-res-fromfile'); + if ((byName && !Bridge.NString.empty(byName)) || (byId && parseInt(byId, 10) > 0) || (fromFile && !Bridge.NString.empty(fromFile))) { result.push(el); } } return result; // 返回符合条件的元素数组 } + module.exports = { + getFileResPair: function(filepath, resid) { + return { + filepath: filepath, + resid: resid + }; + } + }; module.exports = { Resources: { processAll: function() { var nodes = getAllNodesHasResource(); + var resources = Bridge.Resources; for (var i = 0; i < nodes.length; i++) { if (nodes[i].hasAttribute('data-res-byname')) { var resName = nodes[i].getAttribute('data-res-byname'); @@ -30,6 +40,13 @@ } else if (nodes[i].hasAttribute('data-res-byid')) { var resId = parseInt(nodes[i].getAttribute('data-res-byid'), 10); nodes[i].textContent = Bridge.Resources.byid(resId); + } else if (nodes[i].hasAttribute('data-res-fromfile')) { + try { + var obj = eval(nodes[i].getAttribute('data-res-fromfile')); + nodes[i].textContent = resources.fromfile(obj.filepath, obj.resid); + } catch (e) { + nodes[i].textContent = ""; + } } else { nodes[i].textContent = ""; } diff --git a/shared/html/settings.html b/shared/html/settings.html index caab8d4..f4a1e3f 100644 --- a/shared/html/settings.html +++ b/shared/html/settings.html @@ -37,7 +37,7 @@
-

设置

-

通过左侧的导航页,载入相应的设置。

+

+

diff --git a/shared/html/settings/appinstaller.html b/shared/html/settings/appinstaller.html index 307f572..174b6af 100644 --- a/shared/html/settings/appinstaller.html +++ b/shared/html/settings/appinstaller.html @@ -26,6 +26,7 @@ + @@ -37,14 +38,11 @@ diff --git a/shared/html/settings/appinstaller/guide.html b/shared/html/settings/appinstaller/guide.html index ef65d12..ce81ef5 100644 --- a/shared/html/settings/appinstaller/guide.html +++ b/shared/html/settings/appinstaller/guide.html @@ -26,13 +26,26 @@ +
-

App Installer Settings

+

+

+ \ No newline at end of file diff --git a/shared/html/settings/appinstaller/items.js b/shared/html/settings/appinstaller/items.js index b319a0c..b3ce855 100644 --- a/shared/html/settings/appinstaller/items.js +++ b/shared/html/settings/appinstaller/items.js @@ -8,9 +8,9 @@ }; } var pages = { - general: getPage("appinstaller/general.html", "General"), - theme: getPage("appinstaller/theme.html", "Theme"), - update: getPage("update.html", "Update") + general: getPage("appinstaller/general.html", getPublicRes(101)), + theme: getPage("appinstaller/theme.html", getPublicRes(102)), + update: getPage("update.html", getPublicRes(103)) }; Object.defineProperty(global, "pages", { get: function() { diff --git a/shared/html/settings/appinstaller/preinit.js b/shared/html/settings/appinstaller/preinit.js new file mode 100644 index 0000000..665e204 --- /dev/null +++ b/shared/html/settings/appinstaller/preinit.js @@ -0,0 +1,12 @@ +(function(global) { + var storage = Bridge.External.Storage; + var path = storage.path; + var root = path.getDir(path.program); + var exepath = path.combine(root, "appinstaller.exe"); + var id = "App"; + var ve = Bridge.External.VisualElements.get(id); + var slideback = ve["BackgroundColor"]; + global.slideback = slideback; + global.exepath = exepath; + global.visual = ve; +})(this); \ No newline at end of file diff --git a/shared/html/settings/initsame.js b/shared/html/settings/initsame.js index 6965964..844747e 100644 --- a/shared/html/settings/initsame.js +++ b/shared/html/settings/initsame.js @@ -8,7 +8,17 @@ var content = guide.querySelector(".main"); var shead = slide.querySelector("header"); var list = slide.querySelector("ul"); - try { slide.style.backgroundColor = Bridge.UI.themeColor; } catch (e) {} + var apptitle = shead.querySelector("#apptitle"); + var backbtn = shead.querySelector("#back"); + if (backbtn && backbtn.disabled) { + apptitle.style.marginLeft = backbtn.style.marginLeft; + } else { + apptitle.style.marginLeft = ""; + } + try { + slide.style.backgroundColor = Bridge.UI.themeColor; + slide.style.color = Color.getSuitableForegroundTextColor(Color.parse(slide.style.backgroundColor), [Color.Const.white, Color.Const.black]); + } catch (e) {} setTimeout(function() { slide.style.transition = "all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1)"; }, 0); diff --git a/shared/html/settings/items.js b/shared/html/settings/items.js index a12227a..c8fca92 100644 --- a/shared/html/settings/items.js +++ b/shared/html/settings/items.js @@ -1,5 +1,14 @@ (function(global) { "use strict"; + var res = Bridge.Resources; + var storage = Bridge.External.Storage; + var path = storage.path; + var root = path.getDir(path.program); + + function getLibRes(libfilename, resid) { + var libpath = path.combine(root, libfilename); + return res.fromfile(libpath, resid); + } function getSettingsItem(page, displayName) { return { @@ -8,7 +17,7 @@ }; } var settingItems = { - appinstaller: getSettingsItem("appinstaller.html", "App Installer") + appinstaller: getSettingsItem("appinstaller.html", getLibRes("appinstaller.exe", 300)) }; Object.defineProperty(global, "settingPages", { get: function() { return settingItems; } diff --git a/shared/html/settings/page.css b/shared/html/settings/page.css index 796bd10..76d9b37 100644 --- a/shared/html/settings/page.css +++ b/shared/html/settings/page.css @@ -121,7 +121,7 @@ aside.left { left: 0px; width: 300px; box-sizing: border-box; - padding: 0; + padding: 0 1px 0 0; background-color: rgb(20, 0, 68); color: white; } @@ -157,11 +157,12 @@ aside .container ul li { align-content: center; justify-content: flex-start; align-items: center; + transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1); } aside .container ul li.selected { /* background-color: rgba(101, 38, 254, 0.61); */ - background-color: rgba(95, 95, 95, 0.45); + background-color: rgba(170, 170, 170, 0.45); } aside .container ul li:hover { @@ -171,12 +172,17 @@ aside .container ul li:hover { aside .container ul li:active { background-color: white; color: black; + transform: scale(0.9594); } aside .container ul li:focus { border: 1px solid white; } +#back:disabled { + display: none; +} + .main.right { position: absolute; top: 0px; diff --git a/uishell/AssemblyInfo.cpp b/uishell/AssemblyInfo.cpp deleted file mode 100644 index b4fec5b..0000000 --- a/uishell/AssemblyInfo.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "stdafx.h" - -using namespace System; -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Permissions; - -// -// йس򼯵һϢ -// ơЩֵ޸ -// 򼯹Ϣ -// -[assembly:AssemblyTitleAttribute(L"uishell")]; -[assembly:AssemblyDescriptionAttribute(L"")]; -[assembly:AssemblyConfigurationAttribute(L"")]; -[assembly:AssemblyCompanyAttribute(L"")]; -[assembly:AssemblyProductAttribute(L"uishell")]; -[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2025")]; -[assembly:AssemblyTrademarkAttribute(L"")]; -[assembly:AssemblyCultureAttribute(L"")]; - -// -// 򼯵İ汾Ϣĸֵ: -// -// 汾 -// ΰ汾 -// ɺ -// ޶ -// -// ֵָҲʹá޶š͡ɺšĬֵ -// ǰʾʹá*: : - -[assembly:AssemblyVersionAttribute("1.0.*")]; - -[assembly:ComVisible(false)]; - -[assembly:CLSCompliantAttribute(true)]; \ No newline at end of file diff --git a/uishell/ReadMe.txt b/uishell/ReadMe.txt deleted file mode 100644 index b2b842d..0000000 --- a/uishell/ReadMe.txt +++ /dev/null @@ -1,38 +0,0 @@ -======================================================================== - DYNAMIC LINK LIBRARY : uishell Project Overview -======================================================================== - -AppWizard has created this uishell DLL for you. - -This file contains a summary of what you will find in each of the files that -make up your uishell application. - -uishell.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -uishell.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -uishell.cpp - This is the main DLL source file. - -uishell.h - This file contains a class declaration. - -AssemblyInfo.cpp - Contains custom attributes for modifying assembly metadata. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/uishell/Stdafx.cpp b/uishell/Stdafx.cpp deleted file mode 100644 index 7501de5..0000000 --- a/uishell/Stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : ֻ׼ļԴļ -// uishell.pch ΪԤͷ -// stdafx.obj ԤϢ - -#include "stdafx.h" diff --git a/uishell/Stdafx.h b/uishell/Stdafx.h deleted file mode 100644 index 0a9513b..0000000 --- a/uishell/Stdafx.h +++ /dev/null @@ -1,17 +0,0 @@ -// stdafx.h : ׼ϵͳļİļ -// Ǿʹõĵ -// ضĿİļ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - diff --git a/uishell/app.ico b/uishell/app.ico deleted file mode 100644 index 789d7cc..0000000 Binary files a/uishell/app.ico and /dev/null differ diff --git a/uishell/resource.h b/uishell/resource.h deleted file mode 100644 index d5ac7c4..0000000 --- a/uishell/resource.h +++ /dev/null @@ -1,3 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by app.rc diff --git a/uishell/themeinfo.h b/uishell/themeinfo.h deleted file mode 120000 index de15510..0000000 --- a/uishell/themeinfo.h +++ /dev/null @@ -1 +0,0 @@ -../appinstaller/themeinfo.h \ No newline at end of file diff --git a/uishell/uishell.cpp b/uishell/uishell.cpp deleted file mode 100644 index 919a5d7..0000000 --- a/uishell/uishell.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// DLL ļ - -#include "stdafx.h" - -#include "uishell.h" - diff --git a/uishell/uishell.h b/uishell/uishell.h deleted file mode 100644 index b7c7ce9..0000000 --- a/uishell/uishell.h +++ /dev/null @@ -1,197 +0,0 @@ -// uishell.h - -#pragma once - -using namespace System; -using namespace System::Windows::Forms; -using namespace System::Runtime::InteropServices; - -namespace Win32 -{ - using WebBrowserCli = System::Windows::Forms::WebBrowser; - public ref class SplashForm: Form - { - private: - PictureBox ^picbox; - Timer ^timer; - System::Drawing::Image ^splashimg = nullptr; - System::Drawing::Color background = System::Drawing::Color::Transparent; - double opastep = 0.05; - void InitForm () - { - this->DoubleBuffered = true; - InitializeComponent (); - this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None; - this->StartPosition = System::Windows::Forms::FormStartPosition::Manual; - this->ShowInTaskbar = false; - this->AllowTransparency = true; - this->Opacity = 1.0; - } - void InitializeComponent () - { - double dDpi = GetDPI () * 0.01; - this->picbox = gcnew System::Windows::Forms::PictureBox (); - this->picbox->Size = System::Drawing::Size (620 * dDpi, 300 * dDpi); - this->picbox->BackColor = System::Drawing::Color::Transparent; - picbox->Anchor = System::Windows::Forms::AnchorStyles::None; - picbox->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom; - } - void OnFadeTimer (Object ^sender, EventArgs ^e) - { - auto fadeTimer = timer; - auto opacityStep = opastep; - if (this->Opacity > 0) - { - this->Opacity -= opacityStep; - } - else - { - fadeTimer->Stop (); - this->Close (); - } - } - void OnLoad (Object ^sender, EventArgs ^e) - { - this->ChangePosAndSize (); - this->Visible = true; - } - void OnResize (Object ^sender, EventArgs ^e) - { - if (IsHandleCreated && picbox->IsHandleCreated) - { - Drawing::Size sz = this->ClientSize; - this->picbox->Location = Drawing::Point ( - (sz.Width - picbox->Width) * 0.5, - (sz.Height - picbox->Height) * 0.5 - ); - } - } - void OnResizeOwner (Object ^sender, EventArgs ^e) { this->ChangePosAndSize (); } - void OnLocationChangedOwner (Object ^sender, EventArgs ^e) { this->ChangePosAndSize (); } - protected: - virtual void OnHandleCreated (EventArgs^ e) override - { - Form::OnHandleCreated (e); - if (Environment::OSVersion->Version->Major >= 6) - { - INT mr = 0; - MARGINS margins = {mr, mr, mr, mr}; - HRESULT hr = DwmExtendFrameIntoClientArea ((HWND)this->Handle.ToPointer (), &margins); - } - } - public: - SplashForm (System::String ^imgpath, System::Drawing::Color backcolor, System::Windows::Forms::Form ^owner) - { - if (owner != nullptr) this->Owner = owner; - InitForm (); - std::wstring filefullpath = MPStringToStdW (imgpath); - if (filefullpath.find (L'%') != filefullpath.npos) filefullpath = ProcessEnvVars (filefullpath); - filefullpath = GetFullPathName (imgpath ? MPStringToStdW (imgpath) : L""); - try - { - auto img = System::Drawing::Image::FromFile (gcnew System::String (filefullpath.c_str ())); - if (img != nullptr) - { - splashimg = img; - picbox->Image = img; - } - } - catch (...) {} - if (splashimg) picbox->Image = splashimg; - try - { - if (backcolor != Drawing::Color::Transparent) - { - background = backcolor; - picbox->BackColor = backcolor; - this->BackColor = backcolor; - } - else - { - picbox->BackColor = background; - this->BackColor = background; - } - } - catch (...) {} - if (this->Owner != nullptr) - { - this->Owner->Resize += gcnew System::EventHandler (this, &SplashForm::OnResizeOwner); - this->Owner->LocationChanged += gcnew System::EventHandler (this, &SplashForm::OnLocationChangedOwner); - } - this->Controls->Add (picbox); - this->Resize += gcnew EventHandler (this, &SplashForm::OnResize); - timer = gcnew System::Windows::Forms::Timer (); - timer->Interval = 15; - timer->Tick += gcnew System::EventHandler (this, &SplashForm::OnFadeTimer); - this->Load += gcnew EventHandler (this, &SplashForm::OnLoad); - } - void ReInit () - { - InitForm (); - picbox = gcnew System::Windows::Forms::PictureBox (); - picbox->BackColor = background; - if (splashimg) picbox->Image = splashimg; - picbox->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom; - picbox->Anchor = System::Windows::Forms::AnchorStyles::None; - double dDpi = GetDPI () * 0.01; - picbox->Size = Drawing::Size (620 * dDpi, 300 * dDpi); - this->BackColor = background; - this->Controls->Clear (); - this->Controls->Add (picbox); - timer = gcnew System::Windows::Forms::Timer (); - timer->Interval = 15; - timer->Tick += gcnew EventHandler (this, &SplashForm::OnFadeTimer); - this->Resize += gcnew EventHandler (this, &SplashForm::OnResize); - this->Load += gcnew EventHandler (this, &SplashForm::OnLoad); - ChangePosAndSize (); - this->Opacity = 1.0; - } - void ChangePosAndSize () - { - if (this->Owner && this->Owner->IsHandleCreated) - { - this->Owner->Update (); - System::Drawing::Point pt = this->Owner->PointToScreen (this->Owner->ClientRectangle.Location); - this->Location = pt; - this->Size = this->Owner->ClientSize; - } - else if (this->Parent && this->Parent->IsHandleCreated) - { - this->Parent->Update (); - System::Drawing::Point pt = this->Parent->PointToScreen (this->Parent->ClientRectangle.Location); - this->Location = pt; - this->Size = this->Parent->ClientSize; - } - if (IsHandleCreated && picbox->IsHandleCreated) - { - Drawing::Size sz = this->ClientSize; - this->picbox->Location = Drawing::Point ( - (sz.Width - picbox->Width) * 0.5, - (sz.Height - picbox->Height) * 0.5 - ); - } - } - void SetSplashImage (System::Drawing::Image ^img) { if (picbox && picbox->IsHandleCreated) { splashimg = img; picbox->Image = splashimg; } else splashimg = img; } - void SetSplashImage (System::String ^imgpath) { try { SetSplashImage (System::Drawing::Image::FromFile (imgpath)); } catch (...) {} } - void SetSplashImage (const std::wstring &imgpath) { SetSplashImage (CStringToMPString (imgpath)); } - void SetSplashBackgroundColor (System::Drawing::Color color) { background = color; picbox->BackColor = color; this->BackColor = color; } - // ʧ - void FadeOut () { timer->Start (); } - // ʧûУ - void FadeAway () { timer->Start (); } - ~SplashForm () - { - if (this->Owner != nullptr) - { - this->Owner->Resize -= gcnew System::EventHandler (this, &SplashForm::OnResizeOwner); - this->Owner->LocationChanged -= gcnew System::EventHandler (this, &SplashForm::OnLocationChangedOwner); - } - } - }; - public ref class WebBrowserForm: Form - { - private: - WebBrowserCli ^webui; - - }; -}