mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
Organized the project files.
And also fixed some bugs.
This commit is contained in:
@@ -1 +0,0 @@
|
||||
E:/Profiles/Bruce/Documents/visual studio 2015/Projects/priformatcli/priformatcli
|
||||
BIN
priformatcli/PriFileFormat.dll
Normal file
BIN
priformatcli/PriFileFormat.dll
Normal file
Binary file not shown.
30
priformatcli/ReadMe.txt
Normal file
30
priformatcli/ReadMe.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
========================================================================
|
||||
动态链接库:priformatcli 项目概述
|
||||
========================================================================
|
||||
|
||||
应用程序向导已为您创建了此 priformatcli DLL。
|
||||
|
||||
本文件概要介绍组成 priformatcli 应用程序的每个文件的内容。
|
||||
|
||||
|
||||
priformatcli.vcxproj
|
||||
这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
|
||||
|
||||
priformatcli.vcxproj.filters
|
||||
这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
|
||||
|
||||
priformatcli.cpp
|
||||
这是主 DLL 源文件。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
其他标准文件:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
这些文件用于生成名为 priformatcli.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
其他注释:
|
||||
|
||||
应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
19
priformatcli/dllmain.cpp
Normal file
19
priformatcli/dllmain.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// dllmain.cpp : 定义 DLL 应用程序的入口点。
|
||||
#include "stdafx.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
256
priformatcli/localeex.h
Normal file
256
priformatcli/localeex.h
Normal file
@@ -0,0 +1,256 @@
|
||||
#pragma once
|
||||
#include <WinNls.h>
|
||||
#include <string>
|
||||
static 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;
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
42
priformatcli/mpstr.h
Normal file
42
priformatcli/mpstr.h
Normal 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::wstring(UTF-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);
|
||||
}
|
||||
457
priformatcli/nstring.h
Normal file
457
priformatcli/nstring.h
Normal file
@@ -0,0 +1,457 @@
|
||||
#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;
|
||||
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) {}
|
||||
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); }
|
||||
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;
|
||||
}
|
||||
19
priformatcli/prifile.h
Normal file
19
priformatcli/prifile.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#using "./PriFileFormat.dll"
|
||||
using namespace PriFileFormat;
|
||||
#include <comip.h>
|
||||
#include <atlbase.h>
|
||||
#include <atlsafe.h>
|
||||
#include <objidl.h>
|
||||
#include <msclr/marshal.h>
|
||||
#include <msclr/gcroot.h>
|
||||
System::Runtime::InteropServices::ComTypes::IStream ^ComIStreamToCliIStream (IStream *pNativeStream)
|
||||
{
|
||||
if (pNativeStream == nullptr) throw gcnew System::ArgumentNullException ("pNativeStream");
|
||||
pNativeStream->AddRef ();
|
||||
System::IntPtr ptr (pNativeStream);
|
||||
// ½« IUnknown ת»»ÎªÍÐ¹Ü IStream
|
||||
System::Object ^obj = System::Runtime::InteropServices::Marshal::GetObjectForIUnknown (ptr);
|
||||
// ·µ»ØÎª ComTypes::IStream^
|
||||
return (System::Runtime::InteropServices::ComTypes::IStream ^)obj;
|
||||
}
|
||||
877
priformatcli/priformatcli.cpp
Normal file
877
priformatcli/priformatcli.cpp
Normal file
@@ -0,0 +1,877 @@
|
||||
// priformatcli.cpp : 定义 DLL 应用程序的导出函数。
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "priformatcli.h"
|
||||
#include "prifile.h"
|
||||
#include "typestrans.h"
|
||||
#include "mpstr.h"
|
||||
#include "nstring.h"
|
||||
#include "themeinfo.h"
|
||||
#include "localeex.h"
|
||||
#include "syncutil.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cwchar>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
const std::wstring g_swMsResUriProtocolName = L"ms-resource:";
|
||||
const size_t g_cbMsResPNameLength = lstrlenW (g_swMsResUriProtocolName.c_str ());
|
||||
std::wstring g_swExcept = L"";
|
||||
CriticalSection g_csLastErr;
|
||||
CriticalSection g_threadlock;
|
||||
CriticalSection g_iterlock;
|
||||
struct destruct
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
destruct (std::function <void ()> init): endtask (init) {}
|
||||
~destruct () { if (endtask) endtask (); }
|
||||
};
|
||||
void SetPriLastError (const std::wstring &lpMsg)
|
||||
{
|
||||
CreateScopedLock (g_csLastErr);
|
||||
g_swExcept = lpMsg;
|
||||
}
|
||||
enum class OpenType
|
||||
{
|
||||
Unknown,
|
||||
IStream,
|
||||
Stream
|
||||
};
|
||||
ref class PriFileInst
|
||||
{
|
||||
public:
|
||||
PriFile ^inst = nullptr;
|
||||
OpenType opentype = OpenType::Unknown;
|
||||
IStream *isptr = nullptr;
|
||||
System::IO::FileStream ^fsptr = nullptr;
|
||||
operator PriFile ^ () { return inst; }
|
||||
operator IStream * () { return isptr; }
|
||||
operator System::IO::FileStream ^ () { return fsptr; }
|
||||
explicit operator bool () { return inst && (int)opentype && ((bool)isptr ^ (fsptr != nullptr)); }
|
||||
operator System::IO::Stream ^ ()
|
||||
{
|
||||
if (isptr) return gcnew ComStreamWrapper (ComIStreamToCliIStream (isptr));
|
||||
else return fsptr;
|
||||
}
|
||||
size_t Seek (int64_t offset, System::IO::SeekOrigin origin)
|
||||
{
|
||||
if (isptr)
|
||||
{
|
||||
ULARGE_INTEGER ul;
|
||||
ul.QuadPart = 0;
|
||||
LARGE_INTEGER lo;
|
||||
lo.QuadPart = offset;
|
||||
DWORD dwOrigin = 0;
|
||||
switch (origin)
|
||||
{
|
||||
case System::IO::SeekOrigin::Begin: dwOrigin = STREAM_SEEK_SET;
|
||||
break;
|
||||
case System::IO::SeekOrigin::Current: dwOrigin = STREAM_SEEK_CUR;
|
||||
break;
|
||||
case System::IO::SeekOrigin::End: dwOrigin = STREAM_SEEK_END;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
HRESULT hr = isptr->Seek (lo, dwOrigin, &ul);
|
||||
return ul.QuadPart;
|
||||
}
|
||||
else if (fsptr)
|
||||
{
|
||||
return fsptr->Seek (offset, origin);
|
||||
}
|
||||
throw gcnew NullReferenceException ("Error: cannot get the stream.");
|
||||
return 0;
|
||||
}
|
||||
!PriFileInst ()
|
||||
{
|
||||
if (fsptr)
|
||||
{
|
||||
fsptr->Close ();
|
||||
delete fsptr;
|
||||
fsptr = nullptr;
|
||||
}
|
||||
if (inst)
|
||||
{
|
||||
delete inst;
|
||||
inst = nullptr;
|
||||
}
|
||||
}
|
||||
~PriFileInst ()
|
||||
{
|
||||
if (fsptr)
|
||||
{
|
||||
fsptr->Close ();
|
||||
delete fsptr;
|
||||
fsptr = nullptr;
|
||||
}
|
||||
if (inst)
|
||||
{
|
||||
delete inst;
|
||||
inst = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
std::wstring GetStringLeft (const std::wstring &str, size_t length = 1)
|
||||
{
|
||||
std::wstring ret = L"";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = lstrlenW (str.c_str ());
|
||||
for (size_t i = 0; i < length && i < slen; i ++)
|
||||
{
|
||||
ret += str.at (i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::wstring GetStringRight (const std::wstring &str, size_t length = 1)
|
||||
{
|
||||
std::wstring ret = L"";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = lstrlenW (str.c_str ());
|
||||
for (size_t i = ((int64_t)slen - length) < 0 ? 0 : slen - length; i < slen; i ++) ret += str.at (i);
|
||||
return ret;
|
||||
}
|
||||
std::string GetStringLeft (const std::string &str, size_t length = 1)
|
||||
{
|
||||
std::string ret = "";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = strlen (str.c_str ());
|
||||
for (size_t i = 0; i < length && i < slen; i ++)
|
||||
{
|
||||
ret += str.at (i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::string GetStringRight (const std::string &str, size_t length = 1)
|
||||
{
|
||||
std::string ret = "";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = strlen (str.c_str ());
|
||||
for (size_t i = ((int64_t)slen - length) < 0 ? 0 : slen - length; i < slen; i ++) ret += str.at (i);
|
||||
return ret;
|
||||
}
|
||||
size_t KeyToPath (const std::wstring &key, std::vector <std::wnstring> &output);
|
||||
typedef struct _TASKITEM_SEARCH
|
||||
{
|
||||
std::wstring swKey;
|
||||
int iTaskType; // 0: 字符串,1: 文件路径
|
||||
operator std::wstring () { return swKey; }
|
||||
operator LPCWSTR () { return swKey.c_str (); }
|
||||
operator std::wnstring () { return swKey; }
|
||||
void set_key (const std::wstring &value)
|
||||
{
|
||||
iTaskType = std::wnstring (GetStringLeft (std::wnstring::trim (value), g_cbMsResPNameLength)) != g_swMsResUriProtocolName;
|
||||
swKey = value;
|
||||
}
|
||||
bool isuri () const
|
||||
{
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (swKey), g_cbMsResPNameLength)) == g_swMsResUriProtocolName;
|
||||
}
|
||||
bool isfulluri () const
|
||||
{
|
||||
const std::wstring root = L"//";
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (swKey), g_cbMsResPNameLength + root.length ())) == g_swMsResUriProtocolName + root;
|
||||
}
|
||||
bool isfilepath () const { return !isuri (); }
|
||||
bool isrelativeuri () const { return !isfulluri () && isuri (); }
|
||||
size_t get_path (std::vector <std::wnstring> &output) const
|
||||
{
|
||||
output.clear ();
|
||||
auto &path = output;
|
||||
KeyToPath (swKey, path);
|
||||
if (isrelativeuri ())
|
||||
{
|
||||
std::wstring nopre = GetStringRight (swKey, swKey.length () - g_cbMsResPNameLength);
|
||||
std::wstring firstch = GetStringLeft (nopre, 1);
|
||||
if (firstch [0] != L'/') path.insert (path.begin (), L"resources");
|
||||
}
|
||||
else if (isfilepath ()) path.insert (path.begin (), L"Files");
|
||||
return output.size ();
|
||||
}
|
||||
_TASKITEM_SEARCH &operator = (const std::wstring &v)
|
||||
{
|
||||
set_key (v);
|
||||
return *this;
|
||||
}
|
||||
explicit _TASKITEM_SEARCH (const std::wstring &v, int type = -1)
|
||||
{
|
||||
if (type < 0 || type > 1) set_key (v);
|
||||
else
|
||||
{
|
||||
swKey = v;
|
||||
iTaskType = type;
|
||||
}
|
||||
}
|
||||
_TASKITEM_SEARCH (int type, const std::wstring &v = L"")
|
||||
{
|
||||
if (type < 0 || type > 1) set_key (v);
|
||||
else
|
||||
{
|
||||
swKey = v;
|
||||
iTaskType = type;
|
||||
}
|
||||
}
|
||||
_TASKITEM_SEARCH () = default;
|
||||
bool operator == (const _TASKITEM_SEARCH &another) const
|
||||
{
|
||||
return std::wnstring (swKey).equals (another.swKey);
|
||||
}
|
||||
bool operator < (const _TASKITEM_SEARCH &another) const
|
||||
{
|
||||
return std::wnstring (swKey).compare (another.swKey) < 0;
|
||||
}
|
||||
} TASKITEM_SEARCH;
|
||||
typedef struct _TASKRESULT_FIND
|
||||
{
|
||||
std::wstring swValue = L"";
|
||||
int iFindResult = -1; // -1 未进行查找,0:查找但未找到,1:查找且已找到
|
||||
operator std::wstring () { return swValue; }
|
||||
operator LPCWSTR () { return swValue.c_str (); }
|
||||
operator std::wnstring () { return swValue; }
|
||||
_TASKRESULT_FIND (const std::wstring &v, int findres = -1):
|
||||
swValue (v), iFindResult (findres) {}
|
||||
_TASKRESULT_FIND (int findres, const std::wstring &v = L""):
|
||||
swValue (v), iFindResult (findres) {}
|
||||
_TASKRESULT_FIND () = default;
|
||||
// 是否查找到
|
||||
bool is_find () const { return iFindResult > 0; }
|
||||
// 是否进行过查找
|
||||
bool has_search () const { return iFindResult >= 0; }
|
||||
} TASKRESULT_FIND;
|
||||
typedef struct _TASKINFO_SEARCH
|
||||
{
|
||||
bool bIsRunning = false;
|
||||
std::map <TASKITEM_SEARCH, TASKRESULT_FIND> mapTasks;
|
||||
operator std::map <TASKITEM_SEARCH, TASKRESULT_FIND> () { return mapTasks; }
|
||||
} TASKINFO_SEARCH;
|
||||
|
||||
size_t UriToPath (System::Uri ^uri, std::vector <std::wnstring> &output)
|
||||
{
|
||||
output.clear ();
|
||||
try
|
||||
{
|
||||
auto path = uri->AbsolutePath;
|
||||
auto arr = path->Split ('/');
|
||||
for (size_t i = 0; i < arr->Length; i ++)
|
||||
{
|
||||
auto str = arr [i];
|
||||
std::wnstring cppstr = MPStringToStdW (str);
|
||||
if (cppstr.empty ()) continue;
|
||||
output.push_back (cppstr);
|
||||
}
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
std::vector <std::wstring> split_wcstok (const std::wstring &str, const std::wstring &delim)
|
||||
{
|
||||
std::vector <std::wstring> result;
|
||||
std::wstring cpy = L"" + str;
|
||||
LPWSTR context = nullptr;
|
||||
LPWSTR token = wcstok ((LPWSTR)cpy.c_str (), delim.c_str (), &context);
|
||||
while (token)
|
||||
{
|
||||
result.push_back (token);
|
||||
token = wcstok (nullptr, delim.c_str (), &context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
std::vector <std::wnstring> VecWStringToWNString (const std::vector <std::wstring> &vec)
|
||||
{
|
||||
std::vector <std::wnstring> wns;
|
||||
wns.reserve (vec.size ());
|
||||
for (auto &it : vec) wns.push_back (it);
|
||||
return wns;
|
||||
}
|
||||
size_t KeyToPath (const std::wstring &key, std::vector <std::wnstring> &output)
|
||||
{
|
||||
output.clear ();
|
||||
try
|
||||
{
|
||||
// 1: 字符串,0: 文件路径
|
||||
int iTaskType = std::wnstring (GetStringLeft (key, g_cbMsResPNameLength)) == g_swMsResUriProtocolName;
|
||||
if (iTaskType)
|
||||
{
|
||||
Uri ^uri = gcnew Uri (CStringToMPString (key.c_str ()));
|
||||
size_t ret = UriToPath (uri, output);
|
||||
delete uri;
|
||||
uri = nullptr;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto arr = split_wcstok (key, L"\\");
|
||||
for (auto &it : arr)
|
||||
{
|
||||
if (std::wnstring (it).empty ()) continue;
|
||||
else output.push_back (it);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
auto arr = split_wcstok (key, L"\\");
|
||||
for (auto &it : arr)
|
||||
{
|
||||
if (std::wnstring (it).empty ()) continue;
|
||||
else output.push_back (it);
|
||||
}
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t KeyToPath (const TASKITEM_SEARCH &key, std::vector <std::wnstring> &output)
|
||||
{
|
||||
return KeyToPath (key.swKey, output);
|
||||
}
|
||||
bool PathEquals (const std::vector <std::wnstring> &left, const std::vector <std::wnstring> &right)
|
||||
{
|
||||
if (left.size () != right.size ()) return false;
|
||||
try
|
||||
{
|
||||
for (size_t i = 0; i < left.size () && i < right.size (); i ++)
|
||||
{
|
||||
if (left.at (i) != right.at (i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map <PCSPRIFILE, TASKINFO_SEARCH> g_tasklist;
|
||||
|
||||
PCSPRIFILE CreatePriFileInstanceFromStream (PCOISTREAM pStream)
|
||||
{
|
||||
if (!pStream) return nullptr;
|
||||
try
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (pStream) hr = ((IStream *)pStream)->Seek (LARGE_INTEGER {}, STREAM_SEEK_SET, nullptr);
|
||||
auto pri = PriFile::Parse (ComIStreamToCliIStream (reinterpret_cast <IStream *> (pStream)));
|
||||
PriFileInst ^inst = gcnew PriFileInst ();
|
||||
inst->inst = pri;
|
||||
inst->opentype = OpenType::IStream;
|
||||
inst->isptr = reinterpret_cast <IStream *> (pStream);
|
||||
auto handle = System::Runtime::InteropServices::GCHandle::Alloc (inst);
|
||||
IntPtr token = System::Runtime::InteropServices::GCHandle::ToIntPtr (handle);
|
||||
return reinterpret_cast <PCSPRIFILE> (token.ToPointer ());
|
||||
}
|
||||
catch (System::Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
PCSPRIFILE CreatePriFileInstanceFromPath (LPCWSTR lpswFilePath)
|
||||
{
|
||||
if (!lpswFilePath) return nullptr;
|
||||
if (!*lpswFilePath) return nullptr;
|
||||
try
|
||||
{
|
||||
auto fstream = System::IO::File::OpenRead (CStringToMPString (lpswFilePath ? lpswFilePath : L""));
|
||||
auto pri = PriFile::Parse (fstream);
|
||||
PriFileInst ^inst = gcnew PriFileInst ();
|
||||
inst->inst = pri;
|
||||
inst->opentype = OpenType::Stream;
|
||||
inst->fsptr = fstream;
|
||||
auto handle = System::Runtime::InteropServices::GCHandle::Alloc (inst);
|
||||
IntPtr token = System::Runtime::InteropServices::GCHandle::ToIntPtr (handle);
|
||||
return reinterpret_cast <PCSPRIFILE> (token.ToPointer ());
|
||||
}
|
||||
catch (System::Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void DestroyPriFileInstance (PCSPRIFILE pFilePri)
|
||||
{
|
||||
if (!pFilePri) return;
|
||||
try
|
||||
{
|
||||
if (g_tasklist.find (pFilePri) != g_tasklist.end ())
|
||||
{
|
||||
g_tasklist [pFilePri].bIsRunning = false;
|
||||
g_tasklist.erase (pFilePri);
|
||||
}
|
||||
IntPtr handlePtr = IntPtr (pFilePri);
|
||||
System::Runtime::InteropServices::GCHandle handle = System::Runtime::InteropServices::GCHandle::FromIntPtr (handlePtr);
|
||||
PriFileInst ^inst = safe_cast <PriFileInst ^> (handle.Target);
|
||||
delete inst;
|
||||
handle.Free ();
|
||||
System::GC::Collect ();
|
||||
System::GC::WaitForPendingFinalizers ();
|
||||
System::GC::Collect ();
|
||||
}
|
||||
catch (System::Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
}
|
||||
LPCWSTR PriFileGetLastError ()
|
||||
{
|
||||
CreateScopedLock (g_csLastErr);
|
||||
return g_swExcept.c_str ();
|
||||
}
|
||||
enum class Contrast
|
||||
{
|
||||
None,
|
||||
White,
|
||||
Black,
|
||||
High,
|
||||
Low
|
||||
};
|
||||
struct candidate_value
|
||||
{
|
||||
int type; // 1:语言;2:缩放和对比度;0:未知
|
||||
std::wstring value;
|
||||
union restitem
|
||||
{
|
||||
struct // type==1
|
||||
{
|
||||
std::wstring languages;
|
||||
};
|
||||
struct // type==2
|
||||
{
|
||||
uint32_t scale;
|
||||
Contrast contrast;
|
||||
};
|
||||
struct // type==0
|
||||
{
|
||||
std::wstring not_support_restrict;
|
||||
};
|
||||
restitem () {} // 不做初始化,由外层控制构造
|
||||
~restitem () {} // 不自动析构,由外层控制析构
|
||||
} restitems;
|
||||
candidate_value (const std::wstring &val, const std::wstring &lang): type (1), value (val)
|
||||
{
|
||||
new(&restitems.languages) std::wstring (lang);
|
||||
}
|
||||
candidate_value (const std::wstring &val, uint32_t scale, Contrast contrast = Contrast::None): type (2), value (val)
|
||||
{
|
||||
restitems.scale = scale;
|
||||
restitems.contrast = contrast;
|
||||
}
|
||||
candidate_value (const std::wstring &val): type (0), value (val)
|
||||
{
|
||||
new (&restitems.not_support_restrict) std::wstring (L"");
|
||||
}
|
||||
candidate_value (const candidate_value &other): type (other.type), value (other.value)
|
||||
{
|
||||
if (type == 1) new(&restitems.languages) std::wstring (other.restitems.languages);
|
||||
else if (type == 2)
|
||||
{
|
||||
restitems.scale = other.restitems.scale;
|
||||
restitems.contrast = other.restitems.contrast;
|
||||
}
|
||||
else new (&restitems.not_support_restrict) std::wstring (other.restitems.not_support_restrict);
|
||||
}
|
||||
candidate_value &operator = (const candidate_value &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->~candidate_value (); // 先析构旧内容
|
||||
new (this) candidate_value (other); // 再调用拷贝构造
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~candidate_value ()
|
||||
{
|
||||
if (type == 1) restitems.languages.~basic_string ();
|
||||
else if (type == 0) restitems.not_support_restrict.~basic_string ();
|
||||
}
|
||||
std::wstring get_language () const { return type == 1 ? restitems.languages : L""; }
|
||||
uint32_t get_scale () const { return type == 2 ? restitems.scale : 0; }
|
||||
Contrast get_contrast () const { return type == 2 ? restitems.contrast : Contrast::None; }
|
||||
};
|
||||
std::wstring GetStringValueByLocale (std::vector <candidate_value> &stringcand, const std::wstring &llc)
|
||||
{
|
||||
for (auto &it : stringcand)
|
||||
{
|
||||
if (LocaleNameCompare (it.get_language (), llc)) return it.value;
|
||||
}
|
||||
std::vector <std::wstring> scrc;
|
||||
for (auto &it : stringcand)
|
||||
{
|
||||
std::wstring rc;
|
||||
scrc.push_back (rc = GetLocaleRestrictedCodeFromLcidW (LocaleCodeToLcidW (it.get_language ())));
|
||||
if (LocaleNameCompare (rc, llc)) return it.value;
|
||||
}
|
||||
std::wstring lrc = GetLocaleRestrictedCodeFromLcidW (LocaleCodeToLcidW (llc));
|
||||
for (size_t i = 0; i < stringcand.size (); i ++)
|
||||
{
|
||||
auto &rc = scrc.at (i);
|
||||
auto &it = stringcand.at (i);
|
||||
if (LocaleNameCompare (rc, llc)) return it.value;
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
std::wstring GetSuitableStringValue (std::vector <candidate_value> &stringcand)
|
||||
{
|
||||
std::wstring ret = GetStringValueByLocale (stringcand, GetComputerLocaleCodeW ());
|
||||
if (ret.empty () || std::wnstring::trim (ret).length () == 0) ret = GetStringValueByLocale (stringcand, L"en-US");
|
||||
if (ret.empty () || std::wnstring::trim (ret).length () == 0)
|
||||
{
|
||||
for (auto &it : stringcand) return it.value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::wstring GetSuitablePathValueByDPI (std::vector<candidate_value> &pathcand)
|
||||
{
|
||||
std::sort (pathcand.begin (), pathcand.end (),
|
||||
[] (const candidate_value &v1, const candidate_value &v2) {
|
||||
return v1.get_scale () < v2.get_scale ();
|
||||
});
|
||||
if (pathcand.empty ()) return L"";
|
||||
uint32_t nowdpi = GetDPI ();
|
||||
for (auto &cv : pathcand) if (cv.get_scale () >= nowdpi) return cv.value;
|
||||
return pathcand.back ().value;
|
||||
}
|
||||
std::wstring GetSuitablePathValue (std::vector <candidate_value> &pathcand)
|
||||
{
|
||||
std::vector <candidate_value> contrasted;
|
||||
for (auto &it : pathcand) if (it.get_contrast () == Contrast::None) contrasted.emplace_back (it);
|
||||
std::wstring ret = GetSuitablePathValueByDPI (contrasted);
|
||||
if (std::wnstring (ret).empty ())
|
||||
{
|
||||
contrasted.clear ();
|
||||
for (auto &it: pathcand) if (it.get_contrast () == Contrast::White) contrasted.emplace_back (it);
|
||||
ret = GetSuitablePathValueByDPI (contrasted);
|
||||
}
|
||||
if (std::wnstring (ret).empty ())
|
||||
{
|
||||
contrasted.clear ();
|
||||
for (auto &it : pathcand) if (it.get_contrast () == Contrast::Black) contrasted.emplace_back (it);
|
||||
ret = GetSuitablePathValueByDPI (contrasted);
|
||||
}
|
||||
if (std::wnstring (ret).empty ())
|
||||
{
|
||||
contrasted.clear ();
|
||||
for (auto &it : pathcand) contrasted.emplace_back (it);
|
||||
ret = GetSuitablePathValueByDPI (contrasted);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PriFileIterateTask (PCSPRIFILE pFilePri)
|
||||
{
|
||||
CreateScopedLock (g_threadlock);
|
||||
if (g_tasklist.find (pFilePri) == g_tasklist.end ()) g_tasklist [pFilePri] = TASKINFO_SEARCH ();
|
||||
try { g_tasklist.at (pFilePri); } catch (const std::exception &e) { return; }
|
||||
auto &task = g_tasklist.at (pFilePri);
|
||||
if (task.bIsRunning == false) task.bIsRunning = true;
|
||||
else return;
|
||||
destruct endt ([&task] () {
|
||||
task.bIsRunning = false;
|
||||
});
|
||||
auto &taskitems = task.mapTasks;
|
||||
IntPtr handlePtr = IntPtr (pFilePri);
|
||||
System::Runtime::InteropServices::GCHandle handle = System::Runtime::InteropServices::GCHandle::FromIntPtr (handlePtr);
|
||||
auto pri = safe_cast <PriFileInst ^> (handle.Target);
|
||||
auto &priFile = pri;
|
||||
auto resmapsect = pri->inst->PriDescriptorSection->ResourceMapSections;
|
||||
bool isallsearched = true;
|
||||
size_t allitemslen = 0;
|
||||
std::map <std::wnstring, size_t> mapitemscnt;
|
||||
auto begtime = System::DateTime::Now;
|
||||
SearchLoop:
|
||||
allitemslen = 0;
|
||||
for (size_t i = 0; i < resmapsect->Count; i ++)
|
||||
{
|
||||
CreateScopedLock (g_iterlock);
|
||||
auto resourceMapSectionRef = resmapsect [i];
|
||||
auto resourceMapSection = pri->inst->GetSectionByRef (resourceMapSectionRef);
|
||||
if (resourceMapSection->HierarchicalSchemaReference != nullptr) continue;
|
||||
auto decisionInfoSection = pri->inst->GetSectionByRef (resourceMapSection->DecisionInfoSection);
|
||||
for each (auto candidateSet in resourceMapSection->CandidateSets->Values)
|
||||
{
|
||||
// 超时强制退出(也就没有遍及的必要了)
|
||||
if ((System::DateTime::Now - begtime).TotalSeconds > 20) return;
|
||||
allitemslen ++;
|
||||
auto item = pri->inst->GetResourceMapItemByRef (candidateSet->ResourceMapItem);
|
||||
std::wstring itemfullname = MPStringToStdW (item->FullName);
|
||||
std::vector <std::wnstring> itempath;
|
||||
{
|
||||
auto ips = split_wcstok (itemfullname, L"\\");
|
||||
for (auto &it : ips)
|
||||
{
|
||||
if (std::wnstring::empty (it)) continue;
|
||||
itempath.push_back (it);
|
||||
}
|
||||
}
|
||||
bool willcont = true;
|
||||
TASKITEM_SEARCH *taskkey = nullptr;
|
||||
for (auto &it : taskitems)
|
||||
{
|
||||
auto &key = it.first;
|
||||
auto &value = it.second;
|
||||
mapitemscnt [key.swKey] ++;
|
||||
if (value.has_search ()) continue;
|
||||
std::vector <std::wnstring> namepath;
|
||||
key.get_path (namepath);
|
||||
// KeyToPath (key, namepath);
|
||||
if (PathEquals (itempath, namepath))
|
||||
{
|
||||
taskkey = (TASKITEM_SEARCH *)&key;
|
||||
willcont = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (willcont) continue;
|
||||
auto keyname = taskkey->swKey;
|
||||
auto keytype = taskkey->iTaskType;
|
||||
std::vector <candidate_value> cands;
|
||||
for each (auto candidate in candidateSet->Candidates)
|
||||
{
|
||||
System::String ^value = nullptr;
|
||||
if (candidate->SourceFile.HasValue)
|
||||
{
|
||||
// 内嵌资源,暂无法处理
|
||||
// value = System::String::Format ("<external in {0}>", pri->GetReferencedFileByRef (candidate->SourceFile.Value)->FullName);
|
||||
value = pri->inst->GetReferencedFileByRef (candidate->SourceFile.Value)->FullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteSpan ^byteSpan = nullptr;
|
||||
if (candidate->DataItem.HasValue) byteSpan = priFile->inst->GetDataItemByRef (candidate->DataItem.Value);
|
||||
else byteSpan = candidate->Data.Value;
|
||||
pri->Seek (byteSpan->Offset, System::IO::SeekOrigin::Begin);
|
||||
auto binaryReader = gcnew System::IO::BinaryReader (pri, System::Text::Encoding::Default, true);
|
||||
auto data = binaryReader->ReadBytes ((int)byteSpan->Length);
|
||||
switch (candidate->Type)
|
||||
{
|
||||
case ResourceValueType::AsciiPath:
|
||||
case ResourceValueType::AsciiString:
|
||||
value = System::Text::Encoding::ASCII->GetString (data)->TrimEnd ('\0');
|
||||
break;
|
||||
case ResourceValueType::Utf8Path:
|
||||
case ResourceValueType::Utf8String:
|
||||
value = System::Text::Encoding::UTF8->GetString (data)->TrimEnd ('\0');
|
||||
break;
|
||||
case ResourceValueType::Path:
|
||||
case ResourceValueType::String:
|
||||
value = System::Text::Encoding::Unicode->GetString (data)->TrimEnd ('\0');
|
||||
break;
|
||||
case ResourceValueType::EmbeddedData:
|
||||
value = Convert::ToBase64String (data);
|
||||
break;
|
||||
}
|
||||
delete binaryReader;
|
||||
delete data;
|
||||
binaryReader = nullptr;
|
||||
data = nullptr;
|
||||
}
|
||||
auto qualifierSet = decisionInfoSection->QualifierSets [candidate->QualifierSet];
|
||||
auto qualis = gcnew System::Collections::Generic::Dictionary <QualifierType, Object ^> ();
|
||||
for each (auto quali in qualifierSet->Qualifiers)
|
||||
{
|
||||
auto type = quali->Type;
|
||||
auto value = quali->Value;
|
||||
qualis->Add (type, value);
|
||||
}
|
||||
if (qualis->ContainsKey (QualifierType::Language))
|
||||
{
|
||||
cands.push_back (candidate_value (MPStringToStdW (value ? value : System::String::Empty), MPStringToStdW (qualis [QualifierType::Language]->ToString ())));
|
||||
}
|
||||
else if (qualis->ContainsKey (QualifierType::Scale))
|
||||
{
|
||||
if (qualis->ContainsKey (QualifierType::Contrast))
|
||||
{
|
||||
Contrast ct = Contrast::None;
|
||||
auto contstr = std::wnstring (MPStringToStdW (qualis [QualifierType::Contrast]->ToString ()->Trim ()->ToUpper ()));
|
||||
if (contstr.equals (L"WHITE")) ct = Contrast::White;
|
||||
else if (contstr.equals (L"BLACK")) ct = Contrast::Black;
|
||||
else if (contstr.equals (L"HIGH")) ct = Contrast::High;
|
||||
cands.push_back (candidate_value (
|
||||
MPStringToStdW (value ? value : System::String::Empty),
|
||||
Convert::ToUInt32 (qualis [QualifierType::Scale]),
|
||||
ct
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
cands.push_back (candidate_value (
|
||||
MPStringToStdW (value ? value : System::String::Empty),
|
||||
Convert::ToUInt32 (qualis [QualifierType::Scale])
|
||||
));
|
||||
}
|
||||
}
|
||||
else cands.push_back (candidate_value (MPStringToStdW (value ? value : System::String::Empty)));
|
||||
delete qualis;
|
||||
qualis = nullptr;
|
||||
}
|
||||
switch (keytype)
|
||||
{
|
||||
case 0: {
|
||||
TASKRESULT_FIND tfind;
|
||||
tfind.iFindResult = 1;
|
||||
tfind.swValue = GetSuitableStringValue (cands);
|
||||
taskitems [*taskkey] = tfind;
|
||||
} break;
|
||||
case 1: {
|
||||
TASKRESULT_FIND tfind;
|
||||
tfind.iFindResult = 1;
|
||||
tfind.swValue = GetSuitablePathValue (cands);
|
||||
taskitems [*taskkey] = tfind;
|
||||
} break;
|
||||
default: {
|
||||
TASKRESULT_FIND tfind;
|
||||
tfind.iFindResult = 0;
|
||||
try
|
||||
{
|
||||
tfind.swValue = cands.at (0).value;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
taskitems [*taskkey] = tfind;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
// delete resourceMapSection;
|
||||
resourceMapSection = nullptr;
|
||||
}
|
||||
isallsearched = true;
|
||||
for (auto &it : mapitemscnt)
|
||||
{
|
||||
auto &result = taskitems [TASKITEM_SEARCH (it.first)];
|
||||
isallsearched = isallsearched && (it.second >= allitemslen && result.has_search ());
|
||||
if (it.second >= allitemslen)
|
||||
{
|
||||
if (!result.has_search ()) result.iFindResult = 0;
|
||||
}
|
||||
it.second = 0;
|
||||
}
|
||||
if (!isallsearched)
|
||||
{
|
||||
for (auto &it : mapitemscnt) it.second = 0;
|
||||
goto SearchLoop;
|
||||
}
|
||||
// task.bIsRunning = false;
|
||||
}
|
||||
void PriFileIterateTaskCli (Object^ pFilePriObj)
|
||||
{
|
||||
if (pFilePriObj == nullptr) return;
|
||||
IntPtr ptr = safe_cast <IntPtr> (pFilePriObj);
|
||||
PCSPRIFILE pFilePri = (PCSPRIFILE)ptr.ToPointer ();
|
||||
PriFileIterateTask (pFilePri);
|
||||
}
|
||||
void AddPriResourceName (PCSPRIFILE pFilePri, const std::vector <std::wnstring> &urilist)
|
||||
{
|
||||
if (!pFilePri) return;
|
||||
if (!urilist.size ()) return;
|
||||
try { g_tasklist.at (pFilePri); } catch (const std::exception &e) { g_tasklist [pFilePri] = TASKINFO_SEARCH (); }
|
||||
auto &task = g_tasklist.at (pFilePri);
|
||||
bool isallfined = true;
|
||||
{
|
||||
CreateScopedLock (g_threadlock);
|
||||
CreateScopedLock (g_iterlock);
|
||||
for (auto &it : urilist)
|
||||
{
|
||||
if (it.empty ()) continue;
|
||||
try
|
||||
{
|
||||
if (task.mapTasks [TASKITEM_SEARCH (it)].has_search ())
|
||||
{
|
||||
isallfined = isallfined && true;
|
||||
continue;
|
||||
}
|
||||
else isallfined = isallfined && false;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
task.mapTasks [TASKITEM_SEARCH (it)] = TASKRESULT_FIND ();
|
||||
isallfined = isallfined && false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isallfined) return;
|
||||
// while (task.bIsRunning) { Sleep (200); }
|
||||
System::Threading::Thread ^t = nullptr;
|
||||
if (!task.bIsRunning)
|
||||
{
|
||||
// task.bIsRunning = true;
|
||||
t = gcnew System::Threading::Thread (gcnew System::Threading::ParameterizedThreadStart (PriFileIterateTaskCli));
|
||||
t->IsBackground = true;
|
||||
t->Start (IntPtr (pFilePri));
|
||||
}
|
||||
}
|
||||
void FindPriResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList)
|
||||
{
|
||||
if (!pFilePri) return;
|
||||
if (!hUriList || !hUriList->dwLength) return;
|
||||
std::vector <std::wnstring> list;
|
||||
for (size_t i = 0; i < hUriList->dwLength; i ++)
|
||||
{
|
||||
auto &str = hUriList->aswArray [i];
|
||||
if (!str || !*str) continue;
|
||||
std::wnstring wstr (str);
|
||||
if (wstr.empty ()) continue;
|
||||
list.emplace_back (wstr);
|
||||
}
|
||||
AddPriResourceName (pFilePri, list);
|
||||
}
|
||||
void FindPriStringResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList)
|
||||
{
|
||||
FindPriResource (pFilePri, hUriList);
|
||||
}
|
||||
void FindPriPathResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hPathList)
|
||||
{
|
||||
FindPriResource (pFilePri, hPathList);
|
||||
}
|
||||
LPWSTR GetPriResource (PCSPRIFILE pFilePri, LPCWSTR lpswResId)
|
||||
{
|
||||
if (!pFilePri || !lpswResId || !*lpswResId) return nullptr;
|
||||
try { g_tasklist.at (pFilePri); }
|
||||
catch (const std::exception &e) { g_tasklist [pFilePri]; }
|
||||
auto &task = g_tasklist.at (pFilePri);
|
||||
{
|
||||
auto &result = task.mapTasks [TASKITEM_SEARCH (lpswResId)];
|
||||
if (result.has_search ()) return _wcsdup (result.swValue.c_str ());
|
||||
}
|
||||
BYTE buf [sizeof (LPCWSTRLIST) + sizeof (LPCWSTR)] = {0};
|
||||
HLPCWSTRLIST hStrList = (HLPCWSTRLIST)buf;
|
||||
hStrList->dwLength = 1;
|
||||
hStrList->aswArray [0] = lpswResId;
|
||||
FindPriResource (pFilePri, hStrList);
|
||||
while (task.bIsRunning) { Sleep (200); }
|
||||
try
|
||||
{
|
||||
auto item = task.mapTasks.at (TASKITEM_SEARCH (lpswResId));
|
||||
if (!item.has_search ()) return GetPriResource (pFilePri, lpswResId);
|
||||
return _wcsdup (item.swValue.c_str ());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SetPriLastError (StringToWString (e.what () ? e.what () : "Error: cannot find the resource."));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
LPWSTR GetPriStringResource (PCSPRIFILE pFilePri, LPCWSTR lpswUri) { return GetPriResource (pFilePri, lpswUri); }
|
||||
LPWSTR GetPriPathResource (PCSPRIFILE pFilePri, LPCWSTR lpswFilePath) { return GetPriResource (pFilePri, lpswFilePath); }
|
||||
void ClearPriCacheData ()
|
||||
{
|
||||
g_tasklist.clear ();
|
||||
}
|
||||
|
||||
BOOL IsMsResourcePrefix (LPCWSTR pResName)
|
||||
{
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (std::wstring (pResName ? pResName : L"")), g_cbMsResPNameLength)) == g_swMsResUriProtocolName;
|
||||
}
|
||||
BOOL IsMsResourceUriFull (LPCWSTR pResUri)
|
||||
{
|
||||
const std::wstring root = L"//";
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (std::wstring (pResUri)), g_cbMsResPNameLength + root.length ())) == g_swMsResUriProtocolName + root;
|
||||
}
|
||||
BOOL IsMsResourceUri (LPCWSTR pResUri)
|
||||
{
|
||||
if (!IsMsResourcePrefix (pResUri)) return false;
|
||||
try { Uri ^uri = gcnew Uri (gcnew String (pResUri ? pResUri : L"")); delete uri; }
|
||||
catch (Exception ^e) { return false; }
|
||||
return true;
|
||||
}
|
||||
315
priformatcli/priformatcli.h
Normal file
315
priformatcli/priformatcli.h
Normal file
@@ -0,0 +1,315 @@
|
||||
// 下列 ifdef 块是创建使从 DLL 导出更简单的
|
||||
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 PRIFORMATCLI_EXPORTS
|
||||
// 符号编译的。在使用此 DLL 的
|
||||
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
|
||||
// PRIFORMATCLI_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
|
||||
// 符号视为是被导出的。
|
||||
#ifdef PRIFORMATCLI_EXPORTS
|
||||
#define PRIFORMATCLI_API __declspec(dllexport)
|
||||
#else
|
||||
#define PRIFORMATCLI_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#ifndef _PRI_READER_CLI_HEADER_
|
||||
#define _PRI_READER_CLI_HEADER_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _DEFAULT_VALUE_SET(valueexpr) = valueexpr
|
||||
#ifndef PRIFORMATCLI_EXPORTS
|
||||
#define _DEFAULT_VALUE_SET_FUNC(valueexpr) _DEFAULT_VALUE_SET (valueexpr)
|
||||
#else
|
||||
#define _DEFAULT_VALUE_SET_FUNC(valueexpr)
|
||||
#endif
|
||||
#else
|
||||
#define _DEFAULT_VALUE_SET(valueexpr)
|
||||
#define _DEFAULT_VALUE_SET_FUNC(valueexpr)
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// 为了兼容。将 IStream * 转换成 PCOISTREAM 使用(C 用强制类型转换,C++ 也可以用强制类型,或者 reinterpret_cast?)。
|
||||
typedef struct COISTREAM__ *PCOISTREAM;
|
||||
// 返回 PriFile 实例指针。
|
||||
typedef struct CSPRIFILE__ *PCSPRIFILE;
|
||||
// 创建 PriFile 实例。请传入有效指针。失败返回 nullptr。
|
||||
typedef struct LPCWSTRLIST__
|
||||
{
|
||||
DWORD dwLength _DEFAULT_VALUE_SET (0);
|
||||
LPCWSTR aswArray [1] _DEFAULT_VALUE_SET ({0});
|
||||
} LPCWSTRLIST, *HLPCWSTRLIST;
|
||||
// 注意:PriFile 使用 IStream * 流类似于“借用”关系。要保证 PriFile 实例的生命周期
|
||||
// 在 IStream * 的生命周期内。
|
||||
PRIFORMATCLI_API PCSPRIFILE CreatePriFileInstanceFromStream (PCOISTREAM pStream);
|
||||
// 销毁 PriFile 对象。注意: PriFile 的销毁不会影响 IStream *。
|
||||
PRIFORMATCLI_API void DestroyPriFileInstance (PCSPRIFILE pFilePri);
|
||||
// 获取 PriFile 的文本资源。文本资源是会根据当前系统/用户正在使用的语言来选择最合适的文本。
|
||||
// 这里没有自定义获取。注:返回的有效非空指针请用 free 来释放。
|
||||
// 传入的是 ms-resource: 开头的字符串,以 URI 形式。
|
||||
// 示例:
|
||||
// 1. ms-resource://microsoft.windowscommunicationsapps/hxoutlookintl/AppManifest_OutlookDesktop_DisplayName (常见于 UWP 应用)
|
||||
// 2. ms-resource:ApplicationTitleWithBranding (常见于 Windows 8.x 应用)
|
||||
PRIFORMATCLI_API LPWSTR GetPriStringResource (PCSPRIFILE pFilePri, LPCWSTR lpswUri);
|
||||
// 获取 PriFile 的文件路径资源。对于一些如图像资源,会有对于系统不同 DPI 的适应
|
||||
// 目录分隔符为“\”(在应用清单中对于文件路径一直使用“\”),“/”不会支持。且一定为相对路径。
|
||||
// 注:返回的有效非空指针请用 free 释放。
|
||||
PRIFORMATCLI_API LPWSTR GetPriPathResource (PCSPRIFILE pFilePri, LPCWSTR lpswFilePath);
|
||||
// 从文件路径创建 PriFile 实例。(虽然用不上)。销毁同样通过 DestroyPriFileInstance。
|
||||
PRIFORMATCLI_API PCSPRIFILE CreatePriFileInstanceFromPath (LPCWSTR lpswFilePath);
|
||||
// 注意:可能会由于并发等导致返回的异常信息会错乱。
|
||||
PRIFORMATCLI_API LPCWSTR PriFileGetLastError ();
|
||||
// 对于多个资源,建议一次遍及,预先进行缓存。通过 GetPriStringResource 获取值。
|
||||
PRIFORMATCLI_API void FindPriStringResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList);
|
||||
// 对于多个资源,建议一次遍及,预先进行缓存。通过 GetPriPathResource 获取值。
|
||||
PRIFORMATCLI_API void FindPriPathResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hPathList);
|
||||
// 清理内存缓存数据,仅用于测试用。注意:清理指的是所有。
|
||||
PRIFORMATCLI_API void ClearPriCacheData ();
|
||||
// 获取资源,作用与 GetPriStringResource 和 GetPriPathResource 一样。(因为这两个函数都是调用此函数)
|
||||
PRIFORMATCLI_API LPWSTR GetPriResource (PCSPRIFILE pFilePri, LPCWSTR lpswResId);
|
||||
// 开始查找资源,与 FindPriStringResource 和 FindPriPathResource 一样(因为这两个函数都是调用此函数)
|
||||
PRIFORMATCLI_API void FindPriResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList);
|
||||
// 工具函数,用于判断是否为 ms-resource: 前缀
|
||||
PRIFORMATCLI_API BOOL IsMsResourcePrefix (LPCWSTR pResName);
|
||||
// 工具函数,用于判断是否为 ms-resource:// 前缀
|
||||
PRIFORMATCLI_API BOOL IsMsResourceUriFull (LPCWSTR pResUri);
|
||||
// 工具函数,用于判断是否为 MS-Resource URI
|
||||
PRIFORMATCLI_API BOOL IsMsResourceUri (LPCWSTR pResUri);
|
||||
#ifdef _DEFAULT_VALUE_SET
|
||||
#undef _DEFAULT_VALUE_SET
|
||||
#endif
|
||||
#ifdef _DEFAULT_VALUE_SET_FUNC
|
||||
#undef _DEFAULT_VALUE_SET_FUNC
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
#include <string>
|
||||
#include <atlbase.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
// 注意:此类仅为操作类,如果以 IStream * 来初始化类的话在类销毁时不会释放 IStream *。请在此类实例生命期结束后必须释放 IStream *
|
||||
typedef class prifile
|
||||
{
|
||||
private:
|
||||
PCSPRIFILE m_hPriFile = nullptr;
|
||||
class reltask
|
||||
{
|
||||
public:
|
||||
std::function <void ()> endtask;
|
||||
reltask (std::function <void ()> pf): endtask (pf) {}
|
||||
reltask () { if (endtask) endtask (); }
|
||||
};
|
||||
public:
|
||||
bool valid () const { return m_hPriFile != nullptr; }
|
||||
void destroy ()
|
||||
{
|
||||
if (m_hPriFile)
|
||||
{
|
||||
DestroyPriFileInstance (m_hPriFile);
|
||||
m_hPriFile = nullptr;
|
||||
}
|
||||
}
|
||||
~prifile () { destroy (); }
|
||||
bool create (IStream *p)
|
||||
{
|
||||
try
|
||||
{
|
||||
destroy ();
|
||||
if (!p) return false;
|
||||
m_hPriFile = CreatePriFileInstanceFromStream ((PCOISTREAM)p);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
m_hPriFile = nullptr;
|
||||
}
|
||||
return valid ();
|
||||
}
|
||||
bool create (const std::wstring &filepath)
|
||||
{
|
||||
try
|
||||
{
|
||||
destroy ();
|
||||
if (filepath.empty ()) return false;
|
||||
m_hPriFile = CreatePriFileInstanceFromPath (filepath.c_str ());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
m_hPriFile = nullptr;
|
||||
}
|
||||
return valid ();
|
||||
}
|
||||
prifile (IStream *pStream) { create (pStream); }
|
||||
prifile (const std::wstring &filepath) { create (filepath); }
|
||||
prifile () = default;
|
||||
void add_search (const std::vector <std::wstring> &arr) const
|
||||
{
|
||||
BYTE *buf = (BYTE *)malloc (sizeof (LPCWSTRLIST) + sizeof (LPWSTR) * arr.size ());
|
||||
reltask release ([&buf] () {
|
||||
if (buf) free (buf);
|
||||
buf = nullptr;
|
||||
});
|
||||
HLPCWSTRLIST hList = (HLPCWSTRLIST)buf;
|
||||
hList->dwLength = arr.size ();
|
||||
for (size_t i = 0; i < hList->dwLength; i ++)
|
||||
{
|
||||
hList->aswArray [i] = arr [i].c_str ();
|
||||
}
|
||||
FindPriResource (m_hPriFile, hList);
|
||||
}
|
||||
void add_search (const std::wstring &arr) const
|
||||
{
|
||||
BYTE buf [sizeof (LPCWSTRLIST) + sizeof (LPWSTR)] = {0};
|
||||
HLPCWSTRLIST hList = (HLPCWSTRLIST)buf;
|
||||
hList->dwLength = 1;
|
||||
hList->aswArray [0] = arr.c_str ();
|
||||
FindPriResource (m_hPriFile, hList);
|
||||
}
|
||||
std::wstring resource (const std::wstring &resname) const
|
||||
{
|
||||
LPWSTR lpstr = nullptr;
|
||||
reltask release ([&lpstr] () {
|
||||
if (lpstr) free (lpstr);
|
||||
lpstr = nullptr;
|
||||
});
|
||||
lpstr = GetPriResource (m_hPriFile, resname.c_str ());
|
||||
return lpstr ? lpstr : L"";
|
||||
}
|
||||
size_t resources (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) const
|
||||
{
|
||||
add_search (resnames);
|
||||
for (auto &it : resnames) output [it] = resource (it);
|
||||
return output.size ();
|
||||
}
|
||||
LPCWSTR last_error () { return PriFileGetLastError (); }
|
||||
std::wstring path (const std::wstring &resname) const { return resource (resname); }
|
||||
size_t paths (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) const { return resources (resnames, output); }
|
||||
std::wstring string (const std::wstring &resname) const { return resource (resname); }
|
||||
size_t strings (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) const { return resources (resnames, output); }
|
||||
} prifilecli;
|
||||
// 注意:此类仅为操作类,如果以 IStream * 来初始化类的话在类销毁时不会释放 IStream *。请在此类实例生命期结束后必须释放 IStream *
|
||||
typedef class prifilebundle
|
||||
{
|
||||
public:
|
||||
struct PRI_INST
|
||||
{
|
||||
// 0b01 语言 0b10 缩放资源 0b11 两者(或者是应用包的资源包)
|
||||
uint8_t type = 0;
|
||||
prifile priinst;
|
||||
bool res_language () const { return type & 0b01; }
|
||||
bool res_scale () const { return type & 0b10; }
|
||||
bool res_both () const { return type & 0b11; }
|
||||
bool is_valid () const { return type & 0b11; }
|
||||
// 类型:0: 无效,不许插入,1:语言资源,2:缩放资源,3:两者都有
|
||||
// 必须插入有效的内容
|
||||
PRI_INST (uint8_t type = 0, IStream *ipri = nullptr):
|
||||
type (type), priinst (ipri) {}
|
||||
};
|
||||
private:
|
||||
std::vector <PRI_INST> prifiles;
|
||||
std::map <uint8_t, PRI_INST *> mappri;
|
||||
public:
|
||||
prifilebundle () { prifiles.reserve (3); }
|
||||
// 类型:0: 无效,不许插入,1:语言资源,2:缩放资源,3:两者都有
|
||||
// 插入 3 类型的不会顶替 1 和 2 类型,只会顶替 3 类型。所以类中储存的实例最多只有三个。
|
||||
// 必须指定有效类型。如果 prifile 为 nullptr,则以位置相应类型的 pri 要执行销毁。
|
||||
bool set (uint8_t type, IStream *prifile)
|
||||
{
|
||||
uint8_t realt = type & 0b11;
|
||||
if (!type) return false;
|
||||
if (mappri.find (type & 0b11) != mappri.end ())
|
||||
{
|
||||
auto &prii = mappri [realt];
|
||||
prii->priinst.destroy ();
|
||||
if (prifile) prii->priinst.create (prifile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!prifile) return false;
|
||||
prifiles.emplace_back (realt, prifile);
|
||||
for (auto &it : prifiles)
|
||||
{
|
||||
if (it.type == realt) { mappri [realt] = ⁢ break; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 类型:0: 无效,不许插入,1:语言资源,2:缩放资源,3:两者都有
|
||||
// 失败返回 nullptr
|
||||
// 注意:获取 1 和 2 对应的 pri 资源,如果不存在会尝试返回 3 的资源。
|
||||
// mustreturn 指的是必须返回一个 pri 实例,不管是否符合。这是个没办法的办法
|
||||
prifile *get (uint8_t type, bool mustreturn = false)
|
||||
{
|
||||
type &= 0b11;
|
||||
auto it = mappri.find (type);
|
||||
if (it != mappri.end ()) return &it->second->priinst;
|
||||
if (type != 0b11)
|
||||
{
|
||||
it = mappri.find (0b11);
|
||||
if (it != mappri.end ()) return &it->second->priinst;
|
||||
}
|
||||
if (!prifiles.empty () && mustreturn) return &prifiles.front ().priinst;
|
||||
return nullptr;
|
||||
}
|
||||
void add_search (const std::vector <std::wstring> &arr)
|
||||
{
|
||||
std::vector <std::wstring> strresname;
|
||||
std::vector <std::wstring> pathresname;
|
||||
for (auto &it : arr)
|
||||
{
|
||||
if (IsMsResourcePrefix (it.c_str ())) strresname.push_back (it);
|
||||
else pathresname.push_back (it);
|
||||
}
|
||||
auto langpri = get (1, true);
|
||||
auto scalepri = get (2, true);
|
||||
if (langpri) langpri->add_search (strresname);
|
||||
if (scalepri) scalepri->add_search (pathresname);
|
||||
}
|
||||
void add_search (const std::wstring &resname)
|
||||
{
|
||||
if (IsMsResourcePrefix (resname.c_str ()))
|
||||
{
|
||||
auto langpri = get (1, true);
|
||||
if (langpri) langpri->add_search (resname);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scalepri = get (2, true);
|
||||
if (scalepri) scalepri->add_search (resname);
|
||||
}
|
||||
}
|
||||
std::wstring resource (const std::wstring &resname)
|
||||
{
|
||||
if (IsMsResourcePrefix (resname.c_str ()))
|
||||
{
|
||||
auto langpri = get (1, true);
|
||||
if (langpri) return langpri->resource (resname);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scalepri = get (2, true);
|
||||
if (scalepri) return scalepri->resource (resname);
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
size_t resources (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output)
|
||||
{
|
||||
add_search (resnames);
|
||||
for (auto &it : resnames) output [it] = resource (it);
|
||||
return output.size ();
|
||||
}
|
||||
std::wstring path (const std::wstring &resname) { return resource (resname); }
|
||||
size_t paths (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) { return resources (resnames, output); }
|
||||
std::wstring string (const std::wstring &resname) { return resource (resname); }
|
||||
size_t strings (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) { return resources (resnames, output); }
|
||||
void destroy ()
|
||||
{
|
||||
mappri.clear ();
|
||||
prifiles.clear ();
|
||||
}
|
||||
} prifilebcli;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
BIN
priformatcli/priformatcli.rc
Normal file
BIN
priformatcli/priformatcli.rc
Normal file
Binary file not shown.
191
priformatcli/priformatcli.vcxproj
Normal file
191
priformatcli/priformatcli.vcxproj
Normal file
@@ -0,0 +1,191 @@
|
||||
<?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>{33D91B58-1981-4A3C-B4D1-86EE406CDE12}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>priformatcli</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</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>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</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>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</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;_USRDLL;PRIFORMATCLI_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;PRIFORMATCLI_EXPORTS;%(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;_USRDLL;PRIFORMATCLI_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</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;_USRDLL;PRIFORMATCLI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="localeex.h" />
|
||||
<ClInclude Include="mpstr.h" />
|
||||
<ClInclude Include="nstring.h" />
|
||||
<ClInclude Include="prifile.h" />
|
||||
<ClInclude Include="priformatcli.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="syncutil.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="themeinfo.h" />
|
||||
<ClInclude Include="typestrans.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="priformatcli.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="priformatcli.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
71
priformatcli/priformatcli.vcxproj.filters
Normal file
71
priformatcli/priformatcli.vcxproj.filters
Normal file
@@ -0,0 +1,71 @@
|
||||
<?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>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="priformatcli.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="prifile.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="typestrans.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mpstr.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="localeex.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nstring.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="themeinfo.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="syncutil.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="priformatcli.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="priformatcli.rc">
|
||||
<Filter>资源文件</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
14
priformatcli/resource.h
Normal file
14
priformatcli/resource.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by priformatcli.rc
|
||||
|
||||
// 新对象的下一组默认值
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
8
priformatcli/stdafx.cpp
Normal file
8
priformatcli/stdafx.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// priformatcli.pch 将作为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
|
||||
//而不是在此文件中引用
|
||||
16
priformatcli/stdafx.h
Normal file
16
priformatcli/stdafx.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是经常使用但不常更改的
|
||||
// 特定于项目的包含文件
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
|
||||
// Windows 头文件:
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
|
||||
// TODO: 在此处引用程序需要的其他头文件
|
||||
124
priformatcli/syncutil.h
Normal file
124
priformatcli/syncutil.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
class CriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION m_csection;
|
||||
public:
|
||||
CriticalSection (DWORD spinCount = 4000) { InitializeCriticalSectionAndSpinCount (&m_csection, spinCount); }
|
||||
CriticalSection (const CriticalSection &) = delete;
|
||||
CriticalSection &operator = (const CriticalSection &) = delete;
|
||||
~CriticalSection () { DeleteCriticalSection (&m_csection); }
|
||||
void Lock () { EnterCriticalSection (&m_csection); }
|
||||
void Unlock () { LeaveCriticalSection (&m_csection); }
|
||||
bool TryLock () { return TryEnterCriticalSection (&m_csection) != 0; }
|
||||
class ScopedLock
|
||||
{
|
||||
public:
|
||||
explicit ScopedLock (CriticalSection &cs): m_cs (cs) { m_cs.Lock (); }
|
||||
~ScopedLock () { m_cs.Unlock (); }
|
||||
ScopedLock (const ScopedLock &) = delete;
|
||||
ScopedLock &operator = (const ScopedLock &) = delete;
|
||||
private:
|
||||
CriticalSection& m_cs;
|
||||
};
|
||||
};
|
||||
|
||||
#define CreateScopedLock(_obj_cs_) CriticalSection::ScopedLock _obj_cs_##sl (_obj_cs_)
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
ref struct TaskStructEvent
|
||||
{
|
||||
typedef array <Object ^> args;
|
||||
typedef void (*eventfunc) (... args ^args);
|
||||
eventfunc post;
|
||||
args ^postargs;
|
||||
public:
|
||||
TaskStructEvent (
|
||||
eventfunc prefunc,
|
||||
args ^preargs,
|
||||
eventfunc postfunc,
|
||||
args ^postargs
|
||||
): post (postfunc), postargs (postargs)
|
||||
{
|
||||
if (prefunc == nullptr) {
|
||||
#pragma message("警告:预处理函数指针为空,可能跳过初始化操作")
|
||||
}
|
||||
if (prefunc)
|
||||
{
|
||||
if (preargs)
|
||||
{
|
||||
#pragma region 参数验证示例
|
||||
/*
|
||||
实际项目中应添加具体类型检查,例如:
|
||||
ValidateArgsType<Button^>(preargs);
|
||||
*/
|
||||
#pragma endregion
|
||||
prefunc (preargs);
|
||||
}
|
||||
else prefunc (gcnew args {});
|
||||
}
|
||||
}
|
||||
~TaskStructEvent ()
|
||||
{
|
||||
if (post == nullptr)
|
||||
{
|
||||
#pragma message("警告:后处理函数指针为空,资源可能无法正确释放")
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (postargs) { post (postargs); }
|
||||
else { post (gcnew args {}); }
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
#pragma message("注意:后处理中的异常需手动处理")
|
||||
}
|
||||
}
|
||||
};
|
||||
#define CreateStructEvent(_varname_taskname_, _func_construct_, _args_construct_, _func_destruct_, _args_destruct_) \
|
||||
TaskStructEvent _varname_taskname_ ( \
|
||||
_func_construct_, \
|
||||
_args_construct_, \
|
||||
_func_destruct_, \
|
||||
_args_destruct_ \
|
||||
)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
template <typename PreCallback, typename PostCallback> class ScopedEvent
|
||||
{
|
||||
public:
|
||||
ScopedEvent (PreCallback &&pre, PostCallback &&post)
|
||||
: m_post (std::forward <PostCallback> (post))
|
||||
{
|
||||
static_assert (
|
||||
std::is_constructible <std::function <void ()>, PreCallback>::value,
|
||||
"预处理回调必须可转换为 void () 类型"
|
||||
);
|
||||
|
||||
if (pre) { pre (); }
|
||||
}
|
||||
~ScopedEvent () noexcept
|
||||
{
|
||||
if (m_post) { m_post (); }
|
||||
}
|
||||
ScopedEvent (const ScopedEvent &) = delete;
|
||||
ScopedEvent &operator = (const ScopedEvent &) = delete;
|
||||
ScopedEvent (ScopedEvent &&) = default;
|
||||
ScopedEvent &operator =(ScopedEvent &&) = default;
|
||||
private:
|
||||
PostCallback m_post;
|
||||
};
|
||||
template <typename PreFunc, typename PostFunc> auto make_scoped_event (PreFunc &&pre, PostFunc &&post)
|
||||
{
|
||||
return ScopedEvent <PreFunc, PostFunc> (
|
||||
std::forward <PreFunc> (pre),
|
||||
std::forward <PostFunc> (post)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
8
priformatcli/targetver.h
Normal file
8
priformatcli/targetver.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
|
||||
|
||||
// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
|
||||
// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
40
priformatcli/themeinfo.h
Normal file
40
priformatcli/themeinfo.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
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;
|
||||
}
|
||||
187
priformatcli/typestrans.h
Normal file
187
priformatcli/typestrans.h
Normal file
@@ -0,0 +1,187 @@
|
||||
#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>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#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
|
||||
}
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user