Update Shell

Fix Package Store Logo Read
This commit is contained in:
Bruce
2025-11-26 23:53:09 +08:00
parent a70b0547bd
commit a3b3b097b2
12 changed files with 715 additions and 442 deletions

Binary file not shown.

View File

@@ -183,7 +183,7 @@ public ref class SplashForm: public System::Windows::Forms::Form
picbox->Image = img;
}
}
catch (...) { }
catch (...) {}
if (splashimg) picbox->Image = splashimg;
if (backcolor != Drawing::Color::Transparent)
{
@@ -434,6 +434,512 @@ HRESULT UpdateAppxPackageFromPath (
detailmsg = lpmsg ? lpmsg : L"";
return hr;
}
bool IsWindows10 ()
{
#pragma warning(push)
#pragma warning(disable:4996)
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
osvi.dwMajorVersion = 10;
DWORDLONG conditionMask = 0;
VER_SET_CONDITION (conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
if (VerifyVersionInfoW (&osvi, VER_MAJORVERSION, conditionMask)) return TRUE;
DWORD error = GetLastError ();
return (error == ERROR_OLD_WIN_VERSION) ? FALSE : FALSE;
#pragma warning(pop)
}
void ActivateApp (Object ^appid)
{
auto res = ActivateAppxApplication (MPStringToStdW (appid->ToString ()));
}
[ComVisible (true)]
public ref class AppListWnd: public System::Windows::Forms::Form
{
public:
using WebBrowser = System::Windows::Forms::WebBrowser;
using Timer = System::Windows::Forms::Timer;
[ComVisible (true)]
ref class IBridge
{
private:
AppListWnd ^wndinst = nullptr;
public:
IBridge (AppListWnd ^wnd): wndinst (wnd) {}
ref class _I_HResult
{
private:
HRESULT hr = S_OK;
String ^errorcode = "";
String ^detailmsg = "";
public:
_I_HResult (HRESULT hres)
{
hr = hres;
detailmsg = CStringToMPString (HResultToMessage (hres));
}
_I_HResult (HRESULT hres, String ^error, String ^message)
{
hr = hres;
errorcode = error;
detailmsg = message;
}
property HRESULT HResult { HRESULT get () { return hr; }}
property String ^ErrorCode { String ^get () { return errorcode; }}
property String ^Message { String ^get () { return detailmsg; }}
property bool Succeeded { bool get () { return SUCCEEDED (hr); }}
property bool Failed { bool get () { return FAILED (hr); }}
};
ref class _I_System
{
private:
AppListWnd ^wndinst = nullptr;
public:
ref class _I_UI
{
private:
AppListWnd ^wndinst = nullptr;
public:
ref struct _I_UI_Size
{
private:
int m_width = 0;
int m_height = 0;
public:
property int width { int get () { return m_width; } }
property int height { int get () { return m_height; }}
property int Width { int get () { return m_width; } }
property int Height { int get () { return m_height; }}
int getWidth () { return m_width; }
int getHeight () { return m_height; }
_I_UI_Size (int w, int h): m_width (w), m_height (h) {}
};
_I_UI (AppListWnd ^wnd): wndinst (wnd) {}
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
property _I_UI_Size ^WndSize { _I_UI_Size ^get () { return gcnew _I_UI_Size (wndinst->Width, wndinst->Height); } }
property _I_UI_Size ^ClientSize { _I_UI_Size ^get () { auto cs = wndinst->ClientSize; return gcnew _I_UI_Size (cs.Width, cs.Height); } }
property String ^ThemeColor { String ^get () { return ColorToHtml (GetDwmThemeColor ()); } }
property bool DarkMode { bool get () { return IsAppInDarkMode (); }}
property String ^HighContrast
{
String ^get ()
{
auto highc = GetHighContrastTheme ();
switch (highc)
{
case HighContrastTheme::None: return "none";
break;
case HighContrastTheme::Black: return "black";
break;
case HighContrastTheme::White: return "white";
break;
case HighContrastTheme::Other: return "high";
break;
default: return "none";
break;
}
return "none";
}
}
};
ref class _I_Resources
{
public:
String ^GetById (unsigned int uiResId) { return GetRCStringCli (uiResId); }
unsigned ToId (String ^lpResName)
{
auto it = g_nameToId.find (MPStringToStdA (lpResName));
return (it != g_nameToId.end ()) ? it->second : 0;
}
String ^ToName (unsigned int ulResId)
{
for (auto &it : g_nameToId) { if (it.second == ulResId) return CStringToMPString (it.first); }
return "";
}
String ^GetByName (String ^lpResId) { return GetById (ToId (lpResId)); }
String ^operator [] (unsigned int uiResId) { return GetRCStringCli (uiResId); }
};
private:
_I_UI ^ui = gcnew _I_UI (wndinst);
_I_Resources ^ires = gcnew _I_Resources ();
public:
_I_System (AppListWnd ^wnd): wndinst (wnd) {}
property _I_UI ^UI { _I_UI ^get () { return ui; } }
property _I_Resources ^Resources { _I_Resources ^get () { return ires; } }
property bool IsWindows10
{
bool get ()
{
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
osvi.dwMajorVersion = 10;
DWORDLONG conditionMask = 0;
VER_SET_CONDITION (conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
if (VerifyVersionInfoW (&osvi, VER_MAJORVERSION, conditionMask)) return TRUE;
DWORD error = GetLastError ();
return (error == ERROR_OLD_WIN_VERSION) ? FALSE : FALSE;
}
}
};
ref class _I_IEFrame
{
private:
AppListWnd ^wndinst = nullptr;
public:
_I_IEFrame (AppListWnd ^wnd): wndinst (wnd) {}
property int Scale
{
int get () { return wndinst->PageScale; }
void set (int value) { return wndinst->PageScale = value; }
}
property int Version { int get () { return GetInternetExplorerVersionMajor (); }}
String ^ParseHtmlColor (String ^color)
{
auto dcolor = Drawing::ColorTranslator::FromHtml (color);
{
rapidjson::Document doc;
doc.SetObject ();
auto &alloc = doc.GetAllocator ();
doc.AddMember ("r", (uint16_t)dcolor.R, alloc);
doc.AddMember ("g", (uint16_t)dcolor.G, alloc);
doc.AddMember ("b", (uint16_t)dcolor.B, alloc);
doc.AddMember ("a", (uint16_t)dcolor.A, alloc);
rapidjson::StringBuffer buffer;
rapidjson::Writer <rapidjson::StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return CStringToMPString (conv.from_bytes (utf8));
}
return "{}";
}
};
ref class _I_String
{
public:
ref class _I_NString
{
public:
bool NEquals (String ^l, String ^r) { return IsNormalizeStringEquals (MPStringToPtrW (l), MPStringToPtrW (r)); }
bool Empty (String ^l) { return IsNormalizeStringEmpty (MPStringToStdW (l)); }
int Compare (String ^l, String ^r) { return NormalizeStringCompare (MPStringToPtrW (l), MPStringToPtrW (r)); }
int Length (String ^l) { return GetNormalizeStringLength (MPStringToStdW (l)); }
};
private:
_I_NString ^nstr = gcnew _I_NString ();
public:
property _I_NString ^NString { _I_NString ^get () { return nstr; }}
String ^Trim (String ^src)
{
std::wstring csrc = MPStringToStdW (src);
return CStringToMPString (::StringTrim (csrc));
}
String ^ToLower (String ^src) { return CStringToMPString (StringToLower (MPStringToStdW (src))); }
String ^ToUpper (String ^src) { return CStringToMPString (StringToUpper (MPStringToStdW (src))); }
String ^Format (String ^fmt, ... array <Object ^> ^args) { return FormatString (fmt, args); }
String ^FormatInnerHTML (String ^fmt, ... array <Object ^> ^args)
{
std::wstring ihtml = EscapeToInnerXml (MPStringToStdW (fmt));
auto pih = CStringToMPString (ihtml);
auto newargs = gcnew array <Object ^> (args->Length);
for (size_t i = 0; i < args->Length; i ++)
{
auto %p = newargs [i];
p = Format ("<span>{0}</span>", EscapeToInnerXml (Format ("{0}", args [i])));
}
return Format (pih, newargs);
}
};
ref class _I_Package
{
public:
String ^GetPackagesToJson ()
{
rapidjson::Document doc;
doc.SetArray ();
auto &alloc = doc.GetAllocator ();
for (auto &it : g_pkginfo)
{
rapidjson::Value member (rapidjson::kStringType);
member.SetString (ws2utf8 (it.filepath).c_str (), alloc);
doc.PushBack (member, alloc);
}
rapidjson::StringBuffer buffer;
rapidjson::Writer <rapidjson::StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return CStringToMPString (conv.from_bytes (utf8));
}
String ^GetPackageInfoToJson (String ^filepath)
{
std::wstring fpath = MPStringToStdW (filepath);
for (auto &it : g_pkginfo)
{
if (PathEquals (it.filepath, fpath))
{
return CStringToMPString (it.parseJson ());
}
}
return "{}";
}
String ^GetCapabilityDisplayName (String ^capabilityName)
{
return CStringToMPString (GetPackageCapabilityDisplayName (MPStringToStdW (capabilityName)));
}
_I_HResult ^GetPackageInstallResult (String ^filepath)
{
std::wstring path = MPStringToStdW (filepath);
if (g_pkgresult.find (path) == g_pkgresult.end ()) return nullptr;
auto &pres = g_pkgresult.at (path);
return gcnew _I_HResult (
pres.result,
CStringToMPString (pres.error),
CStringToMPString (pres.reason)
);
}
void Activate (String ^appid) { ActivateApp (appid); }
};
ref class _I_Window
{
private:
AppListWnd ^wndinst = nullptr;
public:
_I_Window (AppListWnd ^wnd): wndinst (wnd) {}
Object ^CallEvent (String ^name, ... array <Object ^> ^args) { return wndinst->CallEvent (name, args [0]); }
};
private:
_I_System ^system = gcnew _I_System (wndinst);
_I_IEFrame ^ieframe = gcnew _I_IEFrame (wndinst);
_I_String ^str = gcnew _I_String ();
_I_Package ^pkg = gcnew _I_Package ();
_I_Window ^wnd = gcnew _I_Window (wndinst);
public:
property _I_System ^System { _I_System ^get () { return system; }}
property _I_IEFrame ^IEFrame { _I_IEFrame ^get () { return ieframe; }}
property _I_String ^String { _I_String ^get () { return str; }}
property _I_Package ^Package { _I_Package ^get () { return pkg; }}
property _I_Window ^Window { _I_Window ^get () { return wnd; }}
};
private:
WebBrowser ^webui = nullptr;
Timer ^showtimer = gcnew Timer ();
Timer ^hidetimer = gcnew Timer ();
int aminedelay = 150;
int framedelay = 25;
double movelen = 10 * DPI;
int frametotal = aminedelay / framedelay;
double movestep = movelen / (double)frametotal;
int framenow = 0;
int finaltop = 0;
public:
property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } }
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
AppListWnd ()
{
this->Visible = false;
this->DoubleBuffered = true;
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->ShowInTaskbar = false;
this->TopMost = true;
this->Size = System::Drawing::Size (392 * DPI, 494 * DPI);
if (IsWindows10 ()) this->MinimumSize = System::Drawing::Size (392 * DPI, 226 * DPI);
else this->MinimumSize = System::Drawing::Size (392 * DPI, 129 * DPI);
if (IsWindows10 ()) this->MaximumSize = System::Drawing::Size (392 * DPI, 522 * DPI);
else this->MaximumSize = System::Drawing::Size (368 * DPI, 394 * DPI);
this->Text = GetRCStringCli (IDS_APPLIST_WINTITLE);
webui = gcnew System::Windows::Forms::WebBrowser ();
webui->Dock = System::Windows::Forms::DockStyle::Fill;
this->Controls->Add (webui);
webui->Visible = false;
webui->ObjectForScripting = gcnew IBridge (this);
this->webui->DocumentCompleted += gcnew System::Windows::Forms::WebBrowserDocumentCompletedEventHandler (this, &AppListWnd::OnDocumentCompleted);
this->Load += gcnew EventHandler (this, &AppListWnd::OnCreate);
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen;
this->Deactivate += gcnew EventHandler (this, &AppListWnd::OnDeactivate);
webui->Navigate (CStringToMPString (CombinePath (GetProgramRootDirectoryW (), L"html\\applist.html")));
showtimer->Interval = framedelay;
hidetimer->Interval = framedelay;
showtimer->Tick += gcnew EventHandler (this, &AppListWnd::OnTick_ShowTimer);
hidetimer->Tick += gcnew EventHandler (this, &AppListWnd::OnTick_HideTimer);
this->Opacity = 0;
}
protected:
void OnCreate (System::Object ^sender, System::EventArgs ^e) {}
void OnDocumentCompleted (Object ^sender, System::Windows::Forms::WebBrowserDocumentCompletedEventArgs ^e)
{
if (e->Url->ToString () == webui->Url->ToString ())
{
ExecScript ("Windows.UI.DPI.mode = 1");
ExecScript ("Bridge.Frame.scale = Bridge.Frame.scale * Bridge.UI.dpi");
InvokeCallScriptFunction ("setWindows10Style", IsWindows10 ());
size_t cnt = 0;
for (auto &it : g_pkginfo)
{
for (auto &app : it.applications)
{
std::wstring launchid = it.identity.package_family_name + L'!' + app [L"Id"];
auto &color = app [L"BackgroundColor"];
std::wnstring displayName = app [L"DisplayName"];
if (displayName.empty ()) displayName = app [L"ShortName"];
auto &logo = app [L"Square44x44Logo"];
InvokeCallScriptFunction (
"addAppToList",
CStringToMPString (displayName),
CStringToMPString (logo),
CStringToMPString (launchid),
CStringToMPString (color)
);
cnt ++;
}
}
if (cnt == 0) this->Close ();
{
bool isWin10 = IsWindows10 ();
size_t height = ((cnt) * (isWin10 ? 50 : 60) * DPI) + (isWin10 ? 206 : 120) * DPI;
if (height < (isWin10 ? 522 : 394) * DPI) this->Height = height;
else this->Height = 522 * DPI;
this->Left = (GetScreenWidth () - this->Width) / 2;
this->Top = (GetScreenHeight () - this->Height) / 2;
}
finaltop = this->Top;
this->Top -= movelen;
webui->Visible = true;
this->Visible = true;
}
}
void OnPress_Cancel ()
{
if (!this->IsHandleCreated) return;
if (InvokeRequired) this->Invoke (gcnew Action (this, &AppListWnd::HideAmine));
else this->HideAmine ();
return;
}
void OnPress_AppItem ()
{
OnPress_Cancel ();
}
void OnDeactivate (Object ^sender, EventArgs ^e)
{
OnPress_Cancel ();
}
void OnTick_ShowTimer (Object ^sender, EventArgs ^e)
{
framenow ++;
if (framenow > frametotal)
{
showtimer->Stop ();
this->Top = finaltop;
this->Opacity = 1;
}
else
{
this->Top = finaltop + movestep * (frametotal - framenow);
this->Opacity = framenow / (double)frametotal;
}
}
void OnTick_HideTimer (Object ^sender, EventArgs ^e)
{
framenow ++;
if (framenow > frametotal)
{
showtimer->Stop ();
this->Opacity = 0;
this->Close ();
}
else
{
this->Opacity = 1.0 - framenow / (double)frametotal;
}
}
public:
static void DisplayWindow ()
{
auto wnd = gcnew AppListWnd ();
wnd->ShowAmine ();
}
Object ^CallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try { return this->webui->Document->InvokeScript (lpFuncName, alpParams); }
catch (Exception ^e) {}
return nullptr;
}
Object ^CallScriptFunction (String ^lpScriptName)
{
try { return this->webui->Document->InvokeScript (lpScriptName); }
catch (Exception ^e) {}
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, array <Object ^> ^, Object ^> (this, &AppListWnd::CallScriptFunction), lpFuncName, alpParams);
else return CallScriptFunction (lpFuncName, alpParams);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpScriptName)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, Object ^> (this, &AppListWnd::CallScriptFunction), lpScriptName);
else return CallScriptFunction (lpScriptName);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^ExecScript (... array <Object ^> ^alpScript) { return InvokeCallScriptFunction ("eval", alpScript); }
Object ^CallEvent (String ^funcName, Object ^e)
{
std::wstring fname = MPStringToStdW (funcName);
if (IsNormalizeStringEquals (fname.c_str (), L"OnPress_CancelButton")) OnPress_Cancel ();
else if (IsNormalizeStringEquals (fname.c_str (), L"OnPress_AppItem")) OnPress_AppItem ();
return nullptr;
}
property int PageScale
{
int get ()
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return 0;
VARIANT v;
VariantInit (&v);
hr = web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DODEFAULT, nullptr, &v);
if (FAILED (hr) || v.vt != VT_I4) return 0;
int val = v.lVal;
VariantClear (&v);
return val;
}
void set (int value)
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return;
VARIANT v;
VariantInit (&v);
v.vt = VT_I4;
v.lVal = value;
web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &v, nullptr);
}
}
void ShowAmine ()
{
this->Show ();
hidetimer->Stop ();
showtimer->Start ();
}
void HideAmine ()
{
framenow = 0;
showtimer->Stop ();
hidetimer->Start ();
}
};
[ComVisible (true)]
public ref class MainHtmlWnd: public System::Windows::Forms::Form
{
@@ -506,13 +1012,13 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
property double DPI { double get () { return DPIPercent * 0.01; }}
property _I_UI_Size ^WndSize { _I_UI_Size ^get () { return gcnew _I_UI_Size (wndinst->Width, wndinst->Height); } }
property _I_UI_Size ^ClientSize { _I_UI_Size ^get () { auto cs = wndinst->ClientSize; return gcnew _I_UI_Size (cs.Width, cs.Height); } }
property String ^SplashImage
{
String ^get ()
{
auto uri = gcnew Uri (CStringToMPString (wndinst->GetSuitSplashImage ()));
property String ^SplashImage
{
String ^get ()
{
auto uri = gcnew Uri (CStringToMPString (wndinst->GetSuitSplashImage ()));
return uri->AbsoluteUri;
}
}
}
property String ^SplashBackgroundColor { String ^get () { return CStringToMPString (g_vemani.splash_screen_backgroundcolor (L"App")); } }
void ShowSplash () { if (wndinst->SplashScreen->IsHandleCreated) wndinst->SplashScreen->Show (); else wndinst->SplashScreen->ReInit (); }
@@ -553,7 +1059,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
}
String ^ToName (unsigned int ulResId)
{
for (auto &it : g_nameToId) {if (it.second == ulResId) return CStringToMPString (it.first);}
for (auto &it : g_nameToId) { if (it.second == ulResId) return CStringToMPString (it.first); }
return "";
}
String ^GetByName (String ^lpResId) { return GetById (ToId (lpResId)); }
@@ -568,7 +1074,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
property UINT16 Minor { UINT16 get () { return minor; } void set (UINT16 value) { minor = value; } }
property UINT16 Build { UINT16 get () { return build; } void set (UINT16 value) { build = value; } }
property UINT16 Revision { UINT16 get () { return revision; } void set (UINT16 value) { revision = value; } }
property array <UINT16> ^Data
property array <UINT16> ^Data
{
array <UINT16> ^get ()
{
@@ -736,7 +1242,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
ref class _I_String
{
public:
ref class _I_NString
ref class _I_NString
{
public:
bool NEquals (String ^l, String ^r) { return IsNormalizeStringEquals (MPStringToPtrW (l), MPStringToPtrW (r)); }
@@ -764,7 +1270,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
for (size_t i = 0; i < args->Length; i ++)
{
auto %p = newargs [i];
p = Format ("<span>{0}</span>", EscapeToInnerXml (Format ("{0}", args [i])));
p = Format ("<span>{0}</span>", EscapeToInnerXml (Format ("{0}", args [i])));
}
return Format (pih, newargs);
}
@@ -831,7 +1337,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
public:
_I_Window (MainHtmlWnd ^wnd): wndinst (wnd) {}
Object ^CallEvent (String ^name, ... array <Object ^> ^args) { return wndinst->CallEvent (name, args [0]); }
};
@@ -900,7 +1406,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
try { this->Icon = System::Drawing::Icon::FromHandle (IntPtr (g_hIconMain.hIcon)); }
catch (...) {}
}
this->Text = rcString (IDS_WINTITLE);
this->Text = GetRCStringCli (IDS_WINTITLE);
this->ResumeLayout (false);
webui->ObjectForScripting = gcnew IBridge (this);
this->webui->DocumentCompleted += gcnew System::Windows::Forms::WebBrowserDocumentCompletedEventHandler (this, &MainHtmlWnd::OnDocumentCompleted);
@@ -988,7 +1494,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
String ^btn2 = GetRCStringCli (IDS_PREINSTALL_CANCEL);
if (g_pkginfo.size () == 1)
{
try
try
{
const auto &pi = *g_pkginfo.begin ();
const std::wstring
@@ -1204,7 +1710,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
auto &it = g_pkginfo.at (nowinstall);
InvokeCallScriptFunction ("setInstallingPackageInfoMultiple", CStringToMPString (it.filepath));
InvokeCallScriptFunction (
"setInstallingStatus",
"setInstallingStatus",
String::Format (
GetRCStringCli (IDS_INSTALLING_MLOADCER),
nowinstall + 1,
@@ -1222,11 +1728,11 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
);
package_installresult pir;
pir.result = AddAppxPackageFromPath (
it.filepath,
blankdeplist,
DEPOLYOPTION_NONE,
it.filepath,
blankdeplist,
DEPOLYOPTION_NONE,
gcnew InstallProgressCallbackDelegate (this, &MainHtmlWnd::InstallProgressCallbackMultiple),
pir.error,
pir.error,
pir.reason
);
g_pkgresult [it.filepath] = pir;
@@ -1261,6 +1767,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
}
void PackageSuccessInstallCountTask ()
{
return;
System::Threading::Thread::Sleep (System::TimeSpan (0, 0, 5));
this->InvokeClose ();
}
@@ -1325,7 +1832,19 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
}
else if (nequals (current, L"installsuccess"))
{
std::vector <std::wnstring> appids;
for (auto &it : g_pkginfo)
for (auto &it_s : it.applications)
if (!it_s [L"Id"].empty ())
appids.emplace_back (it.identity.package_family_name + L'!' + it_s [L"Id"]);
if (appids.size () == 1)
{
ActivateAppxApplication (appids.at (0));
}
else if (appids.size () > 1)
{
AppListWnd::DisplayWindow ();
}
}
else if (nequals (current, L"installfailed")) this->Close ();
return;
@@ -1348,7 +1867,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
case InstallType::reinstall: {
auto &pi = *g_pkginfo.begin ();
if (pi.applications.size () == 1) ActivateAppxApplication (pi.identity.package_family_name + L"!" + pi.applications.at (0).at (L"Id"));
else AppListWnd::DisplayWindow ();
} break;
default:
case InstallType::normal:
@@ -1357,10 +1876,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form
break;
}
}
else
{
this->Close ();
}
else this->Close ();
return;
}
else if (nequals (current, L"installfailed")) this->Close ();
@@ -1576,7 +2092,7 @@ int APIENTRY wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCm
{
if (pair.first.key == std::wnstring (L"help"))
{
MessageBox (nullptr, GenerateCmdHelper ().c_str (), GetRCStringSW (IDS_WINTITLE).c_str (), 0);
MessageBoxW (nullptr, GenerateCmdHelper ().c_str (), GetRCStringSW (IDS_WINTITLE).c_str (), 0);
return 0;
}
}

View File

@@ -74,7 +74,10 @@ std::map <std::string, unsigned> g_nameToId = {
MAKENAMEIDMAP (IDS_MINHIEHGT),
MAKENAMEIDMAP (IDS_INSTALLING_MLOADCER),
MAKENAMEIDMAP (IDS_FAILED_MSUCCESS),
MAKENAMEIDMAP (IDS_FAILED_STITLE)
MAKENAMEIDMAP (IDS_FAILED_STITLE),
MAKENAMEIDMAP (IDS_APPLIST_WINTITLE),
MAKENAMEIDMAP (IDS_APPLIST_TITLE),
MAKENAMEIDMAP (IDS_APPLIST_CANCEL)
};
#ifdef MAKENAMEIDMAP

Binary file not shown.

View File

@@ -539,44 +539,63 @@ HRESULT CreateToastNoticeWithIStream (LPCWSTR lpIdName, LPCWSTR lpText, HANDLE p
}
HRESULT NoticeGetLastHResult () { return g_lasthr; }
LPCWSTR NoticeGetLastDetailMessage () { return g_lastexc.c_str (); }
HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId)
HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId, LPWSTR *lpException)
{
HRESULT hr;
if (FAILED (hr)) return hr;
IShellLinkW *pShellLinkW = nullptr;
raii reltask1 ([&] () {
if (pShellLinkW) pShellLinkW->Release ();
pShellLinkW = nullptr;
HRESULT &hr = g_lasthr;
destruct relt ([&] () {
if (FAILED (hr))
{
if (lpException && !*lpException)
{
_com_error ex (hr);
g_lastexc = ex.ErrorMessage () ? ex.ErrorMessage () : L"";
*lpException = _wcsdup (g_lastexc.c_str ());
}
}
});
hr = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void **)&pShellLinkW);
if (FAILED (hr)) return hr;
hr = pShellLinkW->SetPath (pszTargetPath); return hr;
IPropertyStore *pPropStore = nullptr;
raii reltask2 ([&] () {
if (pPropStore) pPropStore->Release ();
pPropStore = nullptr;
});
hr = pShellLinkW->QueryInterface (IID_IPropertyStore, (void **)&pPropStore);
if (SUCCEEDED (hr))
if (lpException) *lpException = nullptr;
try
{
PROPVARIANT propvar;
hr = InitPropVariantFromString (pszAppId, &propvar);
hr = CoInitialize (NULL);
if (FAILED (hr)) return hr;
IShellLinkW *pShellLinkW = nullptr;
raii reltask1 ([&] () {
if (pShellLinkW) pShellLinkW->Release ();
pShellLinkW = nullptr;
});
hr = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void **)&pShellLinkW);
if (FAILED (hr)) return hr;
hr = pShellLinkW->SetPath (pszTargetPath);
if (FAILED (hr)) return hr;
IPropertyStore *pPropStore = nullptr;
raii reltask2 ([&] () {
if (pPropStore) pPropStore->Release ();
pPropStore = nullptr;
});
hr = pShellLinkW->QueryInterface (IID_IPropertyStore, (void **)&pPropStore);
if (SUCCEEDED (hr))
{
hr = pPropStore->SetValue (PKEY_AppUserModel_ID, propvar);
if (SUCCEEDED (hr)) hr = pPropStore->Commit ();
PropVariantClear (&propvar);
PROPVARIANT propvar;
hr = InitPropVariantFromString (pszAppId, &propvar);
if (SUCCEEDED (hr))
{
hr = pPropStore->SetValue (PKEY_AppUserModel_ID, propvar);
if (SUCCEEDED (hr)) hr = pPropStore->Commit ();
PropVariantClear (&propvar);
}
}
else pPropStore = nullptr;
IPersistFile *pPersistFile = nullptr;
raii reltask3 ([&] () {
if (pPersistFile) pPersistFile->Release ();
pPersistFile = nullptr;
});
hr = pShellLinkW->QueryInterface (IID_IPersistFile, (void **)&pPersistFile);
if (SUCCEEDED (hr)) hr = pPersistFile->Save (pszShortcutPath, TRUE);
else pPersistFile = nullptr;
return hr;
}
else pPropStore = nullptr;
IPersistFile *pPersistFile = nullptr;
raii reltask3 ([&] () {
if (pPersistFile) pPersistFile->Release ();
pPersistFile = nullptr;
});
hr = pShellLinkW->QueryInterface (IID_IPersistFile, (void **)&pPersistFile);
if (SUCCEEDED (hr)) hr = pPersistFile->Save (pszShortcutPath, TRUE);
else pPersistFile = nullptr;
catch_lasterr (&hr, lpException);
return hr;
}
@@ -646,4 +665,51 @@ HRESULT CreateToastNotice2WithImgBase64 (LPCWSTR lpIdName, LPCWSTR lpTitle, LPCW
if (bytes.size ())
{ if (FAILED (BytesToIStream (bytes, &ist))) ist = nullptr; }
return CreateToastNoticeWithIStream2 (lpIdName, lpTitle, lpText, ist, pfCallback, pCustom, lpExceptMsg);
}
HRESULT CreateMessageDialog (const std::wstring &content, const std::wstring &title, LPWSTR *lpException)
{
auto &hr = g_lasthr;
try
{
auto refcon = ref new Platform::String (content.c_str ());
auto reftit = ref new Platform::String (title.c_str ());
Windows::UI::Popups::MessageDialog ^msgdlg = nullptr;
if (IsNormalizeStringEmpty (title)) msgdlg = ref new Windows::UI::Popups::MessageDialog (refcon);
else msgdlg = ref new Windows::UI::Popups::MessageDialog (refcon, reftit);
msgdlg->ShowAsync ();
return S_OK;
}
catch_lasterr (&hr, lpException);
return hr;
}
HRESULT SimpleMessageDialog (LPCWSTR lpContent, LPCWSTR lpTitle, LPWSTR *lpException)
{
auto &hr = g_lasthr;
try
{
return CreateMessageDialog (
lpContent ? lpContent : L"",
lpTitle ? lpTitle : L"",
lpException
);
}
catch_lasterr (&hr, lpException);
return hr;
}
HRESULT CreateTileNoticifation (LPCWSTR lpAppId, LPCWSTR lpXmlDoc, LPWSTR *lpExMsg)
{
auto &hr = g_lasthr;
try
{
auto refcon = ref new Platform::String (lpXmlDoc ? lpXmlDoc : L"");
auto xmldoc = ref new Windows::Data::Xml::Dom::XmlDocument ();
xmldoc->LoadXml (ref new Platform::String (lpXmlDoc ? lpXmlDoc : L""));
auto tile = ref new Windows::UI::Notifications::TileNotification (xmldoc);
auto tilemgr = Windows::UI::Notifications::TileUpdateManager::CreateTileUpdaterForApplication (ref new Platform::String (lpAppId ? lpAppId : L""));
tilemgr->Update (tile);
return S_OK;
}
catch_lasterr (&hr, lpExMsg);
return hr;
}

View File

@@ -70,7 +70,7 @@ extern "C"
NOTICE_API LPCWSTR NoticeGetLastDetailMessage ();
// 创建快捷方式
// (不用安装程序原生的创建,因为需要 AppUserID 才能使用 Toast 通知,当然这个限制只有 Windows 8.x 有Windows 10 没有这个限制了)
NOTICE_API HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId);
NOTICE_API HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId, LPWSTR *lpException);
// 由 notice.dll 获取到的动态字符串必须由此释放。
NOTICE_API void NoticeApiFreeString (LPWSTR lpstr);
// 创建一个简单的 Toast 通知。支持两段文本和一张图片(图片是 data uri 或者只是 Base64 编码后的字符串,如果不想设置则置 NULL
@@ -80,6 +80,7 @@ extern "C"
// lpText 可以设置为 NULL 或空文本。此时函数的作用与 CreateToastNoticeWithIStream 一致。
// 一些参数作用与 CreateToastNoticeFromXmlDocument 中的同名参数作用一致。
NOTICE_API HRESULT CreateToastNotice2WithImgBase64 (LPCWSTR lpIdName, LPCWSTR lpTitle, LPCWSTR lpText, LPCWSTR lpImgBase64, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
@@ -185,7 +186,14 @@ notice::hresult CreateToastNoticeWithIStream (notice::qcwstring idname, notice::
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring xmlstring, std::function <void ()> callback) { return CreateToastNoticeFromXmlDocument (idname, xmlstring, callback); }
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring text, IStream *imgstream, std::function <void ()> callback = nullptr) { return CreateToastNoticeWithIStream (idname, text, imgstream, callback); }
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text, IStream *imgstream, std::function <void ()> callback = nullptr) { return CreateToastNoticeWithIStream2 (idname, title, text, imgstream, callback); }
HRESULT CreateShortcutWithAppIdW (notice::qcwstring shortcut_path, notice::qcwstring targetpath, notice::qcwstring appid) { return CreateShortcutWithAppIdW (shortcut_path.c_str (), targetpath.c_str (), appid.c_str ()); }
notice::hresult CreateShortcutWithAppIdW (notice::qcwstring shortcut_path, notice::qcwstring targetpath, notice::qcwstring appid)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateShortcutWithAppIdW (shortcut_path.c_str (), targetpath.c_str (), appid.c_str (), &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
HRESULT CreateToastNoticeWithImgBase64 (notice::qcwstring idname, notice::qcwstring text, notice::qcwstring imgbase64, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
@@ -202,4 +210,6 @@ HRESULT CreateToastNotice2WithImgBase64 (notice::qcwstring idname, notice::qcwst
hr.message = exp.get_string ();
return hr;
}
// WinRT API 测试用
#endif

View File

@@ -53,7 +53,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalOptions>/ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NOTICE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NOTICE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAsWinRT>true</CompileAsWinRT>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
@@ -72,7 +72,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalOptions>/ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NOTICE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NOTICE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAsWinRT>true</CompileAsWinRT>
</ClCompile>
<Link>

View File

@@ -28,6 +28,7 @@
#include <shlobj.h>
#include <stdio.h>
#include <shobjidl.h>
#include <comdef.h>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Management::Deployment;

View File

@@ -611,6 +611,23 @@ class package_reader
lpstr = nullptr;
});
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
if (!(lpstr && *lpstr))
{
if (lpstr) free (lpstr);
HANDLE pkg1 = nullptr, pic1 = nullptr;
destruct relp1 ([&pic1, &pkg1] () {
if (pic1) DestroyAppxFileStream (pic1);
if (pkg1) DestroyAppxFileStream (pkg1);
pkg1 = nullptr;
pic1 = nullptr;
});
pkg1 = GetAppxBundleApplicationPackageFile (hReader);
if (pkg1)
{
pic1 = GetFileFromPayloadPackage (pkg1, logo ().c_str ());
lpstr = StreamToBase64W (pic1, nullptr, 0, nullptr);
}
}
return lpstr ? lpstr : L"";
} break;
}

View File

@@ -7,7 +7,14 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="libs/winjs/2.0/css/ui-light.css">
<script src="js/bridge.js"></script>
<script type="text/javascript" src="js/module.js"></script>
<script type="text/javascript" src="js/polyfill-ie.js"></script>
<script type="text/javascript" src="js/bridge.js"></script>
<script type="text/javascript" src="js/dpimodes.js"></script>
<script type="text/javascript" src="js/resources.js"></script>
<script type="text/javascript" src="js/event.js"></script>
<script type="text/javascript" src="js/load.js"></script>
<script type="text/javascript" src="js/init.js"></script>
<style>
html,
body {
@@ -35,6 +42,7 @@
.applist-font-title {
color: black;
font-size: 11pt;
font-weight: normal;
}
.applist-font-text {
@@ -42,6 +50,7 @@
font-size: 11pt;
word-wrap: break-word;
overflow-wrap: break-word;
font-weight: normal;
}
.applist-window {
@@ -131,6 +140,7 @@
.applist-item-divide {
width: 12px;
min-width: 12px;
height: 100%;
background-color: transparent;
}
@@ -167,6 +177,7 @@
text-overflow: ellipsis;
max-height: 3.9em;
line-height: 1.3em;
font-weight: normal;
}
.applist-btn-cancel {
@@ -192,6 +203,7 @@
.win10 .applist-font-title {
font-size: 13pt;
font-weight: normal;
}
.win10.applist-window {
@@ -225,10 +237,12 @@
.win10 .applist-item-divide {
width: 12px;
min-width: 12px;
}
.win10 .applist-item-title {
padding-top: 5pt;
font-weight: normal;
}
</style>
</head>
@@ -247,12 +261,12 @@
</div>
<div class="applist-window win10">
<div class="applist-title">
<span class="applist-font-title">你要如何打开这个文件?</span>
<span class="applist-font-title" data-res-byname="IDS_APPLIST_TITLE"></span>
</div>
<div class="applist-listview">
</div>
<div class="applist-control">
<button class="applist-btn-cancel win-commandbutton div-button-size div-std-button-center" onclick="EventCancelWindow()" tabindex="0">Cancel</button>
<button class="applist-btn-cancel win-commandbutton div-button-size div-std-button-center" onclick="Bridge.Frame.callEvent ('OnPress_CancelButton')" tabindex="0" data-res-byname="IDS_APPLIST_CANCEL"></button>
</div>
</div>
</div>
@@ -336,6 +350,13 @@
inode.logo = logo;
inode.appid = appid;
inode.color = color;
item.itemInfo = inode;
item.addEventListener("click", function() {
setTimeout(function() {
external.Package.activate(appid);
Bridge.Frame.callEvent("OnPress_AppItem", appid);
});
});
return item;
}
@@ -350,6 +371,20 @@
add: addItem
}
};
global.addAppToList = function(title, logo, appid, color) {
var item = createItem(title, logo, appid, color);
addItem(item);
};
function setWindows10Style(bIsSet) {
var applist = document.querySelector(".applist-window");
if (bIsSet) {
if (!applist.classList.contains("win10")) applist.classList.add("win10");
} else {
if (applist.classList.contains("win10")) applist.classList.remove("win10");
}
}
global.setWindows10Style = setWindows10Style;
})(this);
</script>
</body>

View File

@@ -1,376 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动画效果测试</title>
<script type="text/javascript" src="js/module.js"></script>
<script type="text/javascript" src="js/polyfill-ie.js"></script>
<link rel="stylesheet" href="libs/winjs/2.0/css/ui-light.css">
<script type="text/javascript" src="libs/winjs/2.0/js/base.js"></script>
<script type="text/javascript" src="libs/winjs/2.0/js/ui.js"></script>
<script type="text/javascript" src="js/animation.js"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
padding: 20px;
overflow-x: auto;
overflow-y: auto;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 30px;
padding: 20px;
background: linear-gradient(135deg, #0067b8, #004e8c);
color: white;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 2.5rem;
margin-bottom: 10px;
}
.description {
font-size: 1.1rem;
max-width: 800px;
margin: 0 auto;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.control-group {
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
}
.control-group h3 {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
color: #0067b8;
}
.demo-area {
display: flex;
flex-direction: column;
align-items: center;
margin: 15px 0;
flex-grow: 1;
}
.demo-element {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #0067b8, #00a4ef);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
position: relative;
transition: all 0.3s;
}
.demo-element::after {
content: "动画元素";
font-size: 0.9rem;
text-align: center;
padding: 5px;
}
.animation-buttons {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
width: 100%;
}
button {
background-color: #0067b8;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s;
font-size: 14px;
width: 100%;
}
button:hover {
background-color: #004e8c;
}
.animation-status {
background: #f8f8f8;
padding: 10px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
min-height: 60px;
white-space: pre-wrap;
margin-top: 10px;
width: 100%;
}
footer {
text-align: center;
margin-top: 40px;
padding: 20px;
color: #666;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.controls {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>动画效果测试</h1>
<p class="description">此页面展示animation.js中定义的所有动画效果。点击每个动画类别下的按钮来测试对应的动画。</p>
</header>
<div class="controls">
<div class="control-group">
<h3>弹出动画 (Flyout)</h3>
<div class="demo-area">
<div class="demo-element" id="flyoutElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Flyout.toTop', 'flyoutElement')">向顶端</button>
<button onclick="runAnimation('Flyout.toBottom', 'flyoutElement')">向底端</button>
<button onclick="runAnimation('Flyout.toLeft', 'flyoutElement')">向左</button>
<button onclick="runAnimation('Flyout.toRight', 'flyoutElement')">向右</button>
<button onclick="runAnimation('Flyout.fromBottom', 'flyoutElement')">从底端</button>
<button onclick="runAnimation('Flyout.fromTop', 'flyoutElement')">从顶端</button>
<button onclick="runAnimation('Flyout.fromLeft', 'flyoutElement')">从左侧</button>
<button onclick="runAnimation('Flyout.fromRight', 'flyoutElement')">从右侧</button>
</div>
<div class="animation-status" id="flyoutStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>渐变动画 (Opacity)</h3>
<div class="demo-area">
<div class="demo-element" id="opacityElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Opacity.visible', 'opacityElement')">显示</button>
<button onclick="runAnimation('Opacity.hidden', 'opacityElement')">消失</button>
</div>
<div class="animation-status" id="opacityStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>缩放动画 (Scale)</h3>
<div class="demo-area">
<div class="demo-element" id="scaleElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Scale.up', 'scaleElement')">放大</button>
<button onclick="runAnimation('Scale.down', 'scaleElement')">缩小</button>
</div>
<div class="animation-status" id="scaleStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>默认动画 (Default)</h3>
<div class="demo-area">
<div class="demo-element" id="defaultElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Default.remove', 'defaultElement')">从右返回</button>
<button onclick="runAnimation('Default.removertl', 'defaultElement')">从左返回</button>
<button onclick="runAnimation('Default.apply', 'defaultElement')">向右移动</button>
<button onclick="runAnimation('Default.applyrtl', 'defaultElement')">向左移动</button>
</div>
<div class="animation-status" id="defaultStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>边缘动画 (Edge)</h3>
<div class="demo-area">
<div class="demo-element" id="edgeElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Edge.show', 'edgeElement')">从顶部显示</button>
<button onclick="runAnimation('Edge.hide', 'edgeElement')">向顶部隐藏</button>
</div>
<div class="animation-status" id="edgeStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>面板动画 (Panel)</h3>
<div class="demo-area">
<div class="demo-element" id="panelElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Panel.show', 'panelElement')">从右侧显示</button>
<button onclick="runAnimation('Panel.showrtl', 'panelElement')">从左侧显示</button>
<button onclick="runAnimation('Panel.hide', 'panelElement')">向右侧隐藏</button>
<button onclick="runAnimation('Panel.hidertl', 'panelElement')">向左侧隐藏</button>
</div>
<div class="animation-status" id="panelStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>弹出动画 (Popup)</h3>
<div class="demo-area">
<div class="demo-element" id="popupElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Popup.show', 'popupElement')">弹出显示</button>
</div>
<div class="animation-status" id="popupStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>拖放动画 (Drag)</h3>
<div class="demo-area">
<div class="demo-element" id="dragElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Drag.sourceEnd', 'dragElement')">从右复位</button>
<button onclick="runAnimation('Drag.sourceEndRtl', 'dragElement')">从左复位</button>
</div>
<div class="animation-status" id="dragStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>内容动画 (Content)</h3>
<div class="demo-area">
<div class="demo-element" id="contentElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Content.enter', 'contentElement')">从右进入</button>
<button onclick="runAnimation('Content.enterrtl', 'contentElement')">从左进入</button>
</div>
<div class="animation-status" id="contentStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>页面动画 (Page)</h3>
<div class="demo-area">
<div class="demo-element" id="pageElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Page.enter', 'pageElement')">从右进入</button>
<button onclick="runAnimation('Page.enterrtl', 'pageElement')">从左进入</button>
</div>
<div class="animation-status" id="pageStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>其他动画</h3>
<div class="demo-area">
<div class="demo-element" id="otherElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Exit', 'otherElement')">退出</button>
<button onclick="runAnimation('UpdateBadge', 'otherElement')">更新徽章</button>
</div>
<div class="animation-status" id="otherStatus">等待动画执行...</div>
</div>
</div>
</div>
<footer>
<p>动画效果测试页面 - 使用 WinJS 动画库</p>
</footer>
</div>
<script>
// 确保Windows对象存在
if (typeof Windows === 'undefined') {
console.error('Windows对象未定义请确保已正确引入WinJS库');
} else if (!Windows.UI || !Windows.UI.Animation) {
console.error('Windows.UI.Animation未定义请确保animation.js已正确加载');
}
// 动画映射表
const animationMap = {
'Flyout.toTop': Windows.UI.Animation.Keyframes.Flyout.toTop,
'Flyout.toBottom': Windows.UI.Animation.Keyframes.Flyout.toBottom,
'Flyout.toLeft': Windows.UI.Animation.Keyframes.Flyout.toLeft,
'Flyout.toRight': Windows.UI.Animation.Keyframes.Flyout.toRight,
'Flyout.fromBottom': Windows.UI.Animation.Keyframes.Flyout.fromBottom,
'Flyout.fromTop': Windows.UI.Animation.Keyframes.Flyout.fromTop,
'Flyout.fromLeft': Windows.UI.Animation.Keyframes.Flyout.fromLeft,
'Flyout.fromRight': Windows.UI.Animation.Keyframes.Flyout.fromRight,
'Opacity.visible': Windows.UI.Animation.Keyframes.Opacity.visible,
'Opacity.hidden': Windows.UI.Animation.Keyframes.Opacity.hidden,
'Scale.up': Windows.UI.Animation.Keyframes.Scale.up,
'Scale.down': Windows.UI.Animation.Keyframes.Scale.down,
'Default.remove': Windows.UI.Animation.Keyframes.Default.remove,
'Default.removertl': Windows.UI.Animation.Keyframes.Default.removertl,
'Default.apply': Windows.UI.Animation.Keyframes.Default.apply,
'Default.applyrtl': Windows.UI.Animation.Keyframes.Default.applyrtl,
'Edge.show': Windows.UI.Animation.Keyframes.Edge.show,
'Edge.hide': Windows.UI.Animation.Keyframes.Edge.hide,
'Panel.show': Windows.UI.Animation.Keyframes.Panel.show,
'Panel.showrtl': Windows.UI.Animation.Keyframes.Panel.showrtl,
'Panel.hide': Windows.UI.Animation.Keyframes.Panel.hide,
'Panel.hidertl': Windows.UI.Animation.Keyframes.Panel.hidertl,
'Popup.show': Windows.UI.Animation.Keyframes.Popup.show,
'Drag.sourceEnd': Windows.UI.Animation.Keyframes.Drag.sourceEnd,
'Drag.sourceEndRtl': Windows.UI.Animation.Keyframes.Drag.sourceEndRtl,
'Content.enter': Windows.UI.Animation.Keyframes.Content.enter,
'Content.enterrtl': Windows.UI.Animation.Keyframes.Content.enterrtl,
'Page.enter': Windows.UI.Animation.Keyframes.Page.enter,
'Page.enterrtl': Windows.UI.Animation.Keyframes.Page.enterrtl,
'Exit': Windows.UI.Animation.Keyframes.Exit,
'UpdateBadge': Windows.UI.Animation.Keyframes.UpdateBadge
};
// 运行动画的函数
function runAnimation(animationKey, elementId) {
const targetElement = document.getElementById(elementId);
const statusElement = document.getElementById(elementId.replace('Element', 'Status'));
if (!animationMap[animationKey]) {
statusElement.textContent = `错误:未找到动画键 "${animationKey}"`;
return;
}
// 获取动画关键帧
const keyFrame = animationMap[animationKey];
// 更新状态
statusElement.textContent = `正在执行动画: ${animationKey}\n关键帧: ${keyFrame}\n开始时间: ${new Date().toLocaleTimeString()}`;
// 执行动画
Windows.UI.Animation.RunAsync(targetElement, keyFrame, 1000)
.then(function() {
statusElement.textContent += `\n动画完成时间: ${new Date().toLocaleTimeString()}`;
})
.catch(function(error) {
statusElement.textContent = `动画执行出错: ${error.message}`;
});
}
// 页面加载完成后显示提示
window.addEventListener('DOMContentLoaded', function() {
const statusElements = document.querySelectorAll('.animation-status');
statusElements.forEach(element => {
element.textContent = '页面已加载完成,点击按钮测试动画效果';
});
});
</script>
</body>
</html>

View File

@@ -5,7 +5,8 @@
function nextstep() {
Resources.processAll();
}
WinJS.UI.processAll().done(nextstep);
if (typeof WinJS !== "undefined") WinJS.UI.processAll().done(nextstep);
else nextstep();
}
OnLoad.add(ready);
})(this);