DWORD WINAPI InstallerThread(LPVOID data) { gGlobalData.success = false; if (!CreateInstallationDirectory()) goto Error; ProgressStep(); if (!InstallCopyFiles()) goto Error; if (gGlobalData.registerAsDefault) { // need to sublaunch SumatraPDF.exe instead of replicating the code // because registration uses translated strings ScopedMem<WCHAR> installedExePath(GetInstalledExePath()); CreateProcessHelper(installedExePath, L"-register-for-pdf"); } if (gGlobalData.installBrowserPlugin) InstallBrowserPlugin(); else if (IsBrowserPluginInstalled()) UninstallBrowserPlugin(); if (gGlobalData.installPdfFilter) InstallPdfFilter(); else if (IsPdfFilterInstalled()) UninstallPdfFilter(); if (gGlobalData.installPdfPreviewer) InstallPdfPreviewer(); else if (IsPdfPreviewerInstalled()) UninstallPdfPreviewer(); if (!CreateAppShortcut(true) && !CreateAppShortcut(false)) { NotifyFailed(_TR("Failed to create a shortcut")); goto Error; } // consider installation a success from here on // (still warn, if we've failed to create the uninstaller, though) gGlobalData.success = true; if (!WriteUninstallerRegistryInfo(HKEY_LOCAL_MACHINE) && !WriteUninstallerRegistryInfo(HKEY_CURRENT_USER)) { NotifyFailed(_TR("Failed to write the uninstallation information to the registry")); } if (!WriteExtendedFileExtensionInfo(HKEY_LOCAL_MACHINE) && !WriteExtendedFileExtensionInfo(HKEY_CURRENT_USER)) { NotifyFailed(_TR("Failed to write the extended file extension information to the registry")); } ProgressStep(); Error: // TODO: roll back installation on failure (restore previous installation!) if (gHwndFrame && !gGlobalData.silent) { Sleep(500); // allow a glimpse of the completed progress bar before hiding it PostMessage(gHwndFrame, WM_APP_INSTALLATION_FINISHED, 0, 0); } return 0; }
//[ ACCESSKEY_GROUP Installer void OnCreateWindow(HWND hwnd) { ClientRect r(hwnd); gHwndButtonInstUninst = CreateDefaultButton(hwnd, _TR("Install SumatraPDF"), IDOK); SIZE btnSize; gHwndButtonOptions = CreateButton(hwnd, _TR("&Options"), ID_BUTTON_OPTIONS, BS_PUSHBUTTON, btnSize); int x = WINDOW_MARGIN; int y = r.dy - btnSize.cy - WINDOW_MARGIN; SetWindowPos(gHwndButtonOptions, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); gButtonDy = btnSize.cy; gBottomPartDy = gButtonDy + (WINDOW_MARGIN * 2); SizeI size = TextSizeInHwnd(hwnd, L"Foo"); int staticDy = size.dy + dpiAdjust(4); y = r.dy - gBottomPartDy; int dx = r.dx - (WINDOW_MARGIN * 2) - dpiAdjust(2); x += dpiAdjust(2); // build options controls going from the bottom y -= (staticDy + WINDOW_MARGIN); ScopedMem<WCHAR> defaultViewer(GetDefaultPdfViewer()); BOOL hasOtherViewer = !str::EqI(defaultViewer, APP_NAME_STR); BOOL isSumatraDefaultViewer = defaultViewer && !hasOtherViewer; // only show this checkbox if the CPU arch of DLL and OS match // (assuming that the installer has the same CPU arch as its content!) if (IsProcessAndOsArchSame()) { // only show this checkbox if the browser plugin has been installed before if (IsBrowserPluginInstalled()) { gHwndCheckboxKeepBrowserPlugin = CreateWindowExW( 0, WC_BUTTON, _TR("Keep the PDF &browser plugin installed (no longer supported)"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, x, y, dx, staticDy, hwnd, (HMENU) ID_CHECKBOX_BROWSER_PLUGIN, GetModuleHandle(nullptr), nullptr); SetWindowFont(gHwndCheckboxKeepBrowserPlugin, gFontDefault, TRUE); Button_SetCheck(gHwndCheckboxKeepBrowserPlugin, gGlobalData.keepBrowserPlugin); y -= staticDy; } // for Windows XP, this means only basic thumbnail support gHwndCheckboxRegisterPdfPreviewer = CreateWindowExW( 0, WC_BUTTON, _TR("Let Windows show &previews of PDF documents"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, x, y, dx, staticDy, hwnd, (HMENU) ID_CHECKBOX_PDF_PREVIEWER, GetModuleHandle(nullptr), nullptr); SetWindowFont(gHwndCheckboxRegisterPdfPreviewer, gFontDefault, TRUE); Button_SetCheck(gHwndCheckboxRegisterPdfPreviewer, gGlobalData.installPdfPreviewer || IsPdfPreviewerInstalled()); y -= staticDy; gHwndCheckboxRegisterPdfFilter = CreateWindowEx( 0, WC_BUTTON, _TR("Let Windows Desktop Search &search PDF documents"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, x, y, dx, staticDy, hwnd, (HMENU) ID_CHECKBOX_PDF_FILTER, GetModuleHandle(nullptr), nullptr); SetWindowFont(gHwndCheckboxRegisterPdfFilter, gFontDefault, TRUE); Button_SetCheck(gHwndCheckboxRegisterPdfFilter, gGlobalData.installPdfFilter || IsPdfFilterInstalled()); y -= staticDy; } // only show the checbox if Sumatra is not already a default viewer. // the alternative (disabling the checkbox) is more confusing if (!isSumatraDefaultViewer) { gHwndCheckboxRegisterDefault = CreateWindowExW( 0, WC_BUTTON, _TR("Use SumatraPDF as the &default PDF reader"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, x, y, dx, staticDy, hwnd, (HMENU) ID_CHECKBOX_MAKE_DEFAULT, GetModuleHandle(nullptr), nullptr); SetWindowFont(gHwndCheckboxRegisterDefault, gFontDefault, TRUE); // only check the "Use as default" checkbox when no other PDF viewer // is currently selected (not going to intrude) Button_SetCheck(gHwndCheckboxRegisterDefault, !hasOtherViewer || gGlobalData.registerAsDefault); y -= staticDy; } // a bit more space between text box and checkboxes y -= (dpiAdjust(4) + WINDOW_MARGIN); const WCHAR *s = L"&..."; SizeI btnSize2 = TextSizeInHwnd(hwnd, s); btnSize.cx += dpiAdjust(4); gHwndButtonBrowseDir = CreateButton(hwnd, s, ID_BUTTON_BROWSE, BS_PUSHBUTTON, btnSize); x = r.dx - WINDOW_MARGIN - btnSize2.dx; SetWindowPos(gHwndButtonBrowseDir, nullptr, x, y, btnSize2.dx, staticDy, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_FRAMECHANGED); x = WINDOW_MARGIN; dx = r.dx - (2 * WINDOW_MARGIN) - btnSize2.dx - dpiAdjust(4); gHwndTextboxInstDir = CreateWindowExW(0, WC_EDIT, gGlobalData.installDir, WS_CHILD | WS_TABSTOP | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL, x, y, dx, staticDy, hwnd, nullptr, GetModuleHandle(nullptr), nullptr); SetWindowFont(gHwndTextboxInstDir, gFontDefault, TRUE); y -= staticDy; gHwndStaticInstDir = CreateWindowExW( 0, WC_STATIC, _TR("Install SumatraPDF in &folder:"),WS_CHILD, x, y, r.dx, staticDy, hwnd, nullptr, GetModuleHandle(nullptr), nullptr); SetWindowFont(gHwndStaticInstDir, gFontDefault, TRUE); gShowOptions = !gShowOptions; OnButtonOptions(); SetFocus(gHwndButtonInstUninst); if (gGlobalData.autoUpdate) { // click the Install button PostMessage(hwnd, WM_COMMAND, IDOK, 0); } }
// TODO: since we have a variable UI, for better layout (anchored to the bottom, // not the top), we should layout controls starting at the bottom and go up void OnCreateWindow(HWND hwnd) { // TODO: this button might be too narrow for some translations gHwndButtonInstUninst = CreateDefaultButton(hwnd, _TR("Install SumatraPDF"), 140); RectI rc(WINDOW_MARGIN, 0, dpiAdjust(96), PUSH_BUTTON_DY); ClientRect r(hwnd); rc.y = r.dy - rc.dy - WINDOW_MARGIN; gHwndButtonOptions = CreateWindow(WC_BUTTON, _TR("&Options"), BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, rc.x, rc.y, rc.dx, rc.dy, hwnd, (HMENU)ID_BUTTON_OPTIONS, ghinst, NULL); SetWindowFont(gHwndButtonOptions, gFontDefault, TRUE); int staticDy = dpiAdjust(20); rc.y = TITLE_PART_DY + WINDOW_MARGIN; gHwndStaticInstDir = CreateWindow(WC_STATIC, _TR("Install SumatraPDF in &folder:"), WS_CHILD, rc.x, rc.y, r.dx - 2 * rc.x, staticDy, hwnd, NULL, ghinst, NULL); SetWindowFont(gHwndStaticInstDir, gFontDefault, TRUE); rc.y += staticDy; gHwndTextboxInstDir = CreateWindow(WC_EDIT, gGlobalData.installDir, WS_CHILD | WS_TABSTOP | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL, rc.x, rc.y, r.dx - 3 * rc.x - staticDy, staticDy, hwnd, NULL, ghinst, NULL); SetWindowFont(gHwndTextboxInstDir, gFontDefault, TRUE); gHwndButtonBrowseDir = CreateWindow(WC_BUTTON, L"&...", BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, r.dx - rc.x - staticDy, rc.y, staticDy, staticDy, hwnd, (HMENU)ID_BUTTON_BROWSE, ghinst, NULL); SetWindowFont(gHwndButtonBrowseDir, gFontDefault, TRUE); rc.y += 2 * staticDy; ScopedMem<WCHAR> defaultViewer(GetDefaultPdfViewer()); BOOL hasOtherViewer = !str::EqI(defaultViewer, APP_NAME_STR); BOOL isSumatraDefaultViewer = defaultViewer && !hasOtherViewer; // only show the checbox if Sumatra is not already a default viewer. // the alternative (disabling the checkbox) is more confusing if (!isSumatraDefaultViewer) { gHwndCheckboxRegisterDefault = CreateWindow( WC_BUTTON, _TR("Use SumatraPDF as the &default PDF reader"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, rc.x, rc.y, r.dx - 2 * rc.x, staticDy, hwnd, (HMENU)ID_CHECKBOX_MAKE_DEFAULT, ghinst, NULL); SetWindowFont(gHwndCheckboxRegisterDefault, gFontDefault, TRUE); // only check the "Use as default" checkbox when no other PDF viewer // is currently selected (not going to intrude) Button_SetCheck(gHwndCheckboxRegisterDefault, !hasOtherViewer || gGlobalData.registerAsDefault); rc.y += staticDy; } gHwndCheckboxRegisterBrowserPlugin = CreateWindow( WC_BUTTON, _TR("Install PDF &browser plugin for Firefox, Chrome and Opera"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, rc.x, rc.y, r.dx - 2 * rc.x, staticDy, hwnd, (HMENU)ID_CHECKBOX_BROWSER_PLUGIN, ghinst, NULL); SetWindowFont(gHwndCheckboxRegisterBrowserPlugin, gFontDefault, TRUE); Button_SetCheck(gHwndCheckboxRegisterBrowserPlugin, gGlobalData.installBrowserPlugin || IsBrowserPluginInstalled()); rc.y += staticDy; // only show this checkbox if the CPU arch of DLL and OS match // (assuming that the installer has the same CPU arch as its content!) #ifndef _WIN64 if (!IsRunningInWow64()) #endif { gHwndCheckboxRegisterPdfFilter = CreateWindow( WC_BUTTON, _TR("Let Windows Desktop Search &search PDF documents"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, rc.x, rc.y, r.dx - 2 * rc.x, staticDy, hwnd, (HMENU)ID_CHECKBOX_PDF_FILTER, ghinst, NULL); SetWindowFont(gHwndCheckboxRegisterPdfFilter, gFontDefault, TRUE); Button_SetCheck(gHwndCheckboxRegisterPdfFilter, gGlobalData.installPdfFilter || IsPdfFilterInstalled()); rc.y += staticDy; } // for Windows XP, this means only basic thumbnail support gHwndCheckboxRegisterPdfPreviewer = CreateWindow( WC_BUTTON, _TR("Let Windows show &previews of PDF documents"), WS_CHILD | BS_AUTOCHECKBOX | WS_TABSTOP, rc.x, rc.y, r.dx - 2 * rc.x, staticDy, hwnd, (HMENU)ID_CHECKBOX_PDF_PREVIEWER, ghinst, NULL); SetWindowFont(gHwndCheckboxRegisterPdfPreviewer, gFontDefault, TRUE); Button_SetCheck(gHwndCheckboxRegisterPdfPreviewer, gGlobalData.installPdfPreviewer || IsPdfPreviewerInstalled()); rc.y += staticDy; gShowOptions = !gShowOptions; OnButtonOptions(); SetFocus(gHwndButtonInstUninst); }