7 Commits

8 changed files with 545 additions and 25 deletions

View File

@@ -30,6 +30,7 @@
#include <windows.h>
#include <dwmapi.h>
#include <glib/gwin32.h>
#include "../../win32/appusermodelid.h"
#else
#include <unistd.h>
#endif
@@ -140,7 +141,7 @@ win32_set_appusermodelid (void)
if (!set_appid)
return;
set_appid (L"ZoiteChat.Desktop.Notify");
set_appid (ZOITECHAT_APPUSERMODELIDW);
}
static void

View File

@@ -31,7 +31,7 @@
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(ArchiveLibDir);$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>$(DepLibs);$(ZoiteChatLib)common.lib;wbemuuid.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(DepLibs);$(ZoiteChatLib)common.lib;wbemuuid.lib;dwmapi.lib;ole32.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>

View File

@@ -1003,7 +1003,9 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen);
#ifdef G_OS_WIN32
mg_win32_allow_autohide_taskbar (wid, event);
if (event->changed_mask &
(GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))
mg_win32_allow_autohide_taskbar (wid, event);
#endif
return FALSE;

View File

@@ -91,6 +91,9 @@ zoitechat_gtk_ldflags = []
if host_machine.system() == 'windows'
zoitechat_gtk_sources += 'notifications/notification-windows.c'
zoitechat_gtk_deps += cc.find_library('dwmapi', required: true)
zoitechat_gtk_deps += cc.find_library('shell32', required: true)
zoitechat_gtk_deps += cc.find_library('ole32', required: true)
zoitechat_gtk_deps += cc.find_library('uuid', required: true)
zoitechat_theme_deps += cc.find_library('dwmapi', required: true)
else

View File

@@ -26,6 +26,7 @@
#include <roapi.h>
#include <windows.ui.notifications.h>
#include "../../../win32/appusermodelid.h"
using namespace Windows::UI::Notifications;
using namespace Windows::Data::Xml::Dom;
@@ -84,13 +85,20 @@ extern "C"
__declspec (dllexport) int
notification_backend_init (const char **error)
{
if (FAILED (Windows::Foundation::Initialize (RO_INIT_SINGLETHREADED)))
{
*error = "Error initializing Windows::Foundation.";
return 0;
}
try
{
if (!notifier)
notifier = ToastNotificationManager::CreateToastNotifier (L"ZoiteChat.Desktop.Notify");
notifier = ToastNotificationManager::CreateToastNotifier (ZOITECHAT_APPUSERMODELIDW);
}
catch (Platform::Exception ^ ex)
{
Windows::Foundation::Uninitialize ();
static char exc_message[1024];
std::string tmp = narrow(std::wstring(ex->Message->Data()));
if (SUCCEEDED(StringCchPrintfA(exc_message, _countof(exc_message), "Error (0x%x): %s", ex->HResult, tmp.c_str())))
@@ -101,16 +109,11 @@ extern "C"
}
catch (...)
{
Windows::Foundation::Uninitialize ();
*error = "Generic c++ exception.";
return 0;
}
if (FAILED (Windows::Foundation::Initialize (RO_INIT_SINGLETHREADED)))
{
*error = "Error initializing Windows::Foundation.";
return 0;
}
return 1;
}

View File

@@ -32,6 +32,12 @@
#include "gtkutil.h"
#include <gio/gio.h>
#ifdef WIN32
#include <windows.h>
#include <shellapi.h>
#include <shobjidl.h>
#include <gdk/gdkwin32.h>
#endif
#if defined(GTK_DISABLE_DEPRECATED)
typedef struct _GtkStatusIcon GtkStatusIcon;
#endif
@@ -117,6 +123,7 @@ gboolean gtk_status_icon_is_embedded (GtkStatusIcon *status_icon);
void tray_apply_setup (void);
static gboolean tray_menu_try_restore (void);
static gboolean tray_toggle_visibility_from_input (gboolean force_hide, gboolean direct_input);
static void tray_cleanup (void);
static void tray_init (void);
static void tray_set_icon_state (TrayIcon icon, TrayIconState state);
@@ -125,6 +132,7 @@ static void tray_menu_notify_cb (GObject *tray, GParamSpec *pspec, gpointer user
static void tray_update_toggle_item_label (void);
static gboolean tray_window_state_cb (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata);
static void tray_window_visibility_cb (GtkWidget *widget, gpointer userdata);
static WinStatus tray_get_window_status (void);
static void tray_toggle_item_destroy_cb (GtkWidget *widget, gpointer userdata);
#if HAVE_APPINDICATOR_BACKEND
static void tray_menu_show_cb (GtkWidget *menu, gpointer userdata) G_GNUC_UNUSED;
@@ -149,6 +157,16 @@ static GtkWidget *tray_menu;
#if !HAVE_APPINDICATOR_BACKEND
static GtkStatusIcon *tray_status_icon;
#endif
#ifdef WIN32
static HWND tray_win32_hwnd;
static HICON tray_win32_icon;
static HICON tray_win32_overlay_icon;
static ITaskbarList3 *tray_win32_taskbar;
static gboolean tray_win32_active;
static UINT tray_win32_taskbar_created;
static const UINT tray_win32_callback_msg = WM_APP + 42;
static const GUID tray_win32_guid = { 0xf79ad3d9, 0xc92f, 0x49eb, { 0x9d, 0xd2, 0xe1, 0xad, 0xad, 0xa8, 0x1c, 0xd3 } };
#endif
static gboolean tray_backend_active = FALSE;
static gint flash_tag;
@@ -510,6 +528,447 @@ tray_status_icon_init (void)
return TRUE;
}
#ifdef WIN32
static HICON
tray_win32_pixbuf_to_hicon (GdkPixbuf *pixbuf)
{
BITMAPV5HEADER bi;
ICONINFO ii;
HBITMAP color;
HBITMAP mask;
HDC dc;
HICON icon;
guchar *pixels;
guchar *src;
guchar *dst;
void *bits;
int width;
int height;
int rowstride;
int channels;
int x;
int y;
if (!pixbuf)
return NULL;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
channels = gdk_pixbuf_get_n_channels (pixbuf);
pixels = gdk_pixbuf_get_pixels (pixbuf);
ZeroMemory (&bi, sizeof (bi));
bi.bV5Size = sizeof (bi);
bi.bV5Width = width;
bi.bV5Height = -height;
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_BITFIELDS;
bi.bV5RedMask = 0x00ff0000;
bi.bV5GreenMask = 0x0000ff00;
bi.bV5BlueMask = 0x000000ff;
bi.bV5AlphaMask = 0xff000000;
dc = GetDC (NULL);
color = CreateDIBSection (dc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, &bits, NULL, 0);
ReleaseDC (NULL, dc);
if (!color)
return NULL;
for (y = 0; y < height; y++)
{
src = pixels + y * rowstride;
dst = (guchar *)bits + y * width * 4;
for (x = 0; x < width; x++)
{
guchar alpha = channels >= 4 ? src[3] : 255;
dst[0] = src[2] * alpha / 255;
dst[1] = src[1] * alpha / 255;
dst[2] = src[0] * alpha / 255;
dst[3] = alpha;
src += channels;
dst += 4;
}
}
mask = CreateBitmap (width, height, 1, 1, NULL);
if (!mask)
{
DeleteObject (color);
return NULL;
}
ZeroMemory (&ii, sizeof (ii));
ii.fIcon = TRUE;
ii.hbmColor = color;
ii.hbmMask = mask;
icon = CreateIconIndirect (&ii);
DeleteObject (mask);
DeleteObject (color);
return icon;
}
static HWND
tray_win32_get_main_hwnd (void)
{
GtkWindow *win;
GdkWindow *gdk_window;
win = GTK_WINDOW (zoitechat_get_info (ph, "gtkwin_ptr"));
if (!win)
return NULL;
gdk_window = gtk_widget_get_window (GTK_WIDGET (win));
if (!gdk_window)
return NULL;
return gdk_win32_window_get_handle (gdk_window);
}
static ITaskbarList3 *
tray_win32_get_taskbar (void)
{
HRESULT hr;
if (tray_win32_taskbar)
return tray_win32_taskbar;
hr = CoCreateInstance (&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
&IID_ITaskbarList3, (void **)&tray_win32_taskbar);
if (FAILED (hr))
return NULL;
hr = tray_win32_taskbar->lpVtbl->HrInit (tray_win32_taskbar);
if (FAILED (hr))
{
tray_win32_taskbar->lpVtbl->Release (tray_win32_taskbar);
tray_win32_taskbar = NULL;
return NULL;
}
return tray_win32_taskbar;
}
static void
tray_win32_release_attention (void)
{
if (tray_win32_overlay_icon)
{
DestroyIcon (tray_win32_overlay_icon);
tray_win32_overlay_icon = NULL;
}
if (tray_win32_taskbar)
{
tray_win32_taskbar->lpVtbl->Release (tray_win32_taskbar);
tray_win32_taskbar = NULL;
}
}
static void
tray_win32_clear_attention (void)
{
FLASHWINFO flash;
ITaskbarList3 *taskbar;
HWND hwnd;
hwnd = tray_win32_get_main_hwnd ();
if (!hwnd)
return;
ZeroMemory (&flash, sizeof (flash));
flash.cbSize = sizeof (flash);
flash.hwnd = hwnd;
flash.dwFlags = FLASHW_STOP;
FlashWindowEx (&flash);
taskbar = tray_win32_get_taskbar ();
if (taskbar)
taskbar->lpVtbl->SetOverlayIcon (taskbar, hwnd, NULL, L"");
if (tray_win32_overlay_icon)
{
DestroyIcon (tray_win32_overlay_icon);
tray_win32_overlay_icon = NULL;
}
}
static void
tray_win32_set_attention (TrayIcon icon)
{
FLASHWINFO flash;
ITaskbarList3 *taskbar;
HICON hicon;
HWND hwnd;
if (tray_get_window_status () == WS_FOCUSED)
return;
hwnd = tray_win32_get_main_hwnd ();
if (!hwnd)
return;
ZeroMemory (&flash, sizeof (flash));
flash.cbSize = sizeof (flash);
flash.hwnd = hwnd;
flash.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
FlashWindowEx (&flash);
taskbar = tray_win32_get_taskbar ();
if (!taskbar)
return;
hicon = tray_win32_pixbuf_to_hicon (icon);
if (!hicon)
return;
if (SUCCEEDED (taskbar->lpVtbl->SetOverlayIcon (taskbar, hwnd, hicon, L"")))
{
if (tray_win32_overlay_icon)
DestroyIcon (tray_win32_overlay_icon);
tray_win32_overlay_icon = hicon;
}
else
{
DestroyIcon (hicon);
}
}
static void
tray_win32_init_data (NOTIFYICONDATAW *nid)
{
ZeroMemory (nid, sizeof (*nid));
nid->cbSize = sizeof (*nid);
nid->hWnd = tray_win32_hwnd;
nid->uID = 1;
nid->uFlags = NIF_GUID;
nid->guidItem = tray_win32_guid;
}
static gboolean
tray_win32_add (void)
{
NOTIFYICONDATAW nid;
tray_win32_init_data (&nid);
nid.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = tray_win32_callback_msg;
nid.hIcon = tray_win32_icon;
wcsncpy (nid.szTip, L"ZoiteChat", G_N_ELEMENTS (nid.szTip) - 1);
if (!Shell_NotifyIconW (NIM_ADD, &nid))
return FALSE;
tray_win32_init_data (&nid);
nid.uVersion = NOTIFYICON_VERSION_4;
Shell_NotifyIconW (NIM_SETVERSION, &nid);
return TRUE;
}
static void
tray_win32_set_icon (TrayIcon icon)
{
NOTIFYICONDATAW nid;
HICON hicon;
if (!tray_win32_active)
return;
hicon = tray_win32_pixbuf_to_hicon (icon);
if (!hicon)
return;
tray_win32_init_data (&nid);
nid.uFlags |= NIF_ICON;
nid.hIcon = hicon;
if (Shell_NotifyIconW (NIM_MODIFY, &nid))
{
if (tray_win32_icon)
DestroyIcon (tray_win32_icon);
tray_win32_icon = hicon;
}
else
{
DestroyIcon (hicon);
}
}
static void
tray_win32_set_tooltip (const char *text)
{
NOTIFYICONDATAW nid;
wchar_t *wide;
if (!tray_win32_active)
return;
wide = g_utf8_to_utf16 (text ? text : "", -1, NULL, NULL, NULL);
tray_win32_init_data (&nid);
nid.uFlags |= NIF_TIP;
if (wide)
{
wcsncpy (nid.szTip, wide, G_N_ELEMENTS (nid.szTip) - 1);
g_free (wide);
}
Shell_NotifyIconW (NIM_MODIFY, &nid);
}
static gboolean
tray_win32_is_embedded (void)
{
return tray_win32_active;
}
static void
tray_win32_cleanup (void)
{
NOTIFYICONDATAW nid;
if (tray_win32_active)
{
tray_win32_init_data (&nid);
Shell_NotifyIconW (NIM_DELETE, &nid);
tray_win32_active = FALSE;
}
if (tray_win32_icon)
{
DestroyIcon (tray_win32_icon);
tray_win32_icon = NULL;
}
tray_win32_release_attention ();
if (tray_win32_hwnd)
{
DestroyWindow (tray_win32_hwnd);
tray_win32_hwnd = NULL;
}
}
static LRESULT CALLBACK
tray_win32_wndproc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
(void)wparam;
if (msg == tray_win32_taskbar_created && tray_win32_icon)
{
tray_win32_add ();
return 0;
}
if (msg == tray_win32_callback_msg)
{
switch (LOWORD (lparam))
{
case NIN_SELECT:
case NIN_KEYSELECT:
case WM_LBUTTONUP:
tray_menu_restore_cb (NULL, NULL);
return 0;
case WM_CONTEXTMENU:
case WM_RBUTTONUP:
SetForegroundWindow (hwnd);
tray_menu_cb (NULL, 3, GetTickCount (), NULL);
PostMessage (hwnd, WM_NULL, 0, 0);
return 0;
default:
break;
}
}
return DefWindowProcW (hwnd, msg, wparam, lparam);
}
static gboolean
tray_win32_init (void)
{
WNDCLASSW wc;
tray_win32_taskbar_created = RegisterWindowMessageW (L"TaskbarCreated");
tray_win32_icon = tray_win32_pixbuf_to_hicon (ICON_NORMAL);
if (!tray_win32_icon)
return FALSE;
ZeroMemory (&wc, sizeof (wc));
wc.lpfnWndProc = tray_win32_wndproc;
wc.hInstance = GetModuleHandleW (NULL);
wc.lpszClassName = L"ZoiteChatTrayWindow";
RegisterClassW (&wc);
tray_win32_hwnd = CreateWindowExW (0, wc.lpszClassName, L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wc.hInstance, NULL);
if (!tray_win32_hwnd)
{
tray_win32_cleanup ();
return FALSE;
}
if (!tray_win32_add ())
{
tray_win32_cleanup ();
return FALSE;
}
tray_win32_active = TRUE;
return TRUE;
}
static gboolean
tray_win32_or_status_icon_init (void)
{
if (tray_win32_init ())
return TRUE;
return tray_status_icon_init ();
}
static void
tray_win32_or_status_icon_set_icon (TrayIcon icon)
{
if (tray_win32_active)
tray_win32_set_icon (icon);
else
tray_status_icon_set_icon (icon);
}
static void
tray_win32_or_status_icon_set_tooltip (const char *text)
{
if (tray_win32_active)
tray_win32_set_tooltip (text);
else
tray_status_icon_set_tooltip (text);
}
static gboolean
tray_win32_or_status_icon_is_embedded (void)
{
if (tray_win32_active)
return tray_win32_is_embedded ();
return tray_status_icon_is_embedded ();
}
static void
tray_win32_or_status_icon_cleanup (void)
{
if (tray_win32_active || tray_win32_hwnd || tray_win32_icon)
tray_win32_cleanup ();
else
tray_status_icon_cleanup ();
}
static const TrayBackendOps tray_backend_ops = {
tray_win32_or_status_icon_init,
tray_win32_or_status_icon_set_icon,
tray_win32_or_status_icon_set_tooltip,
tray_win32_or_status_icon_is_embedded,
tray_win32_or_status_icon_cleanup
};
#else
static const TrayBackendOps tray_backend_ops = {
tray_status_icon_init,
tray_status_icon_set_icon,
@@ -518,6 +977,7 @@ static const TrayBackendOps tray_backend_ops = {
tray_status_icon_cleanup
};
#endif
#endif
static gboolean
tray_backend_init (void)
@@ -697,6 +1157,10 @@ tray_stop_flash (void)
flash_tag = 0;
}
#ifdef WIN32
tray_win32_clear_attention ();
#endif
if (tray_backend_active)
{
tray_set_icon_state (ICON_NORMAL, TRAY_ICON_NORMAL);
@@ -847,8 +1311,8 @@ fe_tray_set_file (const char *filename)
}
}
gboolean
tray_toggle_visibility (gboolean force_hide)
static gboolean
tray_toggle_visibility_from_input (gboolean force_hide, gboolean direct_input)
{
static int x, y;
static GdkScreen *screen;
@@ -890,9 +1354,29 @@ tray_toggle_visibility (gboolean force_hide)
gtk_window_maximize (win);
if (fullscreen)
gtk_window_fullscreen (win);
#ifdef WIN32
{
GdkWindow *gdk_window;
HWND hwnd = NULL;
gdk_window = gtk_widget_get_window (GTK_WIDGET (win));
if (gdk_window)
hwnd = gdk_win32_window_get_handle (gdk_window);
if (hwnd && IsIconic (hwnd))
ShowWindow (hwnd, SW_RESTORE);
gtk_widget_show (GTK_WIDGET (win));
gtk_window_present (win);
if (direct_input && hwnd)
SetForegroundWindow (hwnd);
}
#else
gtk_widget_show (GTK_WIDGET (win));
gtk_window_deiconify (win);
gtk_window_present (win);
#endif
}
tray_update_toggle_item_label ();
@@ -900,13 +1384,19 @@ tray_toggle_visibility (gboolean force_hide)
return TRUE;
}
gboolean
tray_toggle_visibility (gboolean force_hide)
{
return tray_toggle_visibility_from_input (force_hide, FALSE);
}
static void
tray_menu_restore_cb (GtkWidget *item, gpointer userdata)
{
(void)item;
(void)userdata;
tray_toggle_visibility (FALSE);
tray_toggle_visibility_from_input (FALSE, TRUE);
}
static void
@@ -1042,7 +1532,11 @@ tray_menu_destroy (GtkWidget *menu, gpointer userdata)
if (G_IS_OBJECT (menu))
g_object_unref (menu);
#ifdef WIN32
g_source_remove (tray_menu_timer);
if (tray_menu_timer)
{
g_source_remove (tray_menu_timer);
tray_menu_timer = 0;
}
#endif
}
#endif
@@ -1283,6 +1777,9 @@ tray_hilight_cb (char *word[], void *userdata)
if (prefs.hex_input_tray_hilight)
{
tray_set_flash (ICON_HILIGHT, TRAY_ICON_HIGHLIGHT);
#ifdef WIN32
tray_win32_set_attention (ICON_HILIGHT);
#endif
/* FIXME: hides any previous private messages */
tray_hilight_count++;
@@ -1334,6 +1831,9 @@ tray_priv (char *from, char *text)
if (prefs.hex_input_tray_priv)
{
tray_set_flash (ICON_MSG, TRAY_ICON_MESSAGE);
#ifdef WIN32
tray_win32_set_attention (ICON_MSG);
#endif
tray_priv_count++;
if (tray_priv_count == 1)
@@ -1405,6 +1905,9 @@ tray_cleanup (void)
if (tray_backend_active)
tray_backend_cleanup ();
#ifdef WIN32
tray_win32_release_attention ();
#endif
}
void
@@ -1417,7 +1920,7 @@ tray_apply_setup (void)
}
else
{
#if HAVE_APPINDICATOR_BACKEND
#if HAVE_APPINDICATOR_BACKEND || defined(WIN32)
if (prefs.hex_gui_tray)
tray_init ();
#else
@@ -1471,7 +1974,7 @@ tray_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name,
G_CALLBACK (tray_window_visibility_cb), NULL);
}
#if HAVE_APPINDICATOR_BACKEND
#if HAVE_APPINDICATOR_BACKEND || defined(WIN32)
if (prefs.hex_gui_tray)
#else
if (prefs.hex_gui_tray && gtkutil_tray_icon_supported (window))

4
win32/appusermodelid.h Normal file
View File

@@ -0,0 +1,4 @@
#define ZOITECHAT_APPUSERMODELID "ZoiteChat.Desktop.Notify"
#ifdef _WIN32
#define ZOITECHAT_APPUSERMODELIDW L"ZoiteChat.Desktop.Notify"
#endif

View File

@@ -1,5 +1,6 @@
#define APPNAM "ZoiteChat"
#define APPVER "<#= [string]::Join('.', $versionParts) #>"
#include "..\appusermodelid.h"
; These are defined by our installer project at build time
;#define APPARCH "x64"
;#define PROJECTDIR "C:\...\zoitechat\win32\installer\"
@@ -76,11 +77,14 @@ Root: HKCR; Subkey: "irc"; ValueType: string; ValueName: "URL Protocol"; ValueDa
Root: HKCR; Subkey: "irc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\zoitechat.exe,0"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "irc\shell"; ValueType: string; ValueName: ""; ValueData: "open"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "irc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\zoitechat.exe --url=""%1"""; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "irc\Application"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#ZOITECHAT_APPUSERMODELID}"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: ".zct"; ValueType: string; ValueName: ""; ValueData: "ZoiteChat.Theme"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: ".hct"; ValueType: string; ValueName: ""; ValueData: "ZoiteChat.Theme"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "ZoiteChat.Theme"; ValueType: string; ValueName: ""; ValueData: "ZoiteChat Theme"; Flags: uninsdeletekey; Tasks: not portable
Root: HKCR; Subkey: "ZoiteChat.Theme\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\zoitechat.exe,0"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "ZoiteChat.Theme\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\zoitechat.exe"" ""%1"""; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "ZoiteChat.Theme\Application"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#ZOITECHAT_APPUSERMODELID}"; Flags: uninsdeletevalue; Tasks: not portable
Root: HKCR; Subkey: "Applications\zoitechat.exe\Application"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#ZOITECHAT_APPUSERMODELID}"; Flags: uninsdeletevalue; Tasks: not portable
[Run]
Filename: "{app}\zoitechat.exe"; Description: "Run ZoiteChat after closing the Wizard"; Flags: nowait postinstall skipifsilent
@@ -188,15 +192,15 @@ Source: "zoitechat.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: lib
Source: "zoitechat-text.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xctext
[Icons]
Name: "{group}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "ZoiteChat.Desktop.Notify"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat Safe Mode"; Filename: "{app}\zoitechat.exe"; Parameters: "--no-auto --no-plugins"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat Config Folder"; Filename: "%APPDATA%\ZoiteChat\"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat-Text"; Filename: "{app}\zoitechat-text.exe"; Components: xctext; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\Uninstall ZoiteChat"; Filename: "{uninstallexe}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{commondesktop}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "ZoiteChat.Desktop.Notify"; Components: icons\desktopicon; Tasks: not portable
Name: "{commonappdata}\Microsoft\Internet Explorer\Quick Launch\ZoiteChat"; Filename: "{app}\zoitechat.exe"; Components: icons\quicklaunchicon; Tasks: not portable
Name: "{group}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat Safe Mode"; Filename: "{app}\zoitechat.exe"; Parameters: "--no-auto --no-plugins"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat Config Folder"; Filename: "%APPDATA%\ZoiteChat\"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\ZoiteChat-Text"; Filename: "{app}\zoitechat-text.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Components: xctext; Tasks: not portable; Check: not WizardNoIcons
Name: "{group}\Uninstall ZoiteChat"; Filename: "{uninstallexe}"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
Name: "{commondesktop}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Components: icons\desktopicon; Tasks: not portable
Name: "{commonappdata}\Microsoft\Internet Explorer\Quick Launch\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Components: icons\quicklaunchicon; Tasks: not portable
[Messages]
BeveledLabel= {#APPNAM}