Update Settings Page.

This commit is contained in:
Bruce
2025-11-29 18:19:08 +08:00
parent 87efdc39df
commit cf50b09bf0
111 changed files with 7115 additions and 322 deletions
+87
View File
@@ -0,0 +1,87 @@
#pragma once
#include <Windows.h>
#include "mpstr.h"
#include "nstring.h"
using namespace System;
using namespace System::Runtime::InteropServices;
std::wstring HResultToMessage (HRESULT hr)
{
_com_error err (hr);
auto msgptr = err.ErrorMessage ();
return msgptr ? msgptr : L"";
}
[ComVisible (true)]
public ref class _I_HResult
{
private:
HRESULT hr = S_OK;
String ^errorcode = "";
String ^detailmsg = "";
public:
_I_HResult (HRESULT hres)
{
hr = hres;
detailmsg = CStringToMPString (HResultToMessage (hres));
}
_I_HResult (HRESULT hres, String ^error, String ^message)
{
hr = hres;
errorcode = error;
detailmsg = message;
}
property HRESULT HResult { HRESULT get () { return hr; }}
property String ^ErrorCode { String ^get () { return errorcode; }}
property String ^Message { String ^get () { return detailmsg; }}
property bool Succeeded { bool get () { return SUCCEEDED (hr); }}
property bool Failed { bool get () { return FAILED (hr); }}
};
System::String ^FormatString (System::String ^fmt, ... array <Object ^> ^args) { return System::String::Format (fmt, args); }
String ^ EscapeToInnerXml (String ^str)
{
using namespace System::Xml;
auto doc = gcnew System::Xml::XmlDocument ();
doc->LoadXml ("<body></body>");
auto root = doc->FirstChild;
root->InnerText = str;
return root->InnerXml;
}
std::wstring EscapeToInnerXml (const std::wstring &str) { return MPStringToStdW (EscapeToInnerXml (CStringToMPString (str))); }
[ComVisible (true)]
public ref class _I_String
{
public:
ref class _I_NString
{
public:
bool NEquals (String ^l, String ^r) { return IsNormalizeStringEquals (MPStringToPtrW (l), MPStringToPtrW (r)); }
bool Empty (String ^l) { return IsNormalizeStringEmpty (MPStringToStdW (l)); }
int Compare (String ^l, String ^r) { return NormalizeStringCompare (MPStringToPtrW (l), MPStringToPtrW (r)); }
int Length (String ^l) { return GetNormalizeStringLength (MPStringToStdW (l)); }
};
private:
_I_NString ^nstr = gcnew _I_NString ();
public:
property _I_NString ^NString { _I_NString ^get () { return nstr; }}
String ^Trim (String ^src)
{
std::wstring csrc = MPStringToStdW (src);
return CStringToMPString (::StringTrim (csrc));
}
String ^ToLower (String ^src) { return CStringToMPString (StringToLower (MPStringToStdW (src))); }
String ^ToUpper (String ^src) { return CStringToMPString (StringToUpper (MPStringToStdW (src))); }
String ^Format (String ^fmt, ... array <Object ^> ^args) { return FormatString (fmt, args); }
String ^FormatInnerHTML (String ^fmt, ... array <Object ^> ^args)
{
std::wstring ihtml = EscapeToInnerXml (MPStringToStdW (fmt));
auto pih = CStringToMPString (ihtml);
auto newargs = gcnew array <Object ^> (args->Length);
for (size_t i = 0; i < args->Length; i ++)
{
auto %p = newargs [i];
p = Format ("<span>{0}</span>", EscapeToInnerXml (Format ("{0}", args [i])));
}
return Format (pih, newargs);
}
};
+77
View File
@@ -0,0 +1,77 @@
#pragma once
#include <vector>
#include <algorithm>
#include <functional>
template <class T> bool compare_default (const T &l, const T &r) { return l == r; }
template <class T> bool find_vec (std::vector <T> &vec, const T &value, const std::function <void (size_t)> &callback, std::function<bool (const T &, const T &)> compare = compare_default <T>, bool sorted = false)
{
const size_t n = vec.size ();
if (!compare) compare = compare_default<T>;
if (sorted)
{
size_t left = 0, right = n;
while (left < right)
{
size_t mid = left + (right - left) / 2;
if (compare (vec [mid], value))
{
callback (mid);
return true;
}
if (vec [mid] < value) left = mid + 1;
else right = mid;
}
return false;
}
if (n < 64)
{
for (size_t i = 0; i < n; i++)
{
if (compare (vec [i], value))
{
callback (i);
return true;
}
}
return false;
}
const size_t blockSize = 8;
size_t i = 0;
for (; i + blockSize <= n; i += blockSize)
{
for (size_t j = 0; j < blockSize; j ++)
{
if (compare (vec [i + j], value))
{
callback (i + j);
return true;
}
}
}
for (; i < n; i ++)
{
if (compare (vec [i], value))
{
callback (i);
return true;
}
}
return false;
}
template <class T> void push_unique (std::vector <T> &vec, const T &value, std::function <bool (const T &, const T &)> compare = compare_default <T>)
{
bool found = find_vec <T> (
vec, value,
[] (size_t) {},
compare);
if (!found) vec.push_back (value);
}
template <class T> void push_normal (std::vector <T> &vec, const T &value)
{
vec.push_back (value);
}
template <class T> void push_normal (std::vector <T> &target, const std::vector <T> &another)
{
target.insert (target.end (), another.begin (), another.end ());
}
+1173
View File
File diff suppressed because it is too large Load Diff
+46
View File
@@ -0,0 +1,46 @@
#pragma once
#include <Windows.h>
#include <string>
#include <cstdlib>
#include "filepath.h"
void SetWebBrowserEmulation ()
{
std::wstring instname = GetCurrentProgramNameW ();
BOOL isWow64 = FALSE;
IsWow64Process (GetCurrentProcess (), &isWow64);
HKEY hKey;
LPCWSTR keyPath = isWow64
? L"SOFTWARE\\WOW6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION"
: L"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION";
LONG result = RegOpenKeyExW (HKEY_CURRENT_USER, keyPath, 0, KEY_WRITE, &hKey);
if (result == ERROR_SUCCESS)
{
DWORD value = 11001;
RegSetValueExW (hKey, instname.c_str (), 0, REG_DWORD, reinterpret_cast <const BYTE*> (&value), sizeof (value));
RegCloseKey (hKey);
}
}
// 返回系统安装的 Internet Explorer 主版本号(如 8、9、10、11)
int GetInternetExplorerVersionMajor ()
{
HKEY hKey;
LPCWSTR IEKeyPath = L"SOFTWARE\\Microsoft\\Internet Explorer";
if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, IEKeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS) return 0;
WCHAR buffer [128] = {0};
DWORD bufferSize = sizeof (buffer);
DWORD type = 0;
std::wstring versionStr;
if (RegQueryValueExW (hKey, L"svcVersion", NULL, &type, (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS) versionStr = buffer;
else
{
bufferSize = sizeof (buffer);
if (RegQueryValueExW (hKey, L"Version", NULL, &type, (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS) versionStr = buffer;
}
RegCloseKey (hKey);
if (versionStr.empty ()) return 0;
int major = 0;
swscanf_s (versionStr.c_str (), L"%d", &major);
return major;
}
bool IsInternetExplorer10 () { return GetInternetExplorerVersionMajor () == 10; }
bool IsInternetExplorer11AndLater () { return GetInternetExplorerVersionMajor () >= 11; }
+599
View File
@@ -0,0 +1,599 @@
#pragma once
#ifndef _CRT_NON_CONFORMING_SWPRINTFS
#define _CRT_NON_CONFORMING_SWPRINTFS
#endif
#include <Windows.h>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <functional>
#include <cstdint>
#include <cwchar>
#include <type_traits>
#include "strcode.h"
#include "nstring.h"
#include "typestrans.h"
#include "mpstr.h"
template <typename T> std::wstring TypeToString (T value, const std::wstring &reserve = L"") { return std::to_wstring (value); }
template <typename T> std::string TypeToString (T value, const std::string &reserve = "") { return std::to_string (value); }
std::string GetPrivateProfileStringA (const std::string &filePath, const std::string &section, const std::string &key, LPCSTR defaultValue = "")
{
char buf [32768] = {0};
GetPrivateProfileStringA (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ());
return buf;
}
std::wstring GetPrivateProfileStringW (const std::wstring &filePath, const std::wstring &section, const std::wstring &key, LPCWSTR defaultValue = L"")
{
WCHAR buf [32768] = {0};
GetPrivateProfileStringW (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ());
return buf;
}
UINT GetPrivateProfileIntA (const std::string &filePath, const std::string &section, const std::string &key, INT defaultValue = 0)
{
return GetPrivateProfileIntA (section.c_str (), key.c_str (), defaultValue, filePath.c_str ());
}
UINT GetPrivateProfileIntW (const std::wstring &filePath, const std::wstring &section, const std::wstring &key, INT defaultValue = 0)
{
return GetPrivateProfileIntW (section.c_str (), key.c_str (), defaultValue, filePath.c_str ());
}
BOOL WritePrivateProfileStringA (const std::string &filePath, const std::string &section, const std::string &key, const std::string &value)
{
return WritePrivateProfileStringA (section.c_str (), key.c_str (), value.c_str (), filePath.c_str ());
}
BOOL WritePrivateProfileStringW (const std::wstring &filePath, const std::wstring &section, const std::wstring &key, const std::wstring &value)
{
return WritePrivateProfileStringW (section.c_str (), key.c_str (), value.c_str (), filePath.c_str ());
}
size_t GetPrivateProfileSectionA (const std::string &filePath, const std::string &section, std::vector <std::string> &output)
{
char buf [32768] = {0};
DWORD len = GetPrivateProfileSectionA (section.c_str (), buf, sizeof (buf), filePath.c_str ());
output.clear ();
if (len == 0) return 0;
char *ptr = buf;
while (*ptr)
{
output.emplace_back (ptr);
ptr += strlen (ptr) + 1;
}
return output.size ();
}
size_t GetPrivateProfileSectionW (const std::wstring &filePath, const std::wstring &section, std::vector <std::wstring> &output)
{
WCHAR buf [32768] = {0};
DWORD len = GetPrivateProfileSectionW (section.c_str (), buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
output.clear ();
if (len == 0) return 0;
WCHAR *ptr = buf;
while (*ptr)
{
output.emplace_back (ptr);
ptr += wcslen (ptr) + 1;
}
return output.size ();
}
size_t GetPrivateProfileSectionNamesA (const std::string &filePath, std::vector <std::string> &output)
{
char buf [32768] = {0};
DWORD len = GetPrivateProfileSectionNamesA (buf, sizeof (buf), filePath.c_str ());
output.clear ();
if (len == 0) return 0;
char *ptr = buf;
while (*ptr)
{
output.emplace_back (ptr);
ptr += strlen (ptr) + 1;
}
return output.size ();
}
size_t GetPrivateProfileSectionNamesW (const std::wstring &filePath, std::vector <std::wstring> &output)
{
WCHAR buf [32768] = {0};
DWORD len = GetPrivateProfileSectionNamesW (buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
output.clear ();
if (len == 0) return 0;
WCHAR *ptr = buf;
while (*ptr)
{
output.emplace_back (ptr);
ptr += wcslen (ptr) + 1;
}
return output.size ();
}
bool WritePrivateProfileSectionA (const std::string &filePath, const std::string &section, const std::vector <std::string> &lines)
{
std::string buf;
for (const auto &line : lines) buf.append (line).push_back ('\0');
buf.push_back ('\0');
return WritePrivateProfileSectionA (section.c_str (), buf.c_str (), filePath.c_str ()) != 0;
}
bool WritePrivateProfileSectionW (const std::wstring &filePath, const std::wstring &section, const std::vector <std::wstring> &lines)
{
std::wstring buf;
for (const auto &line : lines) buf.append (line).push_back (L'\0');
buf.push_back (L'\0'); // Ë« \0 ½áβ
return WritePrivateProfileSectionW (section.c_str (), buf.c_str (), filePath.c_str ()) != 0;
}
bool GetPrivateProfileStructA (const std::string &filePath, const std::string &section, const std::string &key, void *output, UINT size)
{
return GetPrivateProfileStructA (section.c_str (), key.c_str (), output, size, filePath.c_str ()) != 0;
}
bool WritePrivateProfileStructA (const std::string &filePath, const std::string &section, const std::string &key, void *data, UINT size)
{
return WritePrivateProfileStructA (section.c_str (), key.c_str (), data, size, filePath.c_str ()) != 0;
}
bool GetPrivateProfileStructW (const std::wstring &filePath, const std::wstring &section, const std::wstring &key, void *output, UINT size)
{
return GetPrivateProfileStructW (section.c_str (), key.c_str (), output, size, filePath.c_str ()) != 0;
}
bool WritePrivateProfileStructW (const std::wstring &filePath, const std::wstring &section, const std::wstring &key, void *data, UINT size)
{
return WritePrivateProfileStructW (section.c_str (), key.c_str (), data, size, filePath.c_str ()) != 0;
}
size_t GetPrivateProfileKeysW (const std::wstring &filePath, const std::wstring &section, std::vector <std::wstring> &keys)
{
WCHAR buf [32768] = {0};
DWORD len = GetPrivateProfileSectionW (section.c_str (), buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
keys.clear ();
if (len == 0) return 0;
WCHAR* ptr = buf;
while (*ptr)
{
std::wstring line = ptr;
size_t pos = line.find (L'=');
if (pos != std::wstring::npos) keys.push_back (line.substr (0, pos));
ptr += wcslen (ptr) + 1;
}
return keys.size ();
}
size_t GetPrivateProfileKeysA (const std::string &filePath, const std::string &section, std::vector <std::string> &keys)
{
char buf [32768] = {0};
DWORD len = GetPrivateProfileSectionA (section.c_str (), buf, sizeof (buf), filePath.c_str ());
keys.clear ();
if (len == 0)
return 0;
char *ptr = buf;
while (*ptr)
{
std::string line = ptr;
size_t pos = line.find ('=');
if (pos != std::string::npos) keys.push_back (line.substr (0, pos));
ptr += strlen (ptr) + 1;
}
return keys.size ();
}
bool DeletePrivateProfileKeyA (const std::string &filePath, const std::string &section, const std::string &key)
{
return WritePrivateProfileStringA (section.c_str (), key.c_str (), NULL, filePath.c_str ()) != FALSE;
}
bool DeletePrivateProfileKeyW (const std::wstring &filePath, const std::wstring &section, const std::wstring &key)
{
return WritePrivateProfileStringW (section.c_str (), key.c_str (), NULL, filePath.c_str ()) != FALSE;
}
bool DeletePrivateProfileSectionA (const std::string &filePath, const std::string &section)
{
return WritePrivateProfileStringA (section.c_str (), NULL, NULL, filePath.c_str ()) != FALSE;
}
bool DeletePrivateProfileSectionW (const std::wstring &filePath, const std::wstring &section)
{
return WritePrivateProfileStringW (section.c_str (), NULL, NULL, filePath.c_str ()) != FALSE;
}
class initkey
{
public:
using pstring = std::string &;
using pwstring = std::wstring &;
using pcstring = const std::string &;
using pcwstring = const std::wstring &;
private:
pcwstring filepath;
pcwstring section;
template <typename T, typename Trans = T, typename Func> T read_t (T defaultvalue, Func process) const
{
auto res = read_wstring (std::to_wstring ((Trans)defaultvalue));
if (IsNormalizeStringEmpty (res)) return defaultvalue;
return (T)process (res.c_str ());
}
template <typename T> bool write_t (T value) { return write_string (std::to_wstring (value)); }
public:
std::wstring key;
initkey (pcwstring path, pcwstring sect, pcwstring k): filepath (path), section (sect), key (k) {}
std::wstring read_wstring (pcwstring defaultvalue = L"") const { return GetPrivateProfileStringW (filepath, section, key, defaultvalue.c_str ()); }
std::string read_string (pcstring defaultvalue = "") const { return WStringToString (read_wstring (StringToWString (defaultvalue))); }
short read_short (short defaultvalue = 0) const { return read_t (defaultvalue, _wtoi16); }
unsigned short read_ushort (unsigned short defaultvalue = 0) const { return read_t (defaultvalue, _wtoui16); }
int read_int (int defaultvalue = 0) const { return read_t (defaultvalue, _wtoi); }
unsigned int read_uint (unsigned int defaultvalue = 0) const { return read_t (defaultvalue, _wtou); }
long read_long (long defaultvalue = 0) const { return read_t (defaultvalue, _wtol); }
unsigned long read_ulong (unsigned long defaultvalue = 0) const { return read_t (defaultvalue, _wtoul); }
long long read_llong (long long defaultvalue = 0) const { return read_t (defaultvalue, _wtoll); }
unsigned long long read_ullong (unsigned long long defaultvalue = 0) const { return read_t (defaultvalue, _wtou64); }
float read_float (float defaultvalue = 0) const { return read_t (defaultvalue, _wtof); }
double read_double (double defaultvalue = 0) const { return read_t (defaultvalue, _wtod); }
bool read_bool (bool defaultvalue = false) const
{
std::wnstring res = read_wstring (defaultvalue ? L"true" : L"false");
if (res.empty ()) return defaultvalue;
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
else return defaultvalue;
}
int8_t read_i8 (int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (defaultvalue, _wtoi8); }
uint8_t read_u8 (uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (defaultvalue, _wtoui8); }
int16_t read_i16 (int16_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi16); }
uint16_t read_u16 (uint16_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoui16); }
int32_t read_i32 (int32_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi32); }
uint32_t read_u32 (uint32_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoui32); }
int64_t read_i64 (int64_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi64); }
uint64_t read_u64 (uint64_t defaultvalue = 0) const { return read_t (defaultvalue, _wtou64); }
bool read_struct (void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
template <typename T> bool read_struct (T &structinst) const { return read_struct (&structinst, sizeof (structinst)); }
bool write_string (pcwstring value) { return write (value); }
bool write_string (pcstring value) { return write (value); }
bool write (pcwstring value) { return WritePrivateProfileStringW (filepath, section, key, value); }
bool write (pcstring value) { return write (StringToWString (value)); }
bool write (int value) { return write_t (value); }
bool write (unsigned int value) { return write_t (value); }
bool write (short value) { return write_t (value); }
bool write (unsigned short value) { return write_t (value); }
bool write (long value) { return write_t (value); }
bool write (unsigned long value) { return write_t (value); }
bool write (long long value) { return write_t (value); }
bool write (unsigned long long value) { return write_t (value); }
bool write (int8_t value) { return write_t ((int16_t)value); }
bool write (uint8_t value) { return write_t ((uint16_t)value); }
bool write (float value) { return write_t (value); }
bool write (double value) { return write_t (value); }
bool write (bool value) { return write (value ? L"true" : L"false"); }
bool write (void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
operator std::wstring () { return read_wstring (); }
operator std::string () { return read_string (); }
template <typename T> initkey &operator = (T value) { write (value); return *this; }
initkey &operator = (const initkey &) = delete;
// ɾ³ýÏî
bool clear () { return DeletePrivateProfileKeyW (filepath, section, key); }
bool empty () const { return read_wstring ().empty (); }
#define OPERATOR_TYPE_READ(_type_, _method_) \
operator _type_ () { return _method_ (); }
OPERATOR_TYPE_READ (int, read_int)
OPERATOR_TYPE_READ (unsigned int, read_uint)
OPERATOR_TYPE_READ (long, read_long)
OPERATOR_TYPE_READ (unsigned long, read_ulong)
OPERATOR_TYPE_READ (long long, read_llong)
OPERATOR_TYPE_READ (unsigned long long, read_ullong)
OPERATOR_TYPE_READ (short, read_short)
OPERATOR_TYPE_READ (unsigned short, read_ushort)
OPERATOR_TYPE_READ (float, read_float)
OPERATOR_TYPE_READ (double, read_double)
OPERATOR_TYPE_READ (bool, read_bool)
#ifdef OPERATOR_TYPE_READ
#undef OPERATOR_TYPE_READ
#endif
};
class initsection
{
private:
const std::wstring &filepath;
template <typename T, typename Trans = T, typename CT, typename Func> T read_t (const std::basic_string <CT> &key, T defaultvalue, Func process) const
{
std::basic_string <CT> temp;
auto res = read_string (key, TypeToString ((Trans)defaultvalue, temp));
if (IsNormalizeStringEmpty (res)) return defaultvalue;
return (T)process (res.c_str ());
}
template <typename T, typename CT> bool write_t (const std::basic_string <CT> &key, T value)
{
std::basic_string <CT> temp;
return write_string (key, TypeToString (value, temp));
}
public:
using pcstring = const std::string &;
using pcwstring = const std::wstring &;
std::wstring section;
initsection (const std::wstring &path, const std::wstring &sect): filepath (path), section (sect) {}
size_t keys (std::vector <std::wstring> &output) const { return GetPrivateProfileKeysW (filepath, section, output); }
size_t keys (std::vector <std::string> &output) const { return GetPrivateProfileKeysA (WStringToString (filepath), WStringToString (section), output); }
bool key_values (const std::vector <std::wstring> &lines) { return WritePrivateProfileSectionW (filepath, section, lines); }
bool key_values (const std::vector <std::string> &lines) { return WritePrivateProfileSectionA (WStringToString (filepath), WStringToString (section), lines); }
size_t key_values (std::vector <std::wstring> &output) const { return GetPrivateProfileSectionW (filepath, section, output); }
size_t key_values (std::vector <std::string> &output) const { return GetPrivateProfileSectionA (WStringToString (filepath), WStringToString (section), output); }
std::wstring read_string (const std::wstring &key, const std::wstring &defaultvalue = L"") const { return GetPrivateProfileStringW (filepath, section, key, defaultvalue.c_str ()); }
std::string read_string (const std::string &key, const std::string &defaultvalue = "") const { return WStringToString (read_string (StringToWString (key), StringToWString (defaultvalue))); }
std::wstring read_wstring (const std::wstring &key, const std::wstring &defaultvalue = L"") const { return read_string (key, defaultvalue); }
int read_int (const std::wstring &key, int defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi); }
int read_int (const std::string &key, int defaultvalue = 0) const { return read_t (key, defaultvalue, atoi); }
unsigned int read_uint (const std::wstring &key, unsigned int defaultvalue = 0) const { return read_t (key, defaultvalue, _wtou); }
unsigned int read_uint (const std::string &key, unsigned int defaultvalue = 0) const { return read_t (key, defaultvalue, atou); }
long read_long (const std::wstring &key, long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtol); }
long read_long (const std::string &key, long defaultvalue = 0) const { return read_t (key, defaultvalue, atol); }
unsigned long read_ulong (const std::wstring &key, unsigned long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoul); }
unsigned long read_ulong (const std::string &key, unsigned long defaultvalue = 0) const { return read_t (key, defaultvalue, atoul); }
long long read_llong (const std::wstring &key, long long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoll); }
long long read_llong (const std::string &key, long long defaultvalue = 0) const { return read_t (key, defaultvalue, atoll); }
unsigned long long read_ullong (const std::wstring &key, unsigned long long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtou64); }
unsigned long long read_ullong (const std::string &key, unsigned long long defaultvalue = 0) const { return read_t (key, defaultvalue, atou64); }
int8_t read_i8 (const std::wstring &key, int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (key, defaultvalue, _wtoi8); }
int8_t read_i8 (const std::string &key, int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (key, defaultvalue, atoi8); }
uint8_t read_u8 (const std::wstring &key, uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (key, defaultvalue, _wtoui8); }
uint8_t read_u8 (const std::string &key, uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (key, defaultvalue, atoui8); }
int16_t read_i16 (const std::wstring &key, int16_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi16); }
int16_t read_i16 (const std::string &key, int16_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi16); }
short read_short (pcwstring key, short defaultvalue = 0) const { return read_i16 (key, defaultvalue); }
short read_short (pcstring key, short defaultvalue = 0) const { return read_i16 (key, defaultvalue); }
unsigned short read_ushort (pcwstring key, unsigned short defaultvalue = 0) const { return read_u16 (key, defaultvalue); }
unsigned short read_ushort (pcstring key, unsigned short defaultvalue = 0) const { return read_u16 (key, defaultvalue); }
uint16_t read_u16 (const std::wstring &key, uint16_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoui16); }
uint16_t read_u16 (const std::string &key, uint16_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoui16); }
int32_t read_i32 (const std::wstring &key, int32_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi32); }
int32_t read_i32 (const std::string &key, int32_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi32); }
uint32_t read_u32 (const std::wstring &key, uint32_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoui32); }
uint32_t read_u32 (const std::string &key, uint32_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoui32); }
int64_t read_i64 (const std::wstring &key, int64_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi64); }
int64_t read_i64 (const std::string &key, int64_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi64); }
uint64_t read_u64 (const std::wstring &key, uint64_t defaultvalue = 0) const { return read_ullong (key, defaultvalue); }
uint64_t read_u64 (const std::string &key, uint64_t defaultvalue = 0) const { return read_ullong (key, defaultvalue); }
float read_float (const std::wstring &key, float defaultvalue = 0) const { return read_t (key, defaultvalue, _wtof); }
double read_double (const std::wstring &key, double defaultvalue = 0) const { return read_t (key, defaultvalue, _wtod); }
bool read_bool (const std::wstring &key, bool defaultvalue = false) const
{
std::wnstring res = read_string (key, defaultvalue ? L"true" : L"false");
if (res.empty ()) return defaultvalue;
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
else return defaultvalue;
}
bool read_bool (const std::string &key, bool defaultvalue = false) const { return read_bool (StringToWString (key), defaultvalue); }
bool read_struct (const std::wstring &key, void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
template <typename T> bool read_struct (const std::wstring &key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
bool write_string (const std::wstring &key, const std::wstring &value) { return WritePrivateProfileStringW (filepath, section, key, value); }
bool write_string (const std::string &key, const std::string &value) { return write_string (StringToWString (key), StringToWString (value)); }
bool write (const std::wstring &key, const std::wstring &value) { return write_string (key, value); }
bool write (const std::string &key, const std::string &value) { return write_string (key, value); }
bool write (pcwstring key, short value) { return write_t (key, value); }
bool write (pcwstring key, unsigned short value) { return write_t (key, value); }
bool write (pcwstring key, int value) { return write_t (key, value); }
bool write (pcwstring key, unsigned int value) { return write_t (key, value); }
bool write (pcwstring key, long value) { return write_t (key, value); }
bool write (pcwstring key, unsigned long value) { return write_t (key, value); }
bool write (pcwstring key, long long value) { return write_t (key, value); }
bool write (pcwstring key, unsigned long long value) { return write_t (key, value); }
bool write (pcwstring key, int8_t value) { return write_t (key, (int16_t)value); }
bool write (pcwstring key, uint8_t value) { return write_t (key, (uint16_t)value); }
bool write (pcwstring key, bool value) { return write (key, value ? L"true" : L"false"); }
bool write (pcstring key, short value) { return write_t (key, value); }
bool write (pcstring key, unsigned short value) { return write_t (key, value); }
bool write (pcstring key, int value) { return write_t (key, value); }
bool write (pcstring key, unsigned int value) { return write_t (key, value); }
bool write (pcstring key, long value) { return write_t (key, value); }
bool write (pcstring key, unsigned long value) { return write_t (key, value); }
bool write (pcstring key, long long value) { return write_t (key, value); }
bool write (pcstring key, unsigned long long value) { return write_t (key, value); }
bool write (pcstring key, int8_t value) { return write_t (key, (int16_t)value); }
bool write (pcstring key, uint8_t value) { return write_t (key, (uint16_t)value); }
bool write (pcstring key, bool value) { return write (StringToWString (key), value ? L"true" : L"false"); }
bool write (pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
bool write (pcstring key, void *buf, size_t bufsize) { return write (StringToWString (key), buf, bufsize); }
initkey operator [] (pcwstring key) { return initkey (filepath, section, key); }
initkey operator [] (pcstring key) { return initkey (filepath, section, StringToWString (key)); }
std::wstring operator [] (pcwstring key) const { return read_string (key); }
std::wstring operator [] (pcstring key) const { return read_string (StringToWString (key)); }
bool delete_key (pcwstring key) { return DeletePrivateProfileKeyW (filepath, section, key); }
bool delete_key (pcstring key) { return delete_key (StringToWString (key)); }
bool clear () { return DeletePrivateProfileSectionW (filepath, section); }
initkey get_key (pcwstring key) const { return initkey (filepath, section, key); }
initkey get_key (pcwstring key) { return initkey (filepath, section, key); }
initkey get_key (pcstring key) const { return initkey (filepath, section, StringToWString (key)); }
initkey get_key (pcstring key) { return initkey (filepath, section, StringToWString (key)); }
initsection &operator = (const initsection &) = delete;
};
class initfile
{
public:
using pstring = std::string &;
using pwstring = std::wstring &;
using pcstring = const std::string &;
using pcwstring = const std::wstring &;
std::wstring filepath;
private:
template <typename T, typename TRANS = T, typename FN> T read_t (pcwstring section, pcwstring key, T defaultvalue, FN process) const
{
auto res = read_wstring (section, key, std::to_wstring ((TRANS)defaultvalue));
if (IsNormalizeStringEmpty (res)) return defaultvalue;
return (T)process (res.c_str ());
}
template <typename T> bool write_t (pcwstring section, pcwstring key, T value) { return write (section, key, std::to_wstring (value)); }
public:
initfile (const std::wstring &initpath): filepath (initpath) {}
size_t sections (std::vector <std::wstring> &sect) const { return GetPrivateProfileSectionNamesW (filepath, sect); }
size_t sections (std::vector <std::string> &sect) const { return GetPrivateProfileSectionNamesA (WStringToString (filepath), sect); }
bool delete_section (pcwstring section) { return DeletePrivateProfileSectionW (filepath, section); }
bool delete_section (pcstring section) { return delete_section (StringToWString (section)); }
size_t key_values (pcwstring section, std::vector <std::wstring> &keyvalues) const { return GetPrivateProfileSectionW (filepath, section, keyvalues); }
size_t key_values (pcstring section, std::vector <std::string> &keyvalues) const { return GetPrivateProfileSectionA (WStringToString (filepath), section, keyvalues); }
size_t keys (pcwstring section, std::vector <std::wstring> &keyvalues) const { return GetPrivateProfileKeysW (filepath, section, keyvalues); }
size_t keys (pcstring section, std::vector <std::string> &keyvalues) const { return GetPrivateProfileKeysA (WStringToString (filepath), section, keyvalues); }
initsection get_section (pcwstring section) { return initsection (filepath, section); }
initsection get_section (pcwstring section) const { return initsection (filepath, section); }
std::wstring read_wstring (pcwstring section, pcwstring key, pcwstring dflt = L"") const { return GetPrivateProfileStringW (filepath, section, key, dflt.c_str ()); }
std::string read_string (pcwstring section, pcwstring key, pcstring dflt = "") const { return WStringToString (read_wstring (section, key, StringToWString (dflt))); }
#define INIT_READ_WARGS(_type_, _dfltvalue_) pcwstring section, pcwstring key, _type_ dflt = _dfltvalue_
#define METHOD_INIT_READ(_type_, _typename_, _dfltvalue_, _process_) \
_type_ read_##_typename_ (INIT_READ_WARGS (_type_, _dfltvalue_)) const { return read_t (section, key, dflt, _process_); }
METHOD_INIT_READ (int, int, 0, _wtoi)
METHOD_INIT_READ (unsigned int, uint, 0, _wtou)
METHOD_INIT_READ (long, long, 0, _wtol)
METHOD_INIT_READ (unsigned long, ulong, 0, _wtoul)
METHOD_INIT_READ (long long, llong, 0, _wtoll)
METHOD_INIT_READ (unsigned long, ullong, 0, _wtou64)
METHOD_INIT_READ (short, short, 0, _wtoi16)
METHOD_INIT_READ (unsigned short, ushort, 0, _wtoui16)
METHOD_INIT_READ (int16_t, i16, 0, _wtoi16)
METHOD_INIT_READ (uint16_t, u16, 0, _wtoui16)
METHOD_INIT_READ (int32_t, i32, 0, _wtoi32)
METHOD_INIT_READ (uint32_t, u32, 0, _wtoui32)
METHOD_INIT_READ (int64_t, i64, 0, _wtoi64)
METHOD_INIT_READ (uint64_t, u64, 0, _wtou64)
METHOD_INIT_READ (float, float, 0, _wtof)
METHOD_INIT_READ (double, double, 0, _wtod)
int8_t read_i8 (INIT_READ_WARGS (int8_t, 0)) const { return read_t <int8_t, int16_t> (section, key, dflt, _wtoi8); }
uint8_t read_u8 (INIT_READ_WARGS (uint8_t, 0)) const { return read_t <uint8_t, uint16_t> (section, key, dflt, _wtoui8); }
bool read_bool (INIT_READ_WARGS (bool, false)) const
{
std::wnstring res = read_wstring (section, key, dflt ? L"true" : L"false");
if (res.empty ()) return dflt;
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
else return dflt;
}
bool read_struct (pcwstring section, pcwstring key, void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
template <typename T> bool read_struct (pcwstring section, pcwstring key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
#ifdef INIT_READ_WARGS
#undef INIT_READ_WARGS
#endif
#ifdef METHOD_INIT_READ
#undef METHOD_INIT_READ
#endif
#define INIT_WRITE_WARGS(_type_) pcwstring section, pcwstring key, _type_ value
bool write (INIT_WRITE_WARGS (pcwstring)) { return WritePrivateProfileStringW (filepath, section, key, value); }
#define METHOD_INIT_WRITE(_type_) \
bool write (INIT_WRITE_WARGS (_type_)) { return write_t (section, key, value); }
METHOD_INIT_WRITE (short)
METHOD_INIT_WRITE (unsigned short)
METHOD_INIT_WRITE (int)
METHOD_INIT_WRITE (unsigned int)
METHOD_INIT_WRITE (long)
METHOD_INIT_WRITE (unsigned long)
METHOD_INIT_WRITE (long long)
METHOD_INIT_WRITE (unsigned long long)
METHOD_INIT_WRITE (float)
METHOD_INIT_WRITE (double)
bool write (INIT_WRITE_WARGS (bool)) { return write (section, key, value ? L"true" : L"false"); }
bool write (INIT_WRITE_WARGS (int8_t)) { return write_t (section, key, (int16_t)value); }
bool write (INIT_WRITE_WARGS (uint8_t)) { return write_t (section, key, (uint16_t)value); }
bool write (pcwstring section, pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
initsection operator [] (pcwstring section) { return initsection (filepath, section); }
initsection operator [] (pcstring section) { return initsection (filepath, StringToWString (section)); }
initsection operator [] (pcwstring section) const { return initsection (filepath, section); }
initsection operator [] (pcstring section) const { return initsection (filepath, StringToWString (section)); }
#ifdef METHOD_INIT_WRITE
#undef METHOD_INIT_WRITE
#endif
#ifdef INIT_WRITE_WARGS
#undef INIT_WRITE_WARGS
#endif
};
#ifdef __cplusplus_cli
namespace Win32
{
using namespace System;
using namespace System::Runtime::InteropServices;
[ComVisible (true)]
public ref class Key
{
private:
String ^filepath = "";
String ^section = "";
String ^key = "";
public:
property String ^FilePath { String ^get () { return filepath; }}
property String ^Section { String ^get () { return section; }}
property String ^KeyName { String ^get () { return key; }}
Key (String ^file, String ^sect, String ^k): filepath (file), section (sect), key (k) {}
Object ^Get (Object ^dflt)
{
auto res = GetPrivateProfileStringW (
MPStringToStdW (filepath),
MPStringToStdW (section),
MPStringToStdW (key),
dflt ? MPStringToStdW (dflt->ToString ()).c_str () : L""
);
return CStringToMPString (res);
}
Object ^Get ()
{
auto res = GetPrivateProfileStringW (
MPStringToStdW (filepath),
MPStringToStdW (section),
MPStringToStdW (key)
);
return CStringToMPString (res);
}
bool Set (Object ^value)
{
return WritePrivateProfileStringW (
MPStringToStdW (filepath),
MPStringToStdW (section),
MPStringToStdW (key),
MPStringToStdW (value ? value->ToString () : L"")
);
}
property Object ^Value { Object ^get () { return Get (); } void set (Object ^value) { Set (value); } }
Key %operator = (Object ^value) { Value = value; return *this; }
operator String ^ () { return Value->ToString (); }
explicit operator bool ()
{
auto boolstr = Value->ToString ()->Trim ()->ToLower ();
if (boolstr == "true" || boolstr == "zhen" || boolstr == "yes" || boolstr == "Õæ") return true;
else if (boolstr == "false" || boolstr == "jia" || boolstr == "no" || boolstr == "¼Ù") return false;
else return false;
}
#define OPERATOR_TRANSITION_DEFINE(type, transfunc, defaultret) \
operator type () { try { transfunc (Value->ToString ()); } catch (...) { return defaultret; }}
OPERATOR_TRANSITION_DEFINE (int8_t, Convert::ToSByte, 0)
OPERATOR_TRANSITION_DEFINE (uint8_t, Convert::ToByte, 0)
OPERATOR_TRANSITION_DEFINE (int16_t, Convert::ToInt16, 0)
OPERATOR_TRANSITION_DEFINE (uint16_t, Convert::ToUInt16, 0)
OPERATOR_TRANSITION_DEFINE (int32_t, Convert::ToInt32, 0)
OPERATOR_TRANSITION_DEFINE (uint32_t, Convert::ToUInt32, 0)
OPERATOR_TRANSITION_DEFINE (int64_t, Convert::ToInt64, 0)
OPERATOR_TRANSITION_DEFINE (uint64_t, Convert::ToUInt64, 0)
OPERATOR_TRANSITION_DEFINE (float, Convert::ToSingle, 0)
OPERATOR_TRANSITION_DEFINE (double, Convert::ToDouble, 0)
OPERATOR_TRANSITION_DEFINE (System::Decimal, Convert::ToDecimal, 0)
OPERATOR_TRANSITION_DEFINE (System::DateTime, Convert::ToDateTime, Convert::ToDateTime (0))
#ifdef OPERATOR_TRANSITION_DEFINE
#undef OPERATOR_TRANSITION_DEFINE
#endif
};
[ComVisible (true)]
public ref class Section
{
private:
String ^filepath = "";
String ^section = "";
public:
property String ^FilePath { String ^get () { return filepath; } }
property String ^SectionName { String ^get () { return section; } }
Section (String ^file, String ^sect): filepath (file), section (sect) {}
Key ^GetKey (String ^key) { return gcnew Key (filepath, section, key); }
Object ^Get (String ^key, Object ^dflt) { return GetKey (key)->Get (dflt); }
Object ^Get (String ^key) { return GetKey (key)->Get (); }
bool Set (String ^key, Object ^value) { return GetKey (key)->Set (value); }
Key ^operator [] (String ^key) { return GetKey (key); }
};
[ComVisible (true)]
public ref class InitConfig
{
private:
String ^filepath = "";
public:
property String ^FilePath { String ^get () { return filepath; } void set (String ^path) { filepath = path; } }
InitConfig (String ^path): filepath (path) {}
InitConfig () {}
Section ^GetSection (String ^section) { return gcnew Section (filepath, section); }
Key ^GetKey (String ^section, String ^key) { return gcnew Key (filepath, section, key); }
Object ^Get (String ^section, String ^key, String ^dflt) { return GetKey (section, key)->Get (dflt); }
Object ^Get (String ^section, String ^key) { return GetKey (section, key)->Get (); }
Section ^Get (String ^section) { return GetSection (section); }
bool Set (String ^section, String ^key, String ^value) { return GetKey (section, key)->Set (value); }
Section ^operator [] (String ^section) { return GetSection (section); }
};
}
#endif
+249
View File
@@ -0,0 +1,249 @@
#pragma once
#include <WinNls.h>
#include <string>
#include "typestrans.h"
#include "strcode.h"
#undef GetLocaleInfo
std::string GetLocaleInfoA (LCID code, LCTYPE type)
{
char buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetLocaleInfoA (code, type, buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
std::wstring GetLocaleInfoW (LCID code, LCTYPE type)
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetLocaleInfoW (code, type, buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
void GetLocaleInfo (LCID code, LCTYPE type, std::wstring &output)
{
output = GetLocaleInfoW (code, type);
}
void GetLocaleInfo (LCID code, LCTYPE type, std::string &output)
{
output = GetLocaleInfoA (code, type);
}
int GetLocaleInfoEx (std::wstring lpLocaleName, LCTYPE type, std::wstring &output)
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
int res = GetLocaleInfoEx (lpLocaleName.c_str (), type, buf, LOCALE_NAME_MAX_LENGTH);
if (&output) output = std::wstring (buf);
return res;
}
#undef SetLocaleInfo
BOOL SetLocaleInfoA (LCID code, LCTYPE type, const std::string &lcData)
{
return SetLocaleInfoA (code, type, lcData.c_str ());
}
BOOL SetLocaleInfoW (LCID code, LCTYPE type, const std::wstring &lcData)
{
return SetLocaleInfoW (code, type, lcData.c_str ());
}
BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::wstring &lcData)
{
return SetLocaleInfoW (code, type, lcData);
}
BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::string &lcData)
{
return SetLocaleInfoA (code, type, lcData);
}
std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid)
{
return GetLocaleInfoA (lcid, 89);
}
std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid)
{
return GetLocaleInfoW (lcid, 89);
}
void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::string &ret)
{
ret = GetLocaleRestrictedCodeFromLcidA (lcid);
}
void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::wstring &ret)
{
ret = GetLocaleRestrictedCodeFromLcidW (lcid);
}
std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid)
{
return GetLocaleInfoA (lcid, 90);
}
std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid)
{
return GetLocaleInfoW (lcid, 90);
}
void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::wstring &ret)
{
ret = GetLocaleElaboratedCodeFromLcidW (lcid);
}
void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::string &ret)
{
ret = GetLocaleElaboratedCodeFromLcidA (lcid);
}
LCID LocaleCodeToLcidW (const std::wstring &localeCode)
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0};
int res = GetLocaleInfoEx (localeCode.c_str (), LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH);
LCID lcid = *((LCID *)buf);
return lcid;
}
catch (const std::exception &e) {}
return LocaleNameToLCID (localeCode.c_str (), 0);
#else
return LocaleNameToLCID (localeCode.c_str (), 0);
#endif
}
LCID LocaleCodeToLcidA (const std::string &localeCode)
{
std::wstring lcWide = StringToWString (std::string (localeCode));
return LocaleCodeToLcidW (lcWide.c_str ());
}
LCID LocaleCodeToLcid (const std::wstring &loccode)
{
return LocaleCodeToLcidW (loccode.c_str ());
}
LCID LocaleCodeToLcid (const std::string &loccode)
{
return LocaleCodeToLcidA (loccode.c_str ());
}
std::string GetLocaleRestrictedCodeA (LPCSTR lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc), 89);
}
std::string GetLocaleRestrictedCodeA (const std::string &lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 89);
}
std::wstring GetLocaleRestrictedCodeW (LPCWSTR lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc), 89);
}
std::wstring GetLocaleRestrictedCodeW (const std::wstring &lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 89);
}
std::wstring GetLocaleRestrictedCode (const std::wstring &lc) { return GetLocaleRestrictedCodeW (lc); }
std::string GetLocaleRestrictedCode (const std::string &lc) { return GetLocaleRestrictedCodeA (lc); }
std::string GetLocaleElaboratedCodeA (LPCSTR lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc), 90);
}
std::string GetLocaleElaboratedCodeA (const std::string &lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 90);
}
std::wstring GetLocaleElaboratedCodeW (LPCWSTR lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc), 90);
}
std::wstring GetLocaleElaboratedCodeW (const std::wstring &lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 90);
}
std::wstring GetLocaleElaboratedCode (const std::wstring &lc) { return GetLocaleElaboratedCodeW (lc); }
std::string GetLocaleElaboratedCode (const std::string &lc) { return GetLocaleElaboratedCodeA (lc); }
std::string LcidToLocaleCodeA (LCID lcid, char divide = '-')
{
return GetLocaleRestrictedCodeFromLcidA (lcid) + divide + GetLocaleElaboratedCodeFromLcidA (lcid);
}
std::wstring LcidToLocaleCodeW (LCID lcid, WCHAR divide = L'-')
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
LCIDToLocaleName (lcid, buf, LOCALE_NAME_MAX_LENGTH, 0);
return buf;
}
catch (const std::exception &e) {}
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
#else
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
#endif
}
std::wstring LcidToLocaleCode (LCID lcid, WCHAR divide = L'-') { return LcidToLocaleCodeW (lcid, divide); }
std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); }
std::wstring GetUserDefaultLocaleName ()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
catch (const std::exception &e) {}
return LcidToLocaleCodeW (GetUserDefaultLCID ());
#else
return LcidToLocaleCodeW (GetUserDefaultLCID ());
#endif
}
std::wstring GetSystemDefaultLocaleName ()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
catch (const std::exception &e) {}
return LcidToLocaleCodeW (GetSystemDefaultLCID ());
#else
return LcidToLocaleCodeW (GetSystemDefaultLCID ());
#endif
}
std::wstring GetComputerLocaleCodeW ()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
{
try
{
{
LCID lcid = GetThreadLocale ();
std::wstring tmp = LcidToLocaleCodeW (lcid);
if (lcid && tmp.length () > 1) return tmp;
}
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
if (lstrlenW (buf)) return buf;
}
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
}
catch (const std::exception &e) {}
LCID lcid = GetThreadLocale ();
if (!lcid) lcid = GetUserDefaultLCID ();
if (!lcid) lcid = GetSystemDefaultLCID ();
return LcidToLocaleCodeW (lcid);
}
#else
{
LCID lcid = GetThreadLocale ();
if (!lcid) lcid = GetUserDefaultLCID ();
if (!lcid) lcid = GetSystemDefaultLCID ();
return LcidToLocaleCodeW (lcid);
}
#endif
}
bool LocaleNameCompare (const std::wstring &left, const std::wstring &right)
{
return std::wnstring::equals (left, right) || LocaleCodeToLcidW (left) == LocaleCodeToLcidW (right);
}
+923
View File
@@ -0,0 +1,923 @@
#include <Windows.h>
#include <set>
#include <msclr/marshal_cppstd.h>
#include <ShObjIdl.h>
#include <MsHTML.h>
#include <ExDisp.h>
#include <atlbase.h>
#include <fstream>
#include <comdef.h>
#include <vcclr.h>
#include <map>
#include <rapidjson\document.h>
#include <rapidjson\writer.h>
#include <rapidjson\stringbuffer.h>
#include "module.h"
#include "themeinfo.h"
#include "mpstr.h"
#include "initfile.h"
#include "vemani.h"
#include "ieshell.h"
#include "localeex.h"
#include "bridge.h"
#include "rctools.h"
#include "nstring.h"
#include "resmap.h"
#include "nstring.h"
#include "raii.h"
using namespace System;
using namespace System::Runtime::InteropServices;
#ifdef _DEBUG
#define DEBUGMODE true
#else
#define DEBUGMODE false
#endif
#define JS_SAFE [MarshalAs (UnmanagedType::SafeArray, SafeArraySubType = VarEnum::VT_VARIANT)]
struct iconhandle
{
HICON hIcon = nullptr;
iconhandle (HICON hIcon = nullptr): hIcon (hIcon) {}
~iconhandle () { try { if (hIcon) DestroyIcon (hIcon); hIcon = nullptr; } catch (...) {} }
};
LPCWSTR g_lpAppId = L"WindowsModern.PracticalToolsProject!Settings";
LPCWSTR g_idInVe = L"Settings";
iconhandle g_hIconMain (LoadRCIcon (IDI_ICON_MAIN));
initfile g_initfile (CombinePath (GetProgramRootDirectoryW (), L"config.ini"));
vemanifest g_vemani (
IsFileExists (CombinePath (GetProgramRootDirectoryW (), L"VisualElementsManifest.xml")) ?
CombinePath (GetProgramRootDirectoryW (), L"VisualElementsManifest.xml") :
CombinePath (GetProgramRootDirectoryW (), L"Settings.VisualElementsManifest.xml")
);
resxmldoc g_scaleres (
IsFileExists (CombinePath (GetProgramRootDirectoryW (), L"VisualElements\\scale.xml")) ?
CombinePath (GetProgramRootDirectoryW (), L"VisualElements\\scale.xml") :
CombinePath (GetProgramRootDirectoryW (), L"VisualElementsManifest.xml")
);
ref class MainHtmlWnd;
msclr::gcroot <MainHtmlWnd ^> g_mainwnd;
std::wstring g_lastfile;
inline std::wstring ToStdWString (const std::wstring &str) { return str; }
size_t ExploreFile (HWND hParent, std::vector <std::wstring> &results, LPWSTR lpFilter = L"Windows Store App Package (*.appx; *.appxbundle)\0*.appx;*.appxbundle", DWORD dwFlags = OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST, const std::wstring &swWndTitle = std::wstring (L"Please select the file(-s): "), const std::wstring &swInitDir = GetFileDirectoryW (g_lastfile))
{
results.clear ();
const DWORD BUFFER_SIZE = 65536; // 64KB
std::vector <WCHAR> buffer (BUFFER_SIZE, 0);
OPENFILENAME ofn;
ZeroMemory (&ofn, sizeof (ofn));
ofn.hwndOwner = hParent;
ofn.lpstrFile = (LPWSTR)buffer.data ();
ofn.nMaxFile = BUFFER_SIZE;
ofn.lpstrFilter = lpFilter;
ofn.nFilterIndex = 1;
ofn.lpstrTitle = swWndTitle.c_str ();
ofn.Flags = dwFlags;
ofn.lpstrInitialDir = swInitDir.c_str ();
ofn.lStructSize = sizeof (ofn);
if (GetOpenFileNameW (&ofn))
{
LPCWSTR p = buffer.data ();
std::wstring dir = p;
p += dir.length () + 1;
if (*p == 0) results.push_back (dir);
else
{
while (*p)
{
std::wstring fullPath = dir + L"\\" + p;
results.push_back (fullPath);
p += wcslen (p) + 1;
}
}
if (!results.empty ()) g_lastfile = results.back ();
}
return results.size ();
}
HRESULT GetWebBrowser2Interface (System::Windows::Forms::WebBrowser ^fwb, IWebBrowser2 **output)
{
if (fwb == nullptr || output == nullptr) return E_INVALIDARG;
*output = nullptr;
Object ^activeX = fwb->ActiveXInstance;
if (activeX == nullptr) return E_FAIL;
IntPtr pUnk = Marshal::GetIUnknownForObject (activeX);
if (pUnk == IntPtr::Zero) return E_FAIL;
HRESULT hr = ((IUnknown *)pUnk.ToPointer ())->QueryInterface (IID_IWebBrowser2, (void **)output);
Marshal::Release (pUnk);
return hr;
}
bool IsWindows10 ()
{
#pragma warning(push)
#pragma warning(disable:4996)
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
osvi.dwMajorVersion = 10;
DWORDLONG conditionMask = 0;
VER_SET_CONDITION (conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
if (VerifyVersionInfoW (&osvi, VER_MAJORVERSION, conditionMask)) return TRUE;
DWORD error = GetLastError ();
return (error == ERROR_OLD_WIN_VERSION) ? FALSE : FALSE;
#pragma warning(pop)
}
[ComVisible (true)]
public ref class _I_InitConfig
{
public:
Win32::InitConfig ^Create (String ^filepath) { return gcnew Win32::InitConfig (filepath); }
Win32::InitConfig ^GetConfig () { return Create (CStringToMPString (g_initfile.filepath)); }
};
[ComVisible (true)]
public ref class _I_Bridge_Base
{
protected:
_I_String ^str = gcnew _I_String ();
_I_InitConfig ^initconfig = gcnew _I_InitConfig ();
public:
property _I_String ^String { _I_String ^get () { return str; }}
property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }}
};
[ComVisible (true)]
public interface class IScriptBridge
{
public:
virtual Object ^CallEvent (String ^funcName, Object ^e) = 0;
};
[ComVisible (true)]
public ref class _I_Window
{
private:
IScriptBridge ^wndinst = nullptr;
public:
_I_Window (IScriptBridge ^wnd): wndinst (wnd) {}
Object ^CallEvent (String ^name, ... array <Object ^> ^args) { return wndinst->CallEvent (name, args [0]); }
};
[ComVisible (true)]
public ref class _I_UI
{
private:
System::Windows::Forms::Form ^wndinst = nullptr;
public:
ref struct _I_UI_Size
{
private:
int m_width = 0;
int m_height = 0;
public:
property int width { int get () { return m_width; } }
property int height { int get () { return m_height; }}
property int Width { int get () { return m_width; } }
property int Height { int get () { return m_height; }}
int getWidth () { return m_width; }
int getHeight () { return m_height; }
_I_UI_Size (int w, int h): m_width (w), m_height (h) {}
};
_I_UI (System::Windows::Forms::Form ^wnd): wndinst (wnd) {}
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
property _I_UI_Size ^WndSize { _I_UI_Size ^get () { return gcnew _I_UI_Size (wndinst->Width, wndinst->Height); } }
property _I_UI_Size ^ClientSize { _I_UI_Size ^get () { auto cs = wndinst->ClientSize; return gcnew _I_UI_Size (cs.Width, cs.Height); } }
property String ^ThemeColor { String ^get () { return ColorToHtml (GetDwmThemeColor ()); } }
property bool DarkMode { bool get () { return IsAppInDarkMode (); }}
property String ^HighContrast
{
String ^get ()
{
auto highc = GetHighContrastTheme ();
switch (highc)
{
case HighContrastTheme::None: return "none";
break;
case HighContrastTheme::Black: return "black";
break;
case HighContrastTheme::White: return "white";
break;
case HighContrastTheme::Other: return "high";
break;
default: return "none";
break;
}
return "none";
}
}
};
[ComVisible (true)]
public ref class _I_Locale
{
public:
property String ^CurrentLocale { String ^get () { return CStringToMPString (GetComputerLocaleCodeW ()); } }
property LCID CurrentLCID { LCID get () { return LocaleCodeToLcid (GetComputerLocaleCodeW ()); } }
String ^ToLocaleName (LCID lcid) { return CStringToMPString (LcidToLocaleCodeW (lcid)); }
LCID ToLCID (String ^localename) { return LocaleCodeToLcidW (MPStringToStdW (localename)); }
Object ^LocaleInfo (LCID lcid, LCTYPE lctype) { return CStringToMPString (GetLocaleInfoW (lcid, lctype)); }
Object ^LocaleInfoEx (String ^localeName, LCTYPE lctype)
{
std::wstring output = L"";
int ret = GetLocaleInfoEx (MPStringToStdW (localeName), lctype, output);
if (output.empty ()) return ret;
else return CStringToMPString (output);
}
};
[ComVisible (true)]
public ref class _I_System
{
private:
_I_Resources ^ires = gcnew _I_Resources ();
_I_Locale ^ilocale = gcnew _I_Locale ();
public:
property _I_Resources ^Resources { _I_Resources ^get () { return ires; } }
property _I_Locale ^Locale { _I_Locale ^get () { return ilocale; } }
property bool IsWindows10
{
bool get ()
{
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
osvi.dwMajorVersion = 10;
DWORDLONG conditionMask = 0;
VER_SET_CONDITION (conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
if (VerifyVersionInfoW (&osvi, VER_MAJORVERSION, conditionMask)) return TRUE;
DWORD error = GetLastError ();
return (error == ERROR_OLD_WIN_VERSION) ? FALSE : FALSE;
}
}
};
public ref class _I_System2: public _I_System
{
protected:
_I_UI ^ui;
public:
_I_System2 (System::Windows::Forms::Form ^wnd)
{
ui = gcnew _I_UI (wnd);
}
property _I_UI ^UI { _I_UI ^get () { return ui; } }
};
[ComVisible (true)]
public ref class _I_Bridge_Base2: public _I_Bridge_Base
{
protected:
_I_Window ^window;
public:
_I_Bridge_Base2 (IScriptBridge ^iscr)
{
window = gcnew _I_Window (iscr);
}
property _I_Window ^Window { _I_Window ^get () { return window; }}
};
[ComVisible (true)]
public ref class _I_Bridge_Base3: public _I_Bridge_Base2
{
protected:
_I_System2 ^system;
public:
_I_Bridge_Base3 (IScriptBridge ^iscr, System::Windows::Forms::Form ^form): _I_Bridge_Base2 (iscr)
{
system = gcnew _I_System2 (form);
}
property _I_System2 ^System { _I_System2 ^get () { return system; }}
};
[ComVisible (true)]
public ref class _I_IEFrame_Base
{
public:
property int Version { int get () { return GetInternetExplorerVersionMajor (); }}
String ^ParseHtmlColor (String ^color)
{
auto dcolor = Drawing::ColorTranslator::FromHtml (color);
{
rapidjson::Document doc;
doc.SetObject ();
auto &alloc = doc.GetAllocator ();
doc.AddMember ("r", (uint16_t)dcolor.R, alloc);
doc.AddMember ("g", (uint16_t)dcolor.G, alloc);
doc.AddMember ("b", (uint16_t)dcolor.B, alloc);
doc.AddMember ("a", (uint16_t)dcolor.A, alloc);
rapidjson::StringBuffer buffer;
rapidjson::Writer <rapidjson::StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return CStringToMPString (conv.from_bytes (utf8));
}
return "{}";
}
};
[ComVisible (true)]
public ref class SplashForm: public System::Windows::Forms::Form
{
public:
using PictureBox = System::Windows::Forms::PictureBox;
using Timer = System::Windows::Forms::Timer;
private:
PictureBox ^picbox;
Timer ^timer;
System::Drawing::Image ^splashimg = nullptr;
System::Drawing::Color background = System::Drawing::Color::Transparent;
// System::Windows::Forms ^parent = nullptr;
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);
}
}
};
[ComVisible (true)]
public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScriptBridge
{
public:
using WebBrowser = System::Windows::Forms::WebBrowser;
private:
WebBrowser ^webui;
SplashForm ^splash;
ITaskbarList3 *taskbar = nullptr;
public:
[ComVisible (true)]
ref class _I_UI2: public _I_UI
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
_I_UI2 (MainHtmlWnd ^wnd): wndinst (wnd), _I_UI (wnd) {}
property String ^SplashImage
{
String ^get ()
{
auto uri = gcnew Uri (CStringToMPString (wndinst->GetSuitSplashImage ()));
return uri->AbsoluteUri;
}
}
property String ^SplashBackgroundColor
{
String ^get ()
{
std::wnstring ret = L"";
auto personal = g_initfile [L"Personalization"];
auto thememode = personal [L"AppInstaller:ThemeMode"];
auto custommode = personal [L"AppInstaller:CustomThemeMode"];
bool nowdark =
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"dark") ||
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"auto") && IsAppInDarkMode () ||
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"custom") && IsNormalizeStringEquals (custommode.read_wstring ().c_str (), L"dark") ||
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"custom") && IsNormalizeStringEquals (custommode.read_wstring ().c_str (), L"auto") && IsAppInDarkMode ();
if (nowdark) ret = g_vemani.splash_screen_backgroundcolor_darkmode (g_idInVe);
else ret = g_vemani.splash_screen_backgroundcolor (g_idInVe);
if (ret.empty ()) ret = g_vemani.splash_screen_backgroundcolor (g_idInVe);
if (ret.empty ()) ret = g_vemani.background_color (g_idInVe);
return CStringToMPString (ret);
}
}
void ShowSplash () { if (wndinst->SplashScreen->IsHandleCreated) wndinst->SplashScreen->Show (); else wndinst->SplashScreen->ReInit (); }
void FadeAwaySplash () { wndinst->SplashScreen->FadeAway (); }
void FadeOutSplash () { wndinst->SplashScreen->FadeOut (); }
};
[ComVisible (true)]
ref class IBridge: public _I_Bridge_Base2
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
[ComVisible (true)]
ref class _I_IEFrame: public _I_IEFrame_Base
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
_I_IEFrame (MainHtmlWnd ^wnd): wndinst (wnd) {}
property int Scale
{
int get () { return wndinst->PageScale; }
void set (int value) { return wndinst->PageScale = value; }
}
};
[ComVisible (true)]
ref class _I_System3: public _I_System
{
protected:
_I_UI2 ^ui2;
public:
_I_System3 (MainHtmlWnd ^wnd)
{
ui2 = gcnew _I_UI2 (wnd);
}
property _I_UI2 ^UI { _I_UI2 ^get () { return ui2; } }
};
private:
_I_IEFrame ^ieframe;
_I_System3 ^sys;
_I_Storage ^storage;
public:
IBridge (MainHtmlWnd ^wnd): wndinst (wnd), _I_Bridge_Base2 (wnd)
{
ieframe = gcnew _I_IEFrame (wnd);
sys = gcnew _I_System3 (wnd);
storage = gcnew _I_Storage ();
}
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; }}
};
protected:
property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } }
property SplashForm ^SplashScreen { SplashForm ^get () { return this->splash; } }
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
void InitSize ()
{
unsigned ww = 0, wh = 0;
auto &ini = g_initfile;
auto setsect = ini ["Settings"];
auto savepos = setsect [L"Settings:SavePosAndSizeBeforeCancel"];
auto lastw = setsect [L"Settings:LastWidth"];
auto lasth = setsect [L"Settings:LastHeight"];
auto defw = setsect [L"Settings:DefaultWidth"];
auto defh = setsect [L"Settings:DefaultHeight"];
auto minw = setsect [L"Settings:MinimumWidth"];
auto minh = setsect [L"Settings:MinimumHeight"];
auto lasts = setsect [L"Settings:LastWndState"];
if (savepos.read_bool ())
{
ww = lastw.read_uint (defw.read_uint (rcInt (IDS_DEFAULTWIDTH)));
wh = lasth.read_uint (defh.read_uint (rcInt (IDS_DEFAULTHEIGHT)));
}
else
{
ww = defw.read_uint (rcInt (IDS_DEFAULTWIDTH));
wh = defh.read_uint (rcInt (IDS_DEFAULTHEIGHT));
}
this->ClientSize = System::Drawing::Size (ww * DPI, wh * DPI);
int hborder = this->Size.Width - this->ClientSize.Width,
vborder = this->Size.Height - this->ClientSize.Height;
this->MinimumSize = System::Drawing::Size (
minw.read_uint (rcInt (IDS_MINWIDTH)) * DPI + hborder,
minh.read_uint (rcInt (IDS_MINHIEHGT)) * DPI + vborder
);
this->WindowState = (System::Windows::Forms::FormWindowState)lasts.read_int ((int)System::Windows::Forms::FormWindowState::Normal);
}
void Init ()
{
this->Visible = false;
this->webui = gcnew System::Windows::Forms::WebBrowser ();
this->SuspendLayout ();
this->webui->Dock = System::Windows::Forms::DockStyle::Fill;
this->webui->IsWebBrowserContextMenuEnabled = DEBUGMODE;
this->webui->AllowWebBrowserDrop = false;
this->Controls->Add (this->webui);
if (g_hIconMain.hIcon)
{
try { this->Icon = System::Drawing::Icon::FromHandle (IntPtr (g_hIconMain.hIcon)); }
catch (...) {}
}
this->Text = GetRCStringCli (IDS_WINTITLE);
this->ResumeLayout (false);
webui->ObjectForScripting = gcnew IBridge (this);
this->webui->DocumentCompleted += gcnew System::Windows::Forms::WebBrowserDocumentCompletedEventHandler (this, &MainHtmlWnd::OnDocumentCompleted);
this->webui->PreviewKeyDown += gcnew System::Windows::Forms::PreviewKeyDownEventHandler (this, &MainHtmlWnd::OnPreviewKeyDown_WebBrowser);
this->Resize += gcnew System::EventHandler (this, &MainHtmlWnd::OnResize);
this->Load += gcnew EventHandler (this, &MainHtmlWnd::OnCreate);
this->ResizeEnd += gcnew EventHandler (this, &MainHtmlWnd::OnResizeEnd);
}
void OnDocumentCompleted (Object ^sender, System::Windows::Forms::WebBrowserDocumentCompletedEventArgs ^e)
{
static bool issetdpi = false;
if (!issetdpi)
{
issetdpi = true;
ExecScript ("Bridge.Frame.scale = Bridge.Frame.scale * Bridge.UI.dpi");
}
ExecScript ("Windows.UI.DPI.mode = 1");
if (e->Url->ToString () == webui->Url->ToString ())
{
auto &ini = g_initfile;
splash->FadeAway ();
}
}
void OnCreate (System::Object ^sender, System::EventArgs ^e)
{
splash->Owner = this;
splash->ChangePosAndSize ();
splash->Show ();
splash->Update ();
splash->SetSplashImage (GetSuitSplashImage ());
System::Windows::Forms::Application::DoEvents ();
auto htmlpath = CombinePath (GetProgramRootDirectoryW (), L"html\\settings.html");
webui->Navigate (CStringToMPString (htmlpath));
if (!IsFileExists (htmlpath))
{
std::wstring msg = L"Error: cannot find file \"" + htmlpath + L"\".";
MessageBoxW (InvokeGetHWND (), msg.c_str (), GetRCStringSW (IDS_WINTITLE).c_str (), MB_ICONERROR);
this->Close ();
return;
}
}
void OnPreviewKeyDown_WebBrowser (System::Object ^sender, System::Windows::Forms::PreviewKeyDownEventArgs ^e)
{
if (e->KeyCode == System::Windows::Forms::Keys::F5 || (e->KeyCode == System::Windows::Forms::Keys::R && e->Control))
e->IsInputKey = true;
}
void ResponseSplashChange ()
{
splash->SetSplashImage (GetSuitSplashImage ());
//ExecScript (
// "(function () {"
// "var splash = Page.splash;"
// "if (!splash) return null;"
// "splash.imagesrc = Bridge.UI.Splash.imageurl;"
// "splash.background = Bridge.UI.Splash.backcolor;"
// "var progress = splash.content.querySelector (\"progress\");"
// "if (Bridge.Frame.WindowSize.height / Bridge.UI.dpi < 500) {"
// "if (progress.classList.contains(\"win-ring\")) progress.classList.remove(\"win-ring\");}"
// "else { if (!progress.classList.contains(\"win-ring\")) progress.classList.add(\"win-ring\"); }"
// "}) ();"
//);
}
void OnResize (Object ^sender, EventArgs ^e) { ResizeEvent (); }
void OnResizeEnd (Object ^sender, EventArgs ^e) {}
std::wstring GetSuitSplashImage ()
{
int limitw = 800 * DPI;
int limith = 600 * DPI;
std::wstring tag = L"settings-splash";
int noww = this->Width;
int nowh = this->Height;
if (noww >= limitw && nowh >= limith)
tag = L"settings-splashlarge";
std::wstring path = g_scaleres [tag];
if (IsNormalizeStringEmpty (path))
path = g_scaleres [L"settings-splash"];
if (IsNormalizeStringEmpty (path))
path = g_vemani.splash_screen_image (g_idInVe);
return path;
}
void ResizeEvent ()
{
auto &ini = g_initfile;
auto setsect = ini ["Settings"];
auto lasts = setsect [L"AppInstaller:LastWndState"];
auto savepos = setsect [L"AppInstaller:SavePosAndSizeBeforeCancel"];
auto lastw = setsect [L"AppInstaller:LastWidth"];
auto lasth = setsect [L"AppInstaller:LastHeight"];
switch (this->WindowState)
{
case System::Windows::Forms::FormWindowState::Normal:
case System::Windows::Forms::FormWindowState::Maximized:
lasts = (int)this->WindowState;
}
if (this->WindowState == System::Windows::Forms::FormWindowState::Normal && savepos)
{
lastw = (int)(this->ClientSize.Width / DPI);
lasth = (int)(this->ClientSize.Height / DPI);
}
ResponseSplashChange ();
}
void InvokeClose ()
{
if (this->InvokeRequired) this->Invoke (gcnew Action (this, &MainHtmlWnd::Close));
else this->Close ();
}
IntPtr GetHWnd () { return this->Handle; }
delegate IntPtr GetHwndDelegate ();
HWND InvokeGetHWND ()
{
if (this->InvokeRequired)
{
GetHwndDelegate ^del = gcnew GetHwndDelegate (this, &MainHtmlWnd::GetHWnd);
IntPtr result = safe_cast <IntPtr> (this->Invoke (del));
return static_cast <HWND> (result.ToPointer ());
}
else return static_cast <HWND> (this->Handle.ToPointer ());
}
bool BackPage () { return this->webui->GoBack (); }
bool InvokeBackPage ()
{
if (this->InvokeRequired) return (bool)this->Invoke (gcnew Func <bool> (this, &MainHtmlWnd::BackPage));
else return BackPage (); // 当前线程就是 UI 线程
}
public:
MainHtmlWnd ()
{
InitSize ();
System::Windows::Forms::Application::DoEvents ();
splash = gcnew SplashForm (
CStringToMPString (GetSuitSplashImage ()),
StringToColor (CStringToMPString (g_vemani.splash_screen_backgroundcolor (g_idInVe))),
this
);
System::Windows::Forms::Application::DoEvents ();
Init ();
ITaskbarList3 *ptr = nullptr;
HRESULT hr = CoCreateInstance (CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&ptr);
if (SUCCEEDED (hr))
{
taskbar = ptr;
taskbar->HrInit ();
}
else
{
taskbar = nullptr;
if (ptr) ptr->Release ();
}
}
Object ^CallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try { return this->webui->Document->InvokeScript (lpFuncName, alpParams); }
catch (Exception ^e)
{
try
{
this->webui->Document->InvokeScript ("messageBoxAsync", gcnew array <Object ^> {
e->Message,
e->Source,
0,
CStringToMPString (g_vemani.background_color (g_idInVe))
});
}
catch (Exception ^ex)
{
MessageBoxW (InvokeGetHWND (), MPStringToStdW (e->Message).c_str (), MPStringToStdW (e->Source).c_str (), 0);
}
}
return nullptr;
}
Object ^CallScriptFunction (String ^lpScriptName)
{
try { return this->webui->Document->InvokeScript (lpScriptName); }
catch (Exception ^ex) { System::Windows::Forms::MessageBox::Show ("Error calling JavaScript function: " + ex->Message); }
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, array <Object ^> ^, Object ^> (this, &MainHtmlWnd::CallScriptFunction), lpFuncName, alpParams);
else return CallScriptFunction (lpFuncName, alpParams);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpScriptName)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, Object ^> (this, &MainHtmlWnd::CallScriptFunction), lpScriptName);
else return CallScriptFunction (lpScriptName);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^ExecScript (... array <Object ^> ^alpScript) { return InvokeCallScriptFunction ("eval", alpScript); }
Object ^CallEvent (String ^funcName, Object ^e) override
{
std::wstring fname = MPStringToStdW (funcName);
if (fname == L"InvokeBackPage") InvokeBackPage ();
return nullptr;
}
property int PageScale
{
int get ()
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return 0;
VARIANT v;
VariantInit (&v);
hr = web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DODEFAULT, nullptr, &v);
if (FAILED (hr) || v.vt != VT_I4) return 0;
int val = v.lVal;
VariantClear (&v);
return val;
}
void set (int value)
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return;
VARIANT v;
VariantInit (&v);
v.vt = VT_I4;
v.lVal = value;
web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &v, nullptr);
}
}
~MainHtmlWnd ()
{
if (taskbar) taskbar->Release ();
taskbar = nullptr;
}
};
using MainWnd = MainHtmlWnd;
HRESULT SetCurrentAppUserModelID (PCWSTR appID)
{
typedef HRESULT (WINAPI *SetAppUserModelIDFunc)(PCWSTR);
HMODULE shell32 = LoadLibraryW (L"shell32.dll");
destruct freelib ([&] () {
if (shell32) FreeLibrary (shell32);
});
try
{
if (!shell32) return E_FAIL;
auto SetAppUserModelID = (SetAppUserModelIDFunc)GetProcAddress (shell32, "SetCurrentProcessExplicitAppUserModelID");
if (!SetAppUserModelID)
{
FreeLibrary (shell32);
return E_FAIL;
}
return SetAppUserModelID (appID);
}
catch (...) { return E_FAIL; }
return E_FAIL;
}
[STAThread]
int APIENTRY wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
SetCurrentProcessExplicitAppUserModelID (g_lpAppId);
SetProcessDPIAware ();
{
// 设置当前目录为程序所在目录
std::wnstring currdir = GetCurrentDirectoryW ();
std::wnstring rootdir = GetProgramRootDirectoryW ();
if (!PathEquals (currdir, rootdir)) SetCurrentDirectoryW (rootdir.c_str ());
}
CoInitializeEx (NULL, COINIT_MULTITHREADED | COINIT_APARTMENTTHREADED);
SetupInstanceEnvironment ();
destruct relco ([] () {
CoUninitialize ();
});
SetWebBrowserEmulation ();
System::Windows::Forms::Application::EnableVisualStyles ();
System::Windows::Forms::Application::SetCompatibleTextRenderingDefault (false);
auto mwnd = gcnew MainHtmlWnd ();
g_mainwnd = mwnd;
System::Windows::Forms::Application::Run (mwnd);
return 0;
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include <Windows.h>
#ifdef __cplusplus
#ifndef GetCurrentModule_bRefDefault
// 在 C++ 中,GetCurrentModule 将会启用默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
// 用法如:HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
#define GetCurrentModule_bRefDefault = FALSE
#endif
#else
#define GetCurrentModule_bRefDefault
#endif
HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
{
HMODULE hModule = NULL;
if (GetModuleHandleExW (bRef ? GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), (LPCWSTR)GetCurrentModule, &hModule))
{
return hModule;
}
return NULL;
}
HMODULE GetSelfModuleHandle ()
{
MEMORY_BASIC_INFORMATION mbi;
return ((::VirtualQuery (GetSelfModuleHandle, &mbi, sizeof (mbi)) != 0)
? (HMODULE)mbi.AllocationBase : NULL);
}
#ifndef GetModuleHandleW_lpModuleNameDefault
#define GetModuleHandleW_lpModuleNameDefault NULL
#endif
#ifndef DEFAULT_HMODULE
#ifdef HMODULE_MODE_EXE
#define DEFAULT_HMODULE GetModuleHandleW (NULL)
#elif defined (HMODULE_MODE_DLL1)
#define DEFAULT_HMODULE GetCurrentModule ()
#elif defined (HMODULE_MODE_DLL2)
#define DEFAULT_HMODULE GetSelfModuleHandle ()
#else
#define DEFAULT_HMODULE GetModuleHandleW (GetModuleHandleW_lpModuleNameDefault)
#endif
#endif
#undef GetModuleHandleW_lpModuleNameDefault
#ifdef __cplusplus
#ifndef hModule_DefaultParam
// 在 C++ 中,你可以使用此宏“hModule_DefaultParam”来用于给一些函数的形参定义默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
// 用法如:std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)。
#define hModule_DefaultParam = DEFAULT_HMODULE
#endif
#else
#define hModule_DefaultParam
#endif
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include <windef.h>
#include <string>
#include <vcclr.h>
using namespace System;
using namespace System::Text;
String ^CStringToMPString (LPCSTR lpstr) { return (lpstr ? gcnew String (lpstr) : String::Empty); }
String ^CStringToMPString (LPCWSTR lpstr) { return (lpstr ? gcnew String (lpstr) : String::Empty); }
String ^CStringToMPString (const std::string &objstr) { return CStringToMPString (objstr.c_str ()); }
String ^CStringToMPString (const std::wstring &objstr) { return CStringToMPString (objstr.c_str ()); }
// 转换为 UTF-16,指针不需要释放(本质是指针转换)
LPCWSTR MPStringToPtrW (String ^in)
{
if (in == nullptr) return NULL;
pin_ptr <const wchar_t> wch = PtrToStringChars (in);
return wch;
}
// 转换为 std::wstringUTF-16
std::wstring MPStringToStdW (String^ in)
{
if (in == nullptr) return std::wstring ();
pin_ptr <const wchar_t> wch = PtrToStringChars (in);
return std::wstring (wch, in->Length);
}
// 转换为 ANSI 编码的 std::string
std::string MPStringToStdA (String^ in)
{
if (in == nullptr) return std::string ();
array <unsigned char> ^bytes = Encoding::Default->GetBytes (in);
pin_ptr <unsigned char> pinned = &bytes [0];
return std::string (reinterpret_cast <const char *> (pinned), bytes->Length);
}
// 转换为 UTF-8 编码的 std::string
std::string MPStringToStdU8 (String^ in)
{
if (in == nullptr) return std::string ();
array <unsigned char> ^bytes = Encoding::UTF8->GetBytes (in);
pin_ptr <unsigned char> pinned = &bytes [0];
return std::string (reinterpret_cast <const char*> (pinned), bytes->Length);
}
+465
View File
@@ -0,0 +1,465 @@
#pragma once
#include <string>
#include <locale>
#include <cctype>
namespace l0km
{
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> inline std::basic_string<E, TR, AL> toupper (const std::basic_string <E, TR, AL> &src)
{
std::basic_string <E, TR, AL> dst = src;
static const std::locale loc;
const std::ctype <E> &ctype = std::use_facet <std::ctype <E>> (loc);
for (typename std::basic_string <E, TR, AL>::size_type i = 0; i < src.size (); ++ i)
{
dst [i] = ctype.toupper (src [i]);
}
return dst;
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> inline std::basic_string <E, TR, AL> tolower (const std::basic_string <E, TR, AL> &src)
{
std::basic_string <E, TR, AL> dst = src;
static const std::locale loc;
const std::ctype <E> &ctype = std::use_facet <std::ctype <E>> (loc);
for (typename std::basic_string <E, TR, AL>::size_type i = 0; i < src.size (); ++ i)
{
dst [i] = ctype.tolower (src [i]);
}
return dst;
}
inline char toupper (char ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <char>> (loc).toupper (ch);
}
inline char tolower (char ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <char>> (loc).tolower (ch);
}
inline wchar_t toupper (wchar_t ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <wchar_t>> (loc).toupper (ch);
}
inline wchar_t tolower (wchar_t ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <wchar_t>> (loc).tolower (ch);
}
inline int toupper (int ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <int>> (loc).toupper (ch);
}
inline int tolower (int ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <int>> (loc).tolower (ch);
}
}
template <typename ct> bool is_blank (ct &ch)
{
return ch == ct (' ') || ch == ct ('\t') || ch == ct ('\n');
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> std::basic_string <E, TR, AL> NormalizeString (const std::basic_string <E, TR, AL> &str, bool upper = false, bool includemidblank = false)
{
typedef std::basic_string <E, TR, AL> string_type;
string_type result;
if (str.empty ()) return result;
auto begin_it = str.begin ();
auto end_it = str.end ();
while (begin_it != end_it && is_blank (*begin_it)) ++begin_it;
while (end_it != begin_it && is_blank (*(end_it - 1))) --end_it;
bool in_space = false;
for (auto it = begin_it; it != end_it; ++ it)
{
if (is_blank (*it))
{
if (includemidblank)
{
if (!in_space)
{
result.push_back (E (' '));
in_space = true;
}
}
else
{
result.push_back (*it);
in_space = true;
}
}
else
{
result.push_back (*it);
in_space = false;
}
}
if (upper) return l0km::toupper (result);
else return l0km::tolower (result);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> bool IsNormalizeStringEquals (const std::basic_string <E, TR, AL> &l, const std::basic_string <E, TR, AL> &r, bool includemidblank = false)
{
auto _local_strlen = [] (const E *p) -> size_t {
size_t cnt = 0;
while (*(p + cnt)) { cnt ++; }
return cnt;
};
const E *pl = l.c_str ();
const E *pr = r.c_str ();
while (*pl && is_blank (*pl)) ++ pl;
while (*pr && is_blank (*pr)) ++ pr;
const E *el = l.c_str () + _local_strlen (l.c_str ());
const E *er = r.c_str () + _local_strlen (r.c_str ());
while (el > pl && is_blank (*(el - 1))) --el;
while (er > pr && is_blank (*(er - 1))) --er;
while (pl < el && pr < er)
{
if (includemidblank)
{
if (is_blank (*pl) && is_blank (*pr))
{
while (pl < el && is_blank (*pl)) ++pl;
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
else if (is_blank (*pl))
{
while (pl < el && is_blank (*pl)) ++pl;
continue;
}
else if (is_blank (*pr))
{
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
}
if (l0km::tolower (*pl) != l0km::tolower (*pr)) return false;
++ pl;
++ pr;
}
while (pl < el && is_blank (*pl)) ++ pl;
while (pr < er && is_blank (*pr)) ++ pr;
return pl == el && pr == er;
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> int64_t NormalizeStringCompare (const std::basic_string <E, TR, AL> &l, const std::basic_string <E, TR, AL> &r, bool includemidblank = false)
{
auto _local_strlen = [] (const E *p) -> size_t {
size_t cnt = 0;
while (*(p + cnt)) { cnt ++; }
return cnt;
};
const E *pl = l.c_str ();
const E *pr = r.c_str ();
while (*pl && is_blank (*pl)) ++ pl;
while (*pr && is_blank (*pr)) ++ pr;
const E *el = l.c_str () + _local_strlen (l.c_str ());
const E *er = r.c_str () + _local_strlen (r.c_str ());
while (el > pl && is_blank (*(el - 1))) -- el;
while (er > pr && is_blank (*(er - 1))) -- er;
while (pl < el && pr < er)
{
if (includemidblank)
{
if (is_blank (*pl) && is_blank (*pr))
{
while (pl < el && is_blank (*pl)) ++pl;
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
else if (is_blank (*pl))
{
while (pl < el && is_blank (*pl)) ++pl;
continue;
}
else if (is_blank (*pr))
{
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
}
E chl = l0km::tolower (*pl);
E chr = l0km::tolower (*pr);
if (chl != chr) return (int64_t)chl - (int64_t)chr;
++ pl;
++ pr;
}
while (pl < el && is_blank (*pl)) ++ pl;
while (pr < er && is_blank (*pr)) ++ pr;
if (pl == el && pr == er) return 0;
if (pl == el) return -1;
if (pr == er) return 1;
return (int64_t)l0km::tolower (*pl) - (int64_t)l0km::tolower (*pr);
}
template <typename CharT> bool IsNormalizeStringEquals (const CharT *l, const CharT *r, bool includemidblank = false)
{
if (!l || !r) return l == r;
auto skip_blank = [] (const CharT *&p)
{
while (*p && is_blank (*p)) ++ p;
};
const CharT *p1 = l;
const CharT *p2 = r;
skip_blank (p1);
skip_blank (p2);
while (*p1 && *p2)
{
CharT ch1 = l0km::tolower (*p1);
CharT ch2 = l0km::tolower (*p2);
if (ch1 != ch2) return false;
++ p1;
++ p2;
if (includemidblank)
{
if (is_blank (*p1) || is_blank (*p2))
{
skip_blank (p1);
skip_blank (p2);
}
}
}
skip_blank (p1);
skip_blank (p2);
return *p1 == 0 && *p2 == 0;
}
template <typename CharT> int64_t NormalizeStringCompare (const CharT *l, const CharT *r, bool includemidblank = false)
{
if (!l || !r) return l ? 1 : (r ? -1 : 0);
auto skip_blank = [] (const CharT *&p)
{
while (*p && is_blank (*p)) ++ p;
};
const CharT *p1 = l;
const CharT *p2 = r;
skip_blank (p1);
skip_blank (p2);
while (*p1 && *p2)
{
CharT ch1 = l0km::tolower (*p1);
CharT ch2 = l0km::tolower (*p2);
if (ch1 != ch2) return (ch1 < ch2) ? -1 : 1;
++ p1;
++ p2;
if (includemidblank)
{
if (is_blank (*p1) || is_blank (*p2))
{
skip_blank (p1);
skip_blank (p2);
}
}
}
skip_blank (p1);
skip_blank (p2);
if (*p1 == 0 && *p2 == 0) return 0;
if (*p1 == 0) return -1;
return 1;
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> bool IsNormalizeStringEmpty (const std::basic_string <E, TR, AL> &str)
{
return IsNormalizeStringEquals (str, std::basic_string <E, TR, AL> ());
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> std::basic_string <E, TR, AL> StringTrim (const std::basic_string <E, TR, AL> &str, bool includemidblank = false)
{
typedef std::basic_string <E, TR, AL> string_type;
typedef typename string_type::size_type size_type;
if (str.empty ()) return string_type ();
size_type first = 0;
size_type last = str.size ();
while (first < last && is_blank (str [first])) ++first;
while (last > first && is_blank (str [last - 1])) --last;
if (first == last) return string_type ();
string_type result;
result.reserve (last - first);
bool in_space = false;
for (size_type i = first; i < last; ++ i)
{
if (is_blank (str [i]))
{
if (includemidblank)
{
if (!in_space)
{
result.push_back (E (' '));
in_space = true;
}
}
else
{
result.push_back (str [i]);
in_space = true;
}
}
else
{
result.push_back (str [i]);
in_space = false;
}
}
return result;
}
template <typename E, typename TR = std::char_traits<E>, typename AL = std::allocator <E>> size_t GetNormalizeStringLength (const std::basic_string <E, TR, AL> &str, bool includemidblank = false)
{
typedef typename std::basic_string <E, TR, AL>::size_type size_type;
if (str.empty ()) return 0;
size_type first = 0, last = str.size ();
while (first < last && is_blank (str [first])) ++first;
while (last > first && is_blank (str [last - 1])) --last;
if (first == last) return 0;
size_t length = 0;
bool in_space = false;
for (size_type i = first; i < last; ++i)
{
if (is_blank (str [i]))
{
if (includemidblank)
{
if (!in_space)
{
++ length;
in_space = true;
}
}
else
{
++ length;
in_space = true;
}
}
else
{
++ length;
in_space = false;
}
}
return length;
}
namespace std
{
template <typename ct, typename tr = std::char_traits <ct>, typename al = std::allocator <ct>> class basic_nstring: public std::basic_string <ct, tr, al>
{
bool default_upper = false, default_include_blank_in_str = false;
public:
using base = std::basic_string <ct, tr, al>;
using derive = std::basic_nstring <ct, tr, al>;
using typename base::size_type;
using typename base::value_type;
using base::base;
using pstr = ct *;
using pcstr = const ct *;
basic_nstring (): base (), default_upper (false), default_include_blank_in_str (false) {}
basic_nstring (const ct *pStr): base (pStr), default_upper (false), default_include_blank_in_str (false) {}
basic_nstring (const base &str): base (str) {}
basic_nstring (base &&str): base (std::move (str)) {}
basic_nstring (const ct *data, size_type count): base (data, count), default_upper (false), default_include_blank_in_str (false) {}
// template <std::size_t N> basic_nstring (const ct (&arr) [N]) : base (arr, N - 1) {}
template <typename InputIt> basic_nstring (InputIt first, InputIt last): base (first, last), default_upper (false), default_include_blank_in_str (false) {}
bool upper_default () const { return this->default_upper; }
bool upper_default (bool value) { return this->default_upper = value; }
bool include_blank_in_str_middle () const { return this->default_include_blank_in_str; }
bool include_blank_in_str_middle (bool value) { return this->default_include_blank_in_str = value; }
base normalize (bool upper, bool includemidblank) const
{
return NormalizeString <ct, tr, al> (*this, upper, includemidblank);
}
base normalize (bool upper) const
{
return this->normalize (upper, default_include_blank_in_str);
}
base normalize () const { return this->normalize (default_upper); }
base upper (bool includemidblank) const
{
return NormalizeString <ct, tr, al> (*this, true, includemidblank);
}
base upper () const { return this->upper (default_include_blank_in_str); }
base lower (bool includemidblank) const
{
return NormalizeString <ct, tr, al> (*this, false, includemidblank);
}
base lower () const { return this->lower (default_include_blank_in_str); }
base trim (bool includemidblank) const
{
return StringTrim <ct, tr, al> (*this, includemidblank);
}
base trim () const { return this->trim (default_include_blank_in_str); }
size_t length (bool includemidblank) const { return GetNormalizeStringLength (*this, includemidblank); }
size_t length () const { return length (default_include_blank_in_str); }
bool empty () const
{
return IsNormalizeStringEmpty (*this);
}
bool equals (const base &another, bool includemidblank) const
{
return IsNormalizeStringEquals <ct, tr, al> (*this, another, includemidblank);
}
bool equals (const base &another) const { return equals (another, default_include_blank_in_str); }
int64_t compare (const base &another, bool includemidblank) const
{
return NormalizeStringCompare <ct, tr, al> (*this, another, includemidblank);
}
int64_t compare (const base &another) const { return compare (another, default_include_blank_in_str); }
base &string () { return *this; }
base to_string (bool upper, bool includemidblank) const { return this->normalize (upper, includemidblank); }
base to_string (bool upper) const { return this->normalize (upper, default_include_blank_in_str); }
base to_string () const { return this->normalize (default_upper); }
bool operator == (const base &other) const { return equals (other, false); }
bool operator != (const base &other) const { return !equals (other, false); }
bool operator < (const base &other) const { return compare (other, false) < 0; }
bool operator > (const base &other) const { return compare (other, false) > 0; }
bool operator <= (const base &other) const { return compare (other, false) <= 0; }
bool operator >= (const base &other) const { return compare (other, false) >= 0; }
int64_t operator - (const base &other) const { return compare (other, false); }
bool operator == (pcstr &other) const { return equals (other, false); }
bool operator != (pcstr &other) const { return !equals (other, false); }
bool operator < (pcstr &other) const { return compare (other, false) < 0; }
bool operator > (pcstr &other) const { return compare (other, false) > 0; }
bool operator <= (pcstr &other) const { return compare (other, false) <= 0; }
bool operator >= (pcstr &other) const { return compare (other, false) >= 0; }
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static bool equals (const std::basic_string <E> &l, const std::basic_string <E> &r, bool remove_mid_blank = false)
{
return IsNormalizeStringEquals <E, TR, AL> (l, r, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static int64_t compare (const std::basic_string <E> &l, const std::basic_string <E> &r, bool remove_mid_blank = false)
{
return NormalizeStringCompare <E, TR, AL> (l, r, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_string <E, TR, AL> normalize (const std::basic_string <E> &str, bool to_upper = false, bool remove_mid_blank = false)
{
return NormalizeString <E, TR, AL> (str, to_upper, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_string <E, TR, AL> trim (const std::basic_string <E> &str, bool remove_mid_blank = false)
{
return StringTrim <E, TR, AL> (str, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static size_t length (const std::basic_string <E> &str, bool remove_mid_blank = false)
{
return GetNormalizeStringLength <E, TR, AL> (str, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static bool empty (const std::basic_string <E> &str)
{
return IsNormalizeStringEmpty <E, TR, AL> (str);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_nstring <E, TR, AL> to_nstring (std::basic_string <E> &str) { return std::basic_nstring <E> (str); }
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_nstring <E, TR, AL> toupper (const std::basic_nstring <E, TR, AL> &str) { return l0km::toupper (str); }
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_nstring <E, TR, AL> tolower (const std::basic_nstring <E, TR, AL> &str) { return l0km::tolower (str); }
};
typedef basic_nstring <char> nstring;
typedef basic_nstring <wchar_t> wnstring;
}
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="pugixml" version="1.15.0" targetFramework="native" />
<package id="rapidjson" version="1.0.2" targetFramework="native" />
</packages>
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <functional>
typedef struct raii
{
std::function <void ()> endtask = nullptr;
raii (std::function <void ()> pFunc = nullptr): endtask (pFunc) {}
~raii () { if (endtask) endtask (); }
raii (const raii &) = delete;
raii (raii &&) = delete;
} destruct;
+121
View File
@@ -0,0 +1,121 @@
#pragma once
#include <Windows.h>
#include <WinBase.h>
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "typestrans.h"
#include "module.h"
// 返回的指针如果非空则一定需要用 free 释放
LPWSTR GetRCStringW (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringW:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return _wcsdup (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringW;
}
else return _wcsdup (buf.data ());
}
}
// 返回的指针如果非空则一定需要用 free 释放
LPSTR GetRCStringA (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringA:
{
size_t len = LoadStringA (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return _strdup (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringA;
}
else return _strdup (buf.data ());
}
}
HICON LoadRCIcon (UINT resID, HMODULE hModule hModule_DefaultParam)
{
return (HICON)LoadImageW (hModule, MAKEINTRESOURCEW (resID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
}
HRSRC FindResourceByName (LPCWSTR resourceName, LPCWSTR resourceType, HMODULE hModule hModule_DefaultParam)
{
return FindResourceW (hModule, resourceName, resourceType);
}
#ifdef __cplusplus
#include <string>
std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringSW:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return buf.data ();
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringSW;
}
else return buf.data ();
}
}
std::string GetRCStringSA (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringSA:
{
size_t len = LoadStringA (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return buf.data ();
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringSA;
}
else return buf.data ();
}
}
#endif
#if defined (__cplusplus) && defined (__cplusplus_cli)
using namespace System;
String ^GetRCStringCli (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringCli:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return gcnew String (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringCli;
}
else return gcnew String (buf.data ());
}
}
#define GetRCIntValue(_UINT__resID_) toInt (GetRCStringCli (_UINT__resID_))
#define GetRCDoubleValue(_UINT__resID_) toDouble (GetRCStringCli (_UINT__resID_))
#define GetRCBoolValue(_UINT__resID_) toBool (GetRCStringCli (_UINT__resID_))
#define GetRCDateTimeValue(_UINT__resID_) toDateTime (GetRCStringCli (_UINT__resID_))
#define rcString(resID) GetRCStringCli (resID)
#define rcInt(resID) GetRCIntValue (resID)
#define rcDouble(resID) GetRCDoubleValue (resID)
#define rcBool(resID) GetRCBoolValue (resID)
#define rcDTime(resID) GetRCDateTimeValue (resID)
#define rcIcon(resID) LoadRCIcon (resID)
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <map>
#include <string>
#include "rctools.h"
#include "resource.h"
#define MAKENAMEIDMAP(_Res_Name_) {#_Res_Name_, _Res_Name_}
std::map <std::string, unsigned> g_nameToId = {
MAKENAMEIDMAP (IDS_WINTITLE),
MAKENAMEIDMAP (IDS_DEFAULTWIDTH),
MAKENAMEIDMAP (IDS_DEFAULTHEIGHT),
MAKENAMEIDMAP (IDS_MINWIDTH),
MAKENAMEIDMAP (IDS_MINHIEHGT)
};
#ifdef MAKENAMEIDMAP
#undef MAKENAMEIDMAP
#endif
#ifdef __cplusplus_cli
using namespace System;
using namespace System::Runtime::InteropServices;
[ComVisible (true)]
public ref class _I_Resources
{
public:
String ^GetById (unsigned int uiResId) { return GetRCStringCli (uiResId); }
unsigned ToId (String ^lpResName)
{
auto it = g_nameToId.find (MPStringToStdA (lpResName));
return (it != g_nameToId.end ()) ? it->second : 0;
}
String ^ToName (unsigned int ulResId)
{
for (auto &it : g_nameToId) { if (it.second == ulResId) return CStringToMPString (it.first); }
return "";
}
String ^GetByName (String ^lpResId) { return GetById (ToId (lpResId)); }
String ^operator [] (unsigned int uiResId) { return GetRCStringCli (uiResId); }
String ^GetFromOthers (String ^filepath, unsigned int resid)
{
HMODULE module = nullptr;
if (filepath && !IsNormalizeStringEmpty (MPStringToStdW (filepath))) module = GetModuleHandleW (MPStringToStdW (filepath).c_str ());
else module = GetModuleHandleW (NULL);
return GetRCStringCli (resid, module);
}
};
#endif
Binary file not shown.
Binary file not shown.
+213
View File
@@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>settings</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;HMODULE_MODE_EXE;_CRT_SECURE_NO_WARNINGS;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;HMODULE_MODE_EXE;_CRT_SECURE_NO_WARNINGS;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<Reference Include="System">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll</HintPath>
</Reference>
<Reference Include="System.Drawing">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\appinstaller\bridge.h" />
<ClInclude Include="..\appinstaller\dynarr.h" />
<ClInclude Include="..\appinstaller\filepath.h" />
<ClInclude Include="..\appinstaller\ieshell.h" />
<ClInclude Include="..\appinstaller\initfile.h" />
<ClInclude Include="..\appinstaller\localeex.h" />
<ClInclude Include="..\appinstaller\module.h" />
<ClInclude Include="..\appinstaller\mpstr.h" />
<ClInclude Include="..\appinstaller\nstring.h" />
<ClInclude Include="..\appinstaller\raii.h" />
<ClInclude Include="..\appinstaller\rctools.h" />
<ClInclude Include="..\appinstaller\strcmp.h" />
<ClInclude Include="..\appinstaller\strcode.h" />
<ClInclude Include="..\appinstaller\themeinfo.h" />
<ClInclude Include="..\appinstaller\typestrans.h" />
<ClInclude Include="..\appinstaller\vemani.h" />
<ClInclude Include="..\appinstaller\version.h" />
<ClInclude Include="resmap.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="settings.rc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Image Include="res\icons\color.ico" />
<Image Include="res\icons\main.ico" />
<Image Include="res\icons\white.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\rapidjson.1.0.2\build\native\rapidjson.targets" Condition="Exists('..\packages\rapidjson.1.0.2\build\native\rapidjson.targets')" />
<Import Project="..\packages\pugixml.1.15.0\build\native\pugixml.targets" Condition="Exists('..\packages\pugixml.1.15.0\build\native\pugixml.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\rapidjson.1.0.2\build\native\rapidjson.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\rapidjson.1.0.2\build\native\rapidjson.targets'))" />
<Error Condition="!Exists('..\packages\pugixml.1.15.0\build\native\pugixml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\pugixml.1.15.0\build\native\pugixml.targets'))" />
</Target>
</Project>
+100
View File
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\appinstaller\bridge.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\dynarr.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\filepath.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\ieshell.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\initfile.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\localeex.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\module.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\mpstr.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\nstring.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\raii.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\rctools.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\strcmp.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\strcode.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\themeinfo.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\typestrans.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\vemani.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\appinstaller\version.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="resmap.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="settings.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Image Include="res\icons\main.ico">
<Filter>资源文件</Filter>
</Image>
<Image Include="res\icons\white.ico">
<Filter>资源文件</Filter>
</Image>
<Image Include="res\icons\color.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>
+154
View File
@@ -0,0 +1,154 @@
#pragma once
#include <Shlwapi.h>
#include "nstring.h"
#ifdef __cplusplus
#define ptrnull(ptr) (!(ptr))
#else
#define ptrnull(ptr) ((ptr) == NULL)
#endif
#define ptrvalid(ptr) (!ptrnull (ptr))
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为非空字符串:指针有效且长度大于 0。千万不能是野指针,否则一定会崩溃!
#define strvalid(strptr) (ptrvalid (strptr) && *(strptr))
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为空字符串:指针为 NULL 或长度为 0。千万不能是野指针,否则一定会崩溃!
#define strnull(strptr) (ptrnull (strptr) || !*(strptr))
typedef std::wnstring strlabel, StringLabel;
std::wstring StringTrim (const std::wstring &str) { return std::wnstring::trim (str); }
std::string StringTrim (const std::string &str) { return std::nstring::trim (str); }
#define StringToUpper l0km::toupper
#define StringToLower l0km::tolower
int LabelCompare (const std::wstring &l1, const std::wstring &l2)
{
return std::wnstring::compare (l1, l2);
}
int LabelCompare (const std::string &l1, const std::string &l2)
{
return std::nstring::compare (l1, l2);
}
bool LabelEqual (const std::wstring &l1, const std::wstring &l2)
{
return std::wnstring::equals (l1, l2);
}
bool LabelEqual (const std::string &l1, const std::string &l2)
{
return std::wnstring::equals (l1, l2);
}
bool LabelEmpty (const std::wstring &str) { return std::wnstring::empty (str); }
bool LabelEmpty (const std::string &str) { return std::nstring::empty (str); }
#define LabelNoEmpty(_str_) (!LabelEmpty (_str_))
int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false)
{
std::string s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
if (!found)
{
return -1;
}
return found - text.c_str ();
}
int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
{
std::wstring s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
if (!found)
{
return -1;
}
return found - text.c_str ();
}
bool StrInclude (const std::string &text, const std::string &keyword, bool ignoreCase = false)
{
std::string s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
if (!found) return false;
return true;
}
bool StrInclude (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
{
std::wstring s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
if (!found) return false;
return true;
}
// 该函数帮助构成 "<str1>\0<str2>\0" 这种字符串,用于通用对话框中的文件框
LPCWSTR strcpynull (LPWSTR dest, LPCWSTR endwith, size_t bufsize)
{
if (!dest || !endwith || bufsize == 0)
return dest;
if (dest [0] == L'\0' && bufsize > 1)
{
dest [1] = L'\0';
}
size_t pos = 0;
while (pos < bufsize - 1)
{
if (dest [pos] == L'\0' && dest [pos + 1] == L'\0')
{
if (dest [0]) pos ++;
break;
}
pos ++;
}
size_t i = 0;
while (pos < bufsize - 1 && endwith [i] != L'\0')
{
dest [pos ++] = endwith [i ++];
}
if (pos < bufsize)
{
dest [pos] = L'\0';
}
return dest;
}
// 取文本左边,注意:长度指的是文本字符数,比如“ch”的长度为2
std::wstring GetStringLeft (const std::wstring &str, size_t length)
{
std::vector <WCHAR> buf (length + 1);
lstrcpynW (buf.data (), str.c_str (), length + 1);
return buf.data ();
}
// 取文本右边
std::wstring GetStringRight (const std::wstring &str, size_t length)
{
if (length >= str.length ()) return str;
return str.substr (str.length () - length, length).c_str ();
}
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <string>
#include <Windows.h>
#include <locale>
#include <codecvt>
std::wstring StringToWString (const std::string &str, UINT codePage = CP_ACP)
{
if (str.empty ()) return std::wstring ();
int len = MultiByteToWideChar (codePage, 0, str.c_str (), -1, nullptr, 0);
if (len == 0) return std::wstring ();
std::wstring wstr (len - 1, L'\0');
MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len);
return wstr;
}
std::string WStringToString (const std::wstring &wstr, UINT codePage = CP_ACP)
{
if (wstr.empty ()) return std::string ();
int len = WideCharToMultiByte (codePage, 0, wstr.c_str (), -1, nullptr, 0, nullptr, nullptr);
if (len == 0) return std::string ();
std::string str (len - 1, '\0');
WideCharToMultiByte (codePage, 0, wstr.c_str (), -1, &str [0], len, nullptr, nullptr);
return str;
}
std::string WStringToUtf8 (const std::wstring& ws)
{
static std::wstring_convert <std::codecvt_utf8_utf16 <wchar_t>> conv;
return conv.to_bytes (ws);
}
std::wstring Utf8ToWString (const std::string& s)
{
static std::wstring_convert <std::codecvt_utf8_utf16 <wchar_t>> conv;
return conv.from_bytes (s);
}
+159
View File
@@ -0,0 +1,159 @@
#pragma once
#include <Windows.h>
#include <dwmapi.h>
using namespace System;
bool IsHighContrastEnabled ()
{
HIGHCONTRAST hc = {sizeof (HIGHCONTRAST)};
if (SystemParametersInfo (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0)) return (hc.dwFlags & HCF_HIGHCONTRASTON) != 0;
return false;
}
enum class HighContrastTheme
{
None,
Black,
White,
Other
};
HighContrastTheme GetHighContrastTheme ()
{
HIGHCONTRAST hc = {sizeof (HIGHCONTRAST)};
if (!SystemParametersInfo (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0)) return HighContrastTheme::None;
if (!(hc.dwFlags & HCF_HIGHCONTRASTON)) return HighContrastTheme::None;
COLORREF bgColor = GetSysColor (COLOR_WINDOW);
COLORREF textColor = GetSysColor (COLOR_WINDOWTEXT);
int brightnessBg = (GetRValue (bgColor) + GetGValue (bgColor) + GetBValue (bgColor)) / 3;
int brightnessText = (GetRValue (textColor) + GetGValue (textColor) + GetBValue (textColor)) / 3;
if (brightnessBg < brightnessText) return HighContrastTheme::Black;
else if (brightnessBg > brightnessText) return HighContrastTheme::White;
else return HighContrastTheme::Other;
}
int GetDPI ()
{
HDC hDC = GetDC (NULL);
int DPI_A = (int)(((double)GetDeviceCaps (hDC, 118) / (double)GetDeviceCaps (hDC, 8)) * 100);
int DPI_B = (int)(((double)GetDeviceCaps (hDC, 88) / 96) * 100);
ReleaseDC (NULL, hDC);
if (DPI_A == 100) return DPI_B;
else if (DPI_B == 100) return DPI_A;
else if (DPI_A == DPI_B) return DPI_A;
else return 0;
}
int GetScreenWidth () { return GetSystemMetrics (SM_CXSCREEN); }
int GetScreenHeight () { return GetSystemMetrics (SM_CYSCREEN); }
System::Drawing::Color GetDwmThemeColor ()
{
DWORD color = 0;
BOOL opaqueBlend = FALSE;
// 调用 DwmGetColorizationColor 获取 Aero 颜色
HRESULT hr = DwmGetColorizationColor (&color, &opaqueBlend);
if (SUCCEEDED (hr))
{
BYTE r = (BYTE)((color & 0x00FF0000) >> 16);
BYTE g = (BYTE)((color & 0x0000FF00) >> 8);
BYTE b = (BYTE)(color & 0x000000FF);
return System::Drawing::Color::FromArgb (r, g, b);
}
else return System::Drawing::Color::FromArgb (0, 120, 215); // 如果获取失败,返回默认颜色
}
String ^ColorToHtml (System::Drawing::Color color)
{
return String::Format ("#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
}
System::Drawing::Color StringToColor (String ^colorStr)
{
using Color = System::Drawing::Color;
using Regex = System::Text::RegularExpressions::Regex;
auto Clamp = [] (int value, int min, int max)
{
return (value < min) ? min : (value > max) ? max : value;
};
String ^normalized = colorStr->Trim ()->ToLower ();
if (normalized == "transparent") return Color::Transparent;
if (Color::FromName (normalized).IsKnownColor)
{
return Color::FromName (normalized);
}
if (normalized->StartsWith ("#"))
{
String^ hex = normalized->Substring (1);
if (hex->Length == 3 || hex->Length == 4)
{
hex = String::Concat (
hex [0].ToString () + hex [0],
hex [1].ToString () + hex [1],
hex [2].ToString () + hex [2],
(hex->Length == 4) ? (hex [3].ToString () + hex [3]) : ""
);
}
uint32_t argb = Convert::ToUInt32 (hex, 16);
switch (hex->Length)
{
case 6: return Color::FromArgb (
0xFF,
(argb >> 16) & 0xFF,
(argb >> 8) & 0xFF,
argb & 0xFF
);
case 8: return Color::FromArgb (
(argb >> 24) & 0xFF,
(argb >> 16) & 0xFF,
(argb >> 8) & 0xFF,
argb & 0xFF
);
default: throw gcnew ArgumentException ("Invalid hex color format");
}
}
System::Text::RegularExpressions::Match ^match = Regex::Match (normalized,
"^(rgba?)\\s*\\(\\s*(\\d+%?)\\s*,\\s*(\\d+%?)\\s*,\\s*(\\d+%?)\\s*,?\\s*([\\d.]+%?)?\\s*\\)$");
if (match->Success)
{
auto GetComponent = [&] (String^ val) -> int
{
if (val->EndsWith ("%"))
{
float percent = float::Parse (val->TrimEnd ('%')) / 100.0f;
return Clamp ((int)Math::Round (percent * 255), 0, 255);
}
return Clamp (int::Parse (val), 0, 255);
};
int r = GetComponent (match->Groups [2]->Value);
int g = GetComponent (match->Groups [3]->Value);
int b = GetComponent (match->Groups [4]->Value);
if (match->Groups [1]->Value == "rgba")
{
String^ alphaVal = match->Groups [5]->Value;
int a = 255;
if (alphaVal->EndsWith ("%"))
{
float percent = float::Parse (alphaVal->TrimEnd ('%')) / 100.0f;
a = Clamp ((int)Math::Round (percent * 255), 0, 255);
}
else if (!String::IsNullOrEmpty (alphaVal))
{
a = Clamp ((int)Math::Round (float::Parse (alphaVal) * 255), 0, 255);
}
return Color::FromArgb (a, r, g, b);
}
return Color::FromArgb (r, g, b);
}
//throw gcnew ArgumentException ("Unsupported color format: " + colorStr);
return Color::Transparent;
}
bool IsAppInDarkMode ()
{
HKEY hKey;
DWORD dwValue;
if (RegOpenKeyEx (HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD dwSize = sizeof (dwValue);
if (RegQueryValueEx (hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS)
{
RegCloseKey (hKey);
return dwValue == 0;
}
RegCloseKey (hKey);
}
return false;
}
+267
View File
@@ -0,0 +1,267 @@
#pragma once
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <Windows.h>
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstdbool>
#include <cstring>
#include <cstdint>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <cstdint>
#endif
unsigned _wtou (const wchar_t *str)
{
unsigned value = 0;
if (str)
{
swscanf (str, L"%u", &value);
}
return value;
}
unsigned long _wtoul (const wchar_t *str)
{
unsigned value = 0;
if (str)
{
swscanf (str, L"%lu", &value);
}
return value;
}
unsigned long long _wtou64 (const wchar_t *str)
{
unsigned long long value = 0;
if (str)
{
swscanf (str, L"%llu", &value);
}
return value;
}
double _wtod (const wchar_t *str)
{
if (!str || !*str) return 0.0; // 避免空指针或空字符串
double value = 0.0;
if (swscanf (str, L"%lg", &value) == 1)
{
return value;
}
return 0.0; // 解析失败时返回 0.0
}
unsigned atou (const char *str)
{
unsigned value = 0;
if (str)
{
sscanf (str, "%u", &value);
}
return value;
}
unsigned long atoul (const char *str)
{
unsigned value = 0;
if (str)
{
sscanf (str, "%lu", &value);
}
return value;
}
unsigned long long atou64 (const char *str)
{
unsigned long long value = 0;
if (str)
{
sscanf (str, "%llu", &value);
}
return value;
}
double atod (const char *str)
{
if (!str || !*str) return 0.0; // 避免空指针或空字符串
double value = 0.0;
if (sscanf (str, "%lg", &value) == 1)
{
return value;
}
return 0.0; // 解析失败时返回 0.0
}
int8_t atoi8 (const char *str)
{
int value = 0;
if (str) sscanf (str, "%d", &value);
return (int8_t)value;
}
int16_t atoi16 (const char *str)
{
int value = 0;
if (str) sscanf (str, "%d", &value);
return (int16_t)value;
}
int32_t atoi32 (const char *str)
{
int32_t value = 0;
if (str) sscanf (str, "%d", &value);
return value;
}
uint8_t atoui8 (const char *str)
{
unsigned value = 0;
if (str) sscanf (str, "%u", &value);
return (uint8_t)value;
}
uint16_t atoui16 (const char *str)
{
unsigned value = 0;
if (str) sscanf (str, "%u", &value);
return (uint16_t)value;
}
uint32_t atoui32 (const char *str)
{
uint32_t value = 0;
if (str) sscanf (str, "%u", &value);
return value;
}
int8_t _wtoi8 (const wchar_t *str)
{
int value = 0;
if (str) swscanf (str, L"%d", &value);
return (int8_t)value;
}
int16_t _wtoi16 (const wchar_t *str)
{
int value = 0;
if (str) swscanf (str, L"%d", &value);
return (int16_t)value;
}
int32_t _wtoi32 (const wchar_t *str)
{
int32_t value = 0;
if (str) swscanf (str, L"%d", &value);
return value;
}
uint8_t _wtoui8 (const wchar_t *str)
{
unsigned value = 0;
if (str) swscanf (str, L"%u", &value);
return (uint8_t)value;
}
uint16_t _wtoui16 (const wchar_t *str)
{
unsigned value = 0;
if (str) swscanf (str, L"%u", &value);
return (uint16_t)value;
}
uint32_t _wtoui32 (const wchar_t *str)
{
uint32_t value = 0;
if (str) swscanf (str, L"%u", &value);
return value;
}
int64_t atoi64 (const char *str)
{
int64_t value = 0;
if (str) sscanf (str, "%lld", &value);
return value;
}
EXTERN_C int StringToIntA (const char *str) { return atoi (str); }
EXTERN_C int StringToIntW (const WCHAR *str) { return _wtoi (str); }
EXTERN_C unsigned StringToUnsignedA (const char *str) { return atou (str); }
EXTERN_C unsigned StringToUnsignedW (const WCHAR *str) { return _wtou (str); }
EXTERN_C bool StringToBoolA (const char *str)
{
char buf [32] = {0};
strcpy (buf, str);
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
return !strcmp (buf, "true") ||
!strcmp (buf, "yes") ||
!strcmp (buf, "ok") ||
!strcmp (buf, "sure") ||
!strcmp (buf, "okay") ||
!strcmp (buf, "zhen") ||
!strcmp (buf, "");
}
EXTERN_C bool StringToBoolW (const WCHAR *str)
{
WCHAR buf [32] = {0};
lstrcpyW (buf, str);
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
return !lstrcmpW (buf, L"true") ||
!lstrcmpW (buf, L"yes") ||
!lstrcmpW (buf, L"ok") ||
!lstrcmpW (buf, L"sure") ||
!lstrcmpW (buf, L"okay") ||
!lstrcmpW (buf, L"zhen") ||
!lstrcmpW (buf, L"");
}
EXTERN_C long StringToLongA (const char *str) { return atol (str); }
EXTERN_C long StringToLongW (const WCHAR *str) { return _wtol (str); }
EXTERN_C unsigned long StringToULongA (const char *str) { return atoul (str); }
EXTERN_C unsigned long StringToULongW (const WCHAR *str) { return _wtoul (str); }
EXTERN_C long long StringToLongLongA (const char *str) { return atoll (str); }
EXTERN_C long long StringToLongLongW (const WCHAR *str) { return _wtoll (str); }
EXTERN_C unsigned long long StringToULongLongA (const char *str) { return atou64 (str); }
EXTERN_C unsigned long long StringToULongLongW (const WCHAR *str) { return _wtou64 (str); }
EXTERN_C float StringToFloatA (const char *str) { return atof (str); }
EXTERN_C float StringToFloatW (const WCHAR *str) { return _wtof (str); }
EXTERN_C double StringToDoubleA (const char *str) { return atod (str); }
EXTERN_C double StringToDoubleW (const WCHAR *str) { return _wtod (str); }
#ifdef __cplusplus
int StringToInt (LPCSTR str) { return StringToIntA (str); }
int StringToInt (LPCWSTR str) { return StringToIntW (str); }
unsigned StringToUnsigned (LPCSTR str) { return StringToUnsignedA (str); }
unsigned StringToUnsigned (LPCWSTR str) { return StringToUnsignedW (str); }
bool StringToBool (LPCSTR str) { return StringToBoolA (str); }
bool StringToBool (LPCWSTR str) { return StringToBoolW (str); }
long StringToLong (LPCSTR str) { return StringToLongA (str); }
long StringToLong (LPCWSTR str) { return StringToLongW (str); }
unsigned long StringToULong (LPCSTR str) { return StringToULongA (str); }
unsigned long StringToULong (LPCWSTR str) { return StringToULongW (str); }
long long StringToLongLong (LPCSTR str) { return StringToLongLongA (str); }
long long StringToLongLong (LPCWSTR str) { return StringToLongLongW (str); }
unsigned long long StringToULongLong (LPCSTR str) { return StringToULongLongA (str); }
unsigned long long StringToULongLong (LPCWSTR str) { return StringToULongLongW (str); }
float StringToFloat (LPCSTR str) { return StringToFloatA (str); }
float StringToFloat (LPCWSTR str) { return StringToFloatW (str); }
double StringToDouble (LPCSTR str) { return StringToDoubleA (str); }
double StringToDouble (LPCWSTR str) { return StringToDoubleW (str); }
#endif
#if defined (__cplusplus) && defined (__cplusplus_cli)
using namespace System;
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
#define objToInt(_Object_Managed_) Convert::ToInt32 (_Object_Managed_)
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
#define objToDouble(_Object_Managed_) Convert::ToDouble (_Object_Managed_)
#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_)
bool objToBool (Object ^result)
{
if (!result) return false;
try
{
String ^strValue = safe_cast <String ^> (result);
return (strValue->ToLower () == "on");
}
catch (InvalidCastException ^)
{
try
{
return Convert::ToBoolean (result);
}
catch (InvalidCastException ^)
{
return false;
}
}
return false;
}
#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_)
#define toDateTimeObj(_Object_Managed_) Convert::ToDateTime (_Object_Managed_)
#define objectToType(_Object_Managed_, _Type_Name_) Convert::To##_Type_Name_ (_Object_Managed_)
#endif
+348
View File
@@ -0,0 +1,348 @@
#pragma once
#include <Windows.h>
#include <pugiconfig.hpp>
#include <pugixml.hpp>
#include <string>
#include <fstream>
#include <sstream>
#include <codecvt>
#include <locale>
#include <cstdio>
#include "strcmp.h"
#include "dynarr.h"
#include "themeinfo.h"
#include "nstring.h"
#include "filepath.h"
class vemanifest
{
public:
enum class TextColor { dark = 0x000000, light = 0xFFFFFF };
vemanifest (): available (false) {}
vemanifest (LPCSTR filename): available (false) { create (filename); }
vemanifest (const std::string &filename): available (false) { create (filename); }
vemanifest (LPCWSTR filename): available (false) { create (filename); }
vemanifest (const std::wstring &filename): available (false) { create (filename); }
vemanifest (std::ifstream &stream): available (false) { create (stream); }
vemanifest (std::fstream &stream): available (false) { create (stream); }
vemanifest (FILE *file): available (false) { create (file); }
~vemanifest () { destroy (); }
bool create (LPCSTR filename)
{
destroy ();
pugi::xml_parse_result result = doc.load_file (filename);
available = result; return available;
}
bool create (const std::string &filename) { return create (filename.c_str ()); }
bool create (LPCWSTR filename)
{
destroy ();
std::wstring ws (filename);
std::string s = to_utf8 (ws);
pugi::xml_parse_result result = doc.load_file (s.c_str ());
available = result; return available;
}
bool create (const std::wstring &filename) { return create (filename.c_str ()); }
bool create (std::ifstream &stream)
{
destroy ();
std::stringstream buffer; buffer << stream.rdbuf ();
std::string content = buffer.str ();
pugi::xml_parse_result result = doc.load_string (content.c_str ());
available = result; return available;
}
bool create (std::fstream &stream)
{
destroy ();
std::stringstream buffer; buffer << stream.rdbuf ();
std::string content = buffer.str ();
pugi::xml_parse_result result = doc.load_string (content.c_str ());
available = result; return available;
}
bool create (FILE *file)
{
destroy ();
if (!file) { return false; }
fseek (file, 0, SEEK_END);
long length = ftell (file);
fseek (file, 0, SEEK_SET);
std::string content (length, '\0');
fread (&content [0], 1, length, file);
pugi::xml_parse_result result = doc.load_string (content.c_str ());
available = result; return available;
}
void destroy () { if (!available) return; doc.reset (); available = false; }
bool valid () const { return available; }
std::string display_name (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? visual.attribute ("DisplayName").as_string () : "";
}
std::wstring display_name (const std::wstring &id = L"App") const { return pugi::as_wide (this->display_name (pugi::as_utf8 (id))); }
std::string logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
std::string logo = visual.attribute ("Logo").as_string ();
return !logo.empty () ? logo : visual.attribute ("Square150x150Logo").as_string ();
}
std::wstring logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->logo (pugi::as_utf8 (id))); }
std::string small_logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
std::string smallLogo = visual.attribute ("SmallLogo").as_string ();
return !smallLogo.empty () ? smallLogo : visual.attribute ("Square70x70Logo").as_string ();
}
std::wstring small_logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->small_logo (pugi::as_utf8 (id))); }
TextColor foreground_text (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return TextColor::dark;
std::string fg = visual.attribute ("ForegroundText").as_string ();
return (fg == "light") ? TextColor::light : TextColor::dark;
}
TextColor foreground_text (const std::wstring &id = L"App") const { return (this->foreground_text (pugi::as_utf8 (id))); }
std::string lnk_32x32_logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? visual.attribute ("Lnk32x32Logo").as_string () : "";
}
std::wstring lnk_32x32_logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->lnk_32x32_logo (pugi::as_utf8 (id))); }
std::string item_display_logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
std::string itemLogo = visual.attribute ("ItemDisplayLogo").as_string ();
if (!itemLogo.empty ()) return itemLogo;
itemLogo = visual.attribute ("Lnk32x32Logo").as_string ();
return !itemLogo.empty () ? itemLogo : visual.attribute ("Square44x44Logo").as_string ();
}
std::wstring item_display_logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->item_display_logo (pugi::as_utf8 (id))); }
bool show_name_on_tile (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? (std::string (visual.attribute ("ShowNameOnSquare150x150Logo").as_string ()) == "on") : false;
}
bool show_name_on_tile (const std::wstring &id = L"App") const { return (this->show_name_on_tile (pugi::as_utf8 (id))); }
std::string background_color (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? visual.attribute ("BackgroundColor").as_string () : "";
}
std::wstring background_color (const std::wstring &id = L"App") const { return pugi::as_wide (this->background_color (pugi::as_utf8 (id))); }
std::string splash_screen_image (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
pugi::xml_node splash = visual.child ("SplashScreen");
return splash ? splash.attribute ("Image").as_string () : "";
}
std::wstring splash_screen_image (const std::wstring &id = L"App") const { return pugi::as_wide (this->splash_screen_image (pugi::as_utf8 (id))); }
std::string splash_screen_backgroundcolor (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
pugi::xml_node splash = visual.child ("SplashScreen");
std::string bg = splash ? splash.attribute ("BackgroundColor").as_string () : "";
return !bg.empty () ? bg : visual.attribute ("BackgroundColor").as_string ();
}
std::wstring splash_screen_backgroundcolor (const std::wstring &id = L"App") const { return pugi::as_wide (this->splash_screen_backgroundcolor (pugi::as_utf8 (id))); }
std::string splash_screen_backgroundcolor_darkmode (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
pugi::xml_node splash = visual.child ("SplashScreen");
std::string bg = splash ? splash.attribute ("DarkModeBackgroundColor").as_string () : "";
return !bg.empty () ? bg : visual.attribute ("DarkModeBackgroundColor").as_string ();
}
std::wstring splash_screen_backgroundcolor_darkmode (const std::wstring &id = L"App") const { return pugi::as_wide (this->splash_screen_backgroundcolor_darkmode (pugi::as_utf8 (id))); }
bool is_appid_exists (const std::string &id) const
{
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr && LabelEqual (std::string (attr.value ()), id)) return true;
}
return pugi::xml_node ();
}
else if (rootName == "Application")
{
pugi::xml_attribute attr = root.attribute ("Id");
if (attr && LabelEqual (std::string (attr.value ()), id)) return true;
}
return false;
}
bool is_appid_exists (const std::wstring &id) const { return this->is_appid_exists (pugi::as_utf8 (id)); }
size_t app_ids (std::vector <std::string> &output) const
{
if (!&output) return 0;
output.clear ();
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, std::string (lp));
}
}
}
else if (rootName == "Application")
{
pugi::xml_attribute attr = root.attribute ("Id");
if (attr)
{
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, std::string (lp));
}
}
}
if (!output.size ()) push_unique (output, std::string ("App"));
return output.size ();
}
size_t app_ids (std::vector <std::wstring> &output) const
{
if (!&output) return 0;
output.clear ();
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, pugi::as_wide (lp));
}
}
}
else if (rootName == "Application")
{
pugi::xml_attribute attr = root.attribute ("Id");
if (attr)
{
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, pugi::as_wide (lp));
}
}
}
if (!output.size ()) push_unique (output, std::wstring (L"App"));
return output.size ();
}
private:
pugi::xml_document doc;
bool available;
// 根据 id 查找 VisualElements 节点:若根节点为 <Applications>,遍历所有 <Application> 查找其 <VisualElements> 节点中属性 Id 等于 id;若根节点为 <Application>,直接返回其 <VisualElements>
pugi::xml_node visual_element_node (const std::string &id) const
{
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr && LabelEqual (std::string (attr.value ()), id))
{
pugi::xml_node visual = app.child ("VisualElements");
if (visual) return visual;
}
}
return pugi::xml_node ();
}
else if (rootName == "Application") return root.child ("VisualElements");
return pugi::xml_node ();
}
std::string to_utf8 (const std::wstring &wstr) const
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return conv.to_bytes (wstr);
}
};
class resxmldoc
{
private:
std::wstring filepath;
pugi::xml_document doc;
bool available = false;
std::string to_utf8 (const std::wstring &wstr) const
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return conv.to_bytes (wstr);
}
public:
resxmldoc (const std::wstring &xmlpath) { create (xmlpath); }
void destroy () { if (!available) return; doc.reset (); available = false; }
~resxmldoc () { destroy (); }
bool create (const std::wstring &xmlpath)
{
destroy ();
std::wstring ws (filepath = xmlpath);
std::string s = to_utf8 (ws);
pugi::xml_parse_result result = doc.load_file (s.c_str ());
available = result; return available;
}
std::string get (const std::string &id) const
{
auto root = doc.first_child ();
auto nodes = root.children ();
for (auto it : nodes)
{
if (IsNormalizeStringEquals (std::string (it.attribute ("id").as_string ()), id))
{
auto scales = it.children ();
std::map <int, std::string> s_v;
for (auto it_s : scales)
{
std::string dpi = it_s.attribute ("dpi").as_string ();
if (IsNormalizeStringEquals (dpi.c_str (), "default")) { s_v [0] = it_s.text ().get (); }
else
{
try { s_v [it_s.attribute ("dpi").as_int ()] = it_s.text ().get (); }
catch (...) {}
}
}
std::vector <std::pair <int, std::string>> existfilepath;
{
std::vector <std::pair <int, std::string>> vec (s_v.begin (), s_v.end ());
std::sort (vec.begin (), vec.end (), [] (auto &a, auto &b) { return a.second < b.second; });
for (auto &it_ss : vec)
{
it_ss.second = pugi::as_utf8 (CombinePath (GetFileDirectoryW (filepath), pugi::as_wide (it_ss.second)));
if (IsFileExists (pugi::as_wide (it_ss.second))) existfilepath.push_back (it_ss);
}
}
int dpipercent = GetDPI ();
for (auto &it_path : existfilepath)
{
if (it_path.first >= dpipercent) return it_path.second;
}
if (!existfilepath.empty ()) return existfilepath.at (0).second;
return "";
break;
}
}
return "";
}
std::wstring get (const std::wstring &id) const { return pugi::as_wide (get (WStringToString (id))); }
std::wstring operator [] (const std::wstring &id) const { return get (id); }
std::wstring operator [] (const std::wstring &id) { return get (id); }
std::string operator [] (const std::string &id) const { return get (id); }
std::string operator [] (const std::string &id) { return get (id); }
};
+193
View File
@@ -0,0 +1,193 @@
#pragma once
#include <vector>
#include <string>
#include <cstdint>
typedef uint64_t UINT64;
typedef int64_t INT64;
typedef uint16_t UINT16;
typedef struct version
{
UINT16 major = 0, minor = 0, build = 0, revision = 0;
version (UINT64 value):
major ((value >> 0x30) & 0xFFFF), minor ((value >> 0x20) & 0xFFFF),
build ((value >> 0x10) & 0xFFFF), revision ((value) & 0xFFFF) {}
version (UINT16 major, UINT16 minor, UINT16 build, UINT16 revision):
major (major), minor (minor), build (build), revision (revision) {}
version (const std::wstring &verstr) { this->interpret (verstr); }
version (const std::string &verstr) { this->interpret (verstr); }
version () {}
version (const version &other): major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
version (version &&other) noexcept: major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
version &operator = (const version &other)
{
if (this != &other)
{
major = other.major;
minor = other.minor;
build = other.build;
revision = other.revision;
}
return *this;
}
version &operator = (version &&other) noexcept
{
if (this != &other)
{
major = other.major;
minor = other.minor;
build = other.build;
revision = other.revision;
}
return *this;
}
version &operator = (UINT64 value) { this->data (value); return *this; }
UINT64 data () const { return (((UINT64)major) << 48) | (((UINT64)minor) << 32) | (((UINT64)build) << 16) | ((UINT64)revision); }
UINT64 data (UINT64 value)
{
major = (value >> 48) & 0xFFFF;
minor = (value >> 32) & 0xFFFF;
build = (value >> 16) & 0xFFFF;
revision = value & 0xFFFF;
return value;
}
std::wstring stringifyw () const
{
std::wstringstream ss;
ss << major << L'.' << minor << L'.' << build << L'.' << revision;
return ss.str ();
}
std::string stringify () const
{
std::stringstream ss;
ss << major << '.' << minor << '.' << build << '.' << revision;
return ss.str ();
}
version &interpret (const std::wstring &verstr)
{
auto result = split (verstr);
if (result.size () > 0) this->major = _wtoi (result [0].c_str ());
if (result.size () > 1) this->minor = _wtoi (result [1].c_str ());
if (result.size () > 2) this->build = _wtoi (result [2].c_str ());
if (result.size () > 3) this->revision = _wtoi (result [3].c_str ());
return *this;
}
version &interpret (const std::string &verstr)
{
auto result = split (verstr);
if (result.size () > 0) this->major = atoi (result [0].c_str ());
if (result.size () > 1) this->minor = atoi (result [1].c_str ());
if (result.size () > 2) this->build = atoi (result [2].c_str ());
if (result.size () > 3) this->revision = atoi (result [3].c_str ());
return *this;
}
bool empty () const { return *(UINT64 *)this == 0; }
friend bool operator == (const version &l, const version &r) { return *(UINT64 *)&l == *(UINT64 *)&r; }
friend bool operator == (const version &l, const UINT64 &r) { return l.data () == r; }
friend bool operator == (const UINT64 &r, const version &l) { return l.data () == r; }
friend bool operator < (const version &l, const version &r) { return l.data () < r.data (); }
friend bool operator > (const version &l, const version &r) { return l.data () > r.data (); }
friend bool operator <= (const version &l, const version &r) { return l.data () <= r.data (); }
friend bool operator >= (const version &l, const version &r) { return l.data () >= r.data (); }
friend bool operator != (const version &l, const version &r) { return *(UINT64 *)&l != *(UINT64 *)&r; }
explicit operator bool () const { return !this->empty (); }
bool operator ! () { return this->empty (); }
friend std::ostream &operator << (std::ostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
friend std::wostream &operator << (std::wostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
bool equals (const version &r) const { return *this == r; }
INT64 compare (const version &r) const { return this->data () - r.data (); }
static version parse (const std::wstring &value) { return version (value); }
static version parse (const std::string &value) { return version (value); }
static std::wstring stringifyw (const version &v) { return v.stringifyw (); }
static std::string stringify (const version &v) { return v.stringify (); }
static bool equals (const version &l, const version &r) { return l == r; }
static INT64 compare (const version &l, const version &r) { return l.data () - r.data (); }
static version decode (UINT64 value) { return version (value); }
static UINT64 encode (const version &v) { return v.data (); }
protected:
template <typename StringType> std::vector <StringType> split (const StringType &str, typename StringType::value_type delimiter1 = '.', typename StringType::value_type delimiter2 = ',')
{
std::vector <StringType> result;
std::basic_stringstream<typename StringType::value_type> ss (str);
StringType segment;
while (std::getline (ss, segment, delimiter1))
{
size_t pos = 0;
while ((pos = segment.find (delimiter2)) != StringType::npos)
{
result.push_back (segment.substr (0, pos));
segment.erase (0, pos + 1);
}
if (!segment.empty ()) result.push_back (segment);
}
return result;
}
} Version;
#ifdef __cplusplus_cli
using namespace System;
using namespace System::Runtime::InteropServices;
[ComVisible (true)]
public ref class _I_Version
{
private:
UINT16 major = 0, minor = 0, build = 0, revision = 0;
public:
property UINT16 Major { UINT16 get () { return major; } void set (UINT16 value) { major = value; } }
property UINT16 Minor { UINT16 get () { return minor; } void set (UINT16 value) { minor = value; } }
property UINT16 Build { UINT16 get () { return build; } void set (UINT16 value) { build = value; } }
property UINT16 Revision { UINT16 get () { return revision; } void set (UINT16 value) { revision = value; } }
property array <UINT16> ^Data
{
array <UINT16> ^get ()
{
return gcnew array <UINT16> {
major, minor, build, revision
};
}
void set (array <UINT16> ^arr)
{
major = minor = build = revision = 0;
for (size_t i = 0; i < arr->Length; i ++)
{
switch (i)
{
case 0: major = arr [i]; break;
case 1: minor = arr [i]; break;
case 2: build = arr [i]; break;
case 3: revision = arr [i]; break;
default: break;
}
}
}
}
property String ^DataStr
{
String ^get () { return Stringify (); }
void set (String ^str) { Parse (str); }
}
_I_Version (UINT16 p_ma, UINT16 p_mi, UINT16 p_b, UINT16 p_r):
major (p_ma), minor (p_mi), build (p_b), revision (p_r) {}
_I_Version (UINT16 p_ma, UINT16 p_mi, UINT16 p_b):
major (p_ma), minor (p_mi), build (p_b), revision (0) {}
_I_Version (UINT16 p_ma, UINT16 p_mi):
major (p_ma), minor (p_mi), build (0), revision (0) {}
_I_Version (UINT16 p_ma):
major (p_ma), minor (0), build (0), revision (0) {}
_I_Version () {}
_I_Version %Parse (String ^ver)
{
auto strarr = ver->Split ('.');
auto arr = gcnew array <UINT16> (4);
for (size_t i = 0; i < strarr->Length; i ++)
{
try { arr [i] = Convert::ToUInt16 (strarr [i]); }
catch (...) {}
}
Data = arr;
return *this;
}
String ^Stringify () { return major + "." + minor + "." + build + "." + revision; }
String ^ToString () override { return Stringify (); }
bool Valid () { return Major != 0 && Minor != 0 && Build != 0 && Revision != 0; }
};
#endif