Update: Use desktop toast notifications on Windows 10

Use toast notification to announce new update on modern Windows
versions.

The advantage of toasts is that they look more natural and they are
persistent. So one can find the information about new update in action
center even after notification timed out.
This commit is contained in:
ge0rdi
2020-09-09 21:11:10 +02:00
parent 225d0ba8f9
commit ed3da927cc
3 changed files with 80 additions and 47 deletions

View File

@@ -38,6 +38,7 @@ copy /B ..\ClassicIE\Setup\ClassicIE_32.exe Output > nul
copy /B ..\StartMenu\Setup\StartMenu.exe Output > nul
copy /B ..\StartMenu\Setup\StartMenuDLL.dll Output > nul
copy /B ..\Update\Release\Update.exe Output > nul
copy /B ..\Update\DesktopToasts\Release\DesktopToasts.dll Output > nul
copy /B ..\StartMenu\StartMenuHelper\Setup\StartMenuHelper32.dll Output > nul
copy /B ..\Setup\SetupHelper\Release\SetupHelper.exe Output > nul
@@ -99,6 +100,8 @@ copy /B ..\StartMenu\StartMenuHelper\Setup\StartMenuHelper32.pdb Output\PDB32 >
copy /B Output\StartMenuHelper32.dll Output\PDB32 > nul
copy /B ..\Update\Release\Update.pdb Output\PDB32 > nul
copy /B Output\Update.exe Output\PDB32 > nul
copy /B ..\Update\DesktopToasts\Release\DesktopToasts.pdb Output\PDB32 > nul
copy /B Output\DesktopToasts.dll Output\PDB32 > nul
REM Menu 64
copy /B ..\StartMenu\Setup64\StartMenu.pdb Output\PDB64 > nul

View File

@@ -105,7 +105,9 @@
</Feature>
<Feature Id="Update" Level="1" Title="!(loc.UpdateTitle)" ConfigurableDirectory="APPLICATIONFOLDER" AllowAdvertise="no" Description="!(loc.UpdateDesc)">
<ComponentRef Id="Update.exe" />
<ComponentRef Id="DesktopToasts.dll" />
<ComponentRef Id="UpdateSettingsLink" />
<ComponentRef Id="ToastActivator" />
</Feature>
</Feature>
<UI>
@@ -476,6 +478,9 @@
<Component Id="Update.exe" Guid="FB6C213F-B670-4888-8B2C-12E807E335A7" Win64="$(var.CS_WIN64)">
<File Id="Update" KeyPath="yes" Source="Output\Update.exe" Checksum="yes" Vital="yes" />
</Component>
<Component Id="DesktopToasts.dll" Guid="B42157AF-3984-4796-8BD6-501FC5450FF1" Win64="$(var.CS_WIN64)">
<File Id="DesktopToasts.dll" KeyPath="yes" Source="Output\DesktopToasts.dll" Checksum="yes" Vital="yes" />
</Component>
<Component Id="PolicyDefinitions.zip" Guid="580A15D0-4023-471d-9D82-9D63FBA42B5D" Win64="$(var.CS_WIN64)">
<File Id="PolicyDefinitions.zip" KeyPath="yes" Source="Output\PolicyDefinitions.zip" Vital="yes" />
</Component>
@@ -551,6 +556,11 @@
<Component Id="TreatAs" Guid="B1E7462A-E1E2-47eb-A42C-7BD272D738AA" Win64="$(var.CS_WIN64)">
<RegistryKey Root="HKCR" Key="CLSID\{ECD4FC4D-521C-11D0-B792-00A0C90312E1}\TreatAs" ForceDeleteOnUninstall="yes" />
</Component>
<Component Id="ToastActivator" Guid="3A0FDC31-D5D3-4C2E-9A0B-292CAB46DA87" Win64="$(var.CS_WIN64)">
<RegistryKey Root="HKCR" Key="CLSID\{E407B70A-1FBD-4D5E-8822-231C69102472}\LocalServer32" ForceDeleteOnUninstall="yes">
<RegistryValue Value="&quot;[APPLICATIONFOLDER]Update.exe&quot; -ToastActivated" Type="string" />
</RegistryKey>
</Component>
</DirectoryRef>
<DirectoryRef Id="StartMenuDir">
<Component Id="HelpLink" Guid="D631C351-7BD4-42CE-813C-5D46347068AF">
@@ -564,7 +574,10 @@
<Condition>START_MENU_FOLDER=1</Condition>
</Component>
<Component Id="UpdateSettingsLink" Guid="10B5A082-6C92-4EA7-AFF8-21AE3D2D7FE0">
<Shortcut Id="UpdateSettingsLink" Name="!(loc.UpdateItem)" Advertise="no" Description="!(loc.UpdateSettingsDesc)" Target="[APPLICATIONFOLDER]Update.exe" WorkingDirectory="APPLICATIONFOLDER" />
<Shortcut Id="UpdateSettingsLink" Name="!(loc.UpdateItem)" Advertise="no" Description="!(loc.UpdateSettingsDesc)" Target="[APPLICATIONFOLDER]Update.exe" WorkingDirectory="APPLICATIONFOLDER">
<ShortcutProperty Key="System.AppUserModel.ID" Value="OpenShell.Update"/>
<ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{E407B70A-1FBD-4D5E-8822-231C69102472}"/>
</Shortcut>
<CreateFolder />
<Condition>START_MENU_FOLDER=1</Condition>
</Component>

View File

@@ -16,6 +16,7 @@
#include "ResourceHelper.h"
#include "Translations.h"
#include <shlobj.h>
#include "DesktopToasts/DesktopToasts.h"
void ClosingSettings( HWND hWnd, int flags, int command )
@@ -487,8 +488,6 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrC
CString language=GetSettingString(L"Language");
ParseTranslations(NULL,language);
g_Instance=hInstance;
HINSTANCE resInstance=LoadTranslationDll(language);
LoadTranslationResources(resInstance,g_LoadDialogs);
@@ -500,6 +499,9 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrC
COwnerWindow ownerWindow;
ownerWindow.Create(NULL,0,0,WS_POPUP);
DesktopToasts toasts(L"OpenShell.Update");
if (wcsstr(lpstrCmdLine,L"-popup")!=NULL)
{
g_UpdateDlg.UpdateData();
@@ -507,52 +509,67 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrC
int sleep=5000-(timeGetTime()-time0);
if (sleep>0)
Sleep(sleep);
HWND balloon=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|(IsLanguageRTL()?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_CLOSE|TTS_NOPREFIX,0,0,0,0,NULL,NULL,g_Instance,NULL);
SendMessage(balloon,TTM_SETMAXTIPWIDTH,0,500);
TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRANSPARENT|TTF_TRACK|(IsLanguageRTL()?TTF_RTLREADING:0U)};
tool.uId=1;
CString message=LoadStringEx(g_UpdateDlg.HasNewLanguage()?IDS_LANG_NEWVERSION:IDS_NEWVERSION);
tool.lpszText=(wchar_t*)(const wchar_t*)message;
SendMessage(balloon,TTM_ADDTOOL,0,(LPARAM)&tool);
SendMessage(balloon,TTM_SETTITLE,(WPARAM)LoadIcon(g_Instance,MAKEINTRESOURCE(IDI_APPICON)),(LPARAM)(const wchar_t*)LoadStringEx(IDS_UPDATE_TITLE));
APPBARDATA appbar={sizeof(appbar)};
SHAppBarMessage(ABM_GETTASKBARPOS,&appbar);
MONITORINFO info={sizeof(info)};
GetMonitorInfo(MonitorFromWindow(appbar.hWnd,MONITOR_DEFAULTTOPRIMARY),&info);
SendMessage(balloon,TTM_TRACKPOSITION,0,0);
SendMessage(balloon,TTM_TRACKACTIVATE,TRUE,(LPARAM)&tool);
RECT rc;
GetWindowRect(balloon,&rc);
LONG pos;
if (appbar.uEdge==ABE_LEFT)
pos=MAKELONG(info.rcWork.left,info.rcWork.bottom-rc.bottom+rc.top);
else if (appbar.uEdge==ABE_RIGHT)
pos=MAKELONG(info.rcWork.right-rc.right+rc.left,info.rcWork.bottom-rc.bottom+rc.top);
else if (appbar.uEdge==ABE_TOP)
pos=MAKELONG(IsLanguageRTL()?info.rcWork.left:info.rcWork.right-rc.right+rc.left,info.rcWork.top);
else
pos=MAKELONG(IsLanguageRTL()?info.rcWork.left:info.rcWork.right-rc.right+rc.left,info.rcWork.bottom-rc.bottom+rc.top);
SendMessage(balloon,TTM_TRACKPOSITION,0,pos);
SetWindowSubclass(balloon,SubclassBalloonProc,0,'CLSH');
PlaySound(L"SystemNotification",NULL,SND_APPLICATION|SND_ALIAS|SND_ASYNC|SND_NODEFAULT|SND_SYSTEM);
int time0=timeGetTime();
while (IsWindowVisible(balloon))
auto title = LoadStringEx(IDS_UPDATE_TITLE);
auto message = LoadStringEx(g_UpdateDlg.HasNewLanguage() ? IDS_LANG_NEWVERSION : IDS_NEWVERSION);
if (toasts)
{
if (time0 && (timeGetTime()-time0)>=15000)
{
time0=0;
TOOLINFO tool={sizeof(tool)};
tool.uId=1;
SendMessage(balloon,TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool);
}
MSG msg;
while (PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
toasts.DisplaySimpleToast(title, message);
}
else
{
HWND balloon = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW | (IsLanguageRTL() ? WS_EX_LAYOUTRTL : 0), TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_CLOSE | TTS_NOPREFIX, 0, 0, 0, 0, NULL, NULL, g_Instance, NULL);
SendMessage(balloon, TTM_SETMAXTIPWIDTH, 0, 500);
TOOLINFO tool = { sizeof(tool),TTF_ABSOLUTE | TTF_TRANSPARENT | TTF_TRACK | (IsLanguageRTL() ? TTF_RTLREADING : 0U) };
tool.uId = 1;
tool.lpszText = (wchar_t*)(const wchar_t*)message;
SendMessage(balloon, TTM_ADDTOOL, 0, (LPARAM)&tool);
SendMessage(balloon, TTM_SETTITLE, (WPARAM)LoadIcon(g_Instance, MAKEINTRESOURCE(IDI_APPICON)), (LPARAM)(const wchar_t*)title);
APPBARDATA appbar = { sizeof(appbar) };
SHAppBarMessage(ABM_GETTASKBARPOS, &appbar);
MONITORINFO info = { sizeof(info) };
GetMonitorInfo(MonitorFromWindow(appbar.hWnd, MONITOR_DEFAULTTOPRIMARY), &info);
SendMessage(balloon, TTM_TRACKPOSITION, 0, 0);
SendMessage(balloon, TTM_TRACKACTIVATE, TRUE, (LPARAM)&tool);
RECT rc;
GetWindowRect(balloon, &rc);
LONG pos;
if (appbar.uEdge == ABE_LEFT)
pos = MAKELONG(info.rcWork.left, info.rcWork.bottom - rc.bottom + rc.top);
else if (appbar.uEdge == ABE_RIGHT)
pos = MAKELONG(info.rcWork.right - rc.right + rc.left, info.rcWork.bottom - rc.bottom + rc.top);
else if (appbar.uEdge == ABE_TOP)
pos = MAKELONG(IsLanguageRTL() ? info.rcWork.left : info.rcWork.right - rc.right + rc.left, info.rcWork.top);
else
pos = MAKELONG(IsLanguageRTL() ? info.rcWork.left : info.rcWork.right - rc.right + rc.left, info.rcWork.bottom - rc.bottom + rc.top);
SendMessage(balloon, TTM_TRACKPOSITION, 0, pos);
SetWindowSubclass(balloon, SubclassBalloonProc, 0, 'CLSH');
PlaySound(L"SystemNotification", NULL, SND_APPLICATION | SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_SYSTEM);
int time0 = timeGetTime();
while (IsWindowVisible(balloon))
{
if (time0 && (timeGetTime() - time0) >= 15000)
{
time0 = 0;
TOOLINFO tool = { sizeof(tool) };
tool.uId = 1;
SendMessage(balloon, TTM_TRACKACTIVATE, FALSE, (LPARAM)&tool);
}
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
}
}
}
else if (wcsstr(lpstrCmdLine, L"-ToastActivated"))
{
g_UpdateDlg.UpdateData();
g_UpdateDlg.Run();
}
else
{