diff --git a/.vs/rufus.vcxproj b/.vs/rufus.vcxproj index a3068c82..6d48ff29 100644 --- a/.vs/rufus.vcxproj +++ b/.vs/rufus.vcxproj @@ -340,6 +340,7 @@ + @@ -367,6 +368,7 @@ + diff --git a/.vs/rufus.vcxproj.filters b/.vs/rufus.vcxproj.filters index 11d17ffc..e3af5eba 100644 --- a/.vs/rufus.vcxproj.filters +++ b/.vs/rufus.vcxproj.filters @@ -78,6 +78,9 @@ Source Files + + Source Files + @@ -152,6 +155,9 @@ Header Files + + Header Files + diff --git a/src/Makefile.am b/src/Makefile.am index 9cb4676b..dc259ab6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ AM_V_WINDRES = $(AM_V_WINDRES_$(V)) $(AM_V_WINDRES) $(AM_RCFLAGS) -i $< -o $@ rufus_SOURCES = badblocks.c checksum.c dev.c dos.c dos_locale.c drive.c format.c icon.c iso.c localization.c \ - net.c parser.c pki.c process.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c vhd.c + net.c parser.c pki.c process.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c ui.c vhd.c rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \ diff --git a/src/Makefile.in b/src/Makefile.in index 694be9d7..e5feeb0e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -96,7 +96,8 @@ am_rufus_OBJECTS = rufus-badblocks.$(OBJEXT) rufus-checksum.$(OBJEXT) \ rufus-process.$(OBJEXT) rufus-rufus.$(OBJEXT) \ rufus-smart.$(OBJEXT) rufus-stdfn.$(OBJEXT) \ rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \ - rufus-syslinux.$(OBJEXT) rufus-vhd.$(OBJEXT) + rufus-syslinux.$(OBJEXT) rufus-ui.$(OBJEXT) \ + rufus-vhd.$(OBJEXT) rufus_OBJECTS = $(am_rufus_OBJECTS) rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ms-sys/libmssys.a \ syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ @@ -271,7 +272,7 @@ AM_V_WINDRES_1 = $(WINDRES) AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY)) AM_V_WINDRES = $(AM_V_WINDRES_$(V)) rufus_SOURCES = badblocks.c checksum.c dev.c dos.c dos_locale.c drive.c format.c icon.c iso.c localization.c \ - net.c parser.c pki.c process.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c vhd.c + net.c parser.c pki.c process.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c ui.c vhd.c rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows @@ -452,6 +453,12 @@ rufus-syslinux.o: syslinux.c rufus-syslinux.obj: syslinux.c $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-syslinux.obj `if test -f 'syslinux.c'; then $(CYGPATH_W) 'syslinux.c'; else $(CYGPATH_W) '$(srcdir)/syslinux.c'; fi` +rufus-ui.o: ui.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-ui.o `test -f 'ui.c' || echo '$(srcdir)/'`ui.c + +rufus-ui.obj: ui.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-ui.obj `if test -f 'ui.c'; then $(CYGPATH_W) 'ui.c'; else $(CYGPATH_W) '$(srcdir)/ui.c'; fi` + rufus-vhd.o: vhd.c $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-vhd.o `test -f 'vhd.c' || echo '$(srcdir)/'`vhd.c diff --git a/src/rufus.c b/src/rufus.c index 2fb4b975..1b1a6b45 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "rufus.h" #include "missing.h" @@ -53,11 +52,8 @@ static const char* cmdline_hogger = "rufus.com"; static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "UDF", "exFAT", "ReFS" }; -static const char* flash_type[BADLOCKS_PATTERN_TYPES] = { "SLC", "MLC", "TLC" }; static const char* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"; static const char* vs_reg = "Software\\Microsoft\\VisualStudio"; -// Number of steps for each FS for FCC_STRUCTURE_PROGRESS -const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10 }; static BOOL existing_key = FALSE; // For LGP set/restore static BOOL size_check = TRUE; static BOOL log_displayed = FALSE; @@ -69,19 +65,13 @@ static BOOL user_changed_label = FALSE; static BOOL app_changed_label = FALSE; static BOOL allowed_filesystem[FS_MAX] = { 0 }; static int64_t last_iso_blocking_status; -static int windows_to_go_selection = 0, selected_pt = -1, selected_fs = -1; -static int selection_default, row_height, advanced_device_section_height, advanced_format_section_height, image_index; -static int ddh, bw, hw, fw; // DropDown Height, Main button width, half dropdown width, full dropdown width -static int sw, mw, bsw, sbw, ssw, tw, dbw; // See GetFullWidth() for details on how these values are used -static UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; +static int selected_pt = -1, selected_fs = -1; +static int image_index; static RECT relaunch_rc = { -65536, -65536, 0, 0}; static UINT uQFChecked = BST_CHECKED, uMBRChecked = BST_UNCHECKED; -static HFONT hInfoFont; -static WNDPROC progress_original_proc = NULL; static HANDLE format_thid = NULL, dialog_handle = NULL; static HWND hSelectImage = NULL, hStart = NULL; static char szTimer[12] = "00:00:00"; -static wchar_t wtbtext[2][128]; static unsigned int timer; static char uppercase_select[64], uppercase_start[64], uppercase_close[64], uppercase_cancel[64]; @@ -91,7 +81,6 @@ extern long grub2_len; extern char* szStatusMessage; extern const char* old_c32_name[NB_OLD_C32]; extern const char* cert_name[3]; -extern const char* sfd_name; /* * Globals @@ -100,7 +89,7 @@ OPENED_LIBRARIES_VARS; RUFUS_UPDATE update = { { 0,0,0 },{ 0,0 }, NULL, NULL }; HINSTANCE hMainInstance; HWND hMainDialog, hMultiToolbar, hSaveToolbar, hHashToolbar, hAdvancedDeviceToolbar, hAdvancedFormatToolbar, hUpdatesDlg = NULL; -HIMAGELIST hUpImageList, hDownImageList; +HFONT hInfoFont; uint8_t image_options = 0x00; uint16_t rufus_version[3], embedded_sl_version[2]; uint32_t dur_mins, dur_secs, DrivePort[MAX_DRIVES];; @@ -116,46 +105,21 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa BOOL use_fake_units, preserve_timestamps = FALSE; BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE, write_as_image = FALSE; float fScale = 1.0f; -int dialog_showing = 0; +int dialog_showing = 0, selection_default, windows_to_go_selection = 0; int default_fs, fs, bt, pt, tt; // file system, boot type, partition type, target type -int cbw, ddw, ddbh = 0, bh = 0; // (empty) check box width, (empty) drop down width, button height (for and without dropdown match) char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH]; char embedded_sl_version_str[2][12] = { "?.??", "?.??" }; char embedded_sl_version_ext[2][32]; char ClusterSizeLabel[MAX_CLUSTER_SIZES][64]; char msgbox[1024], msgbox_title[32], *ini_file = NULL, *image_path = NULL, *short_image_path; StrArray DriveID, DriveLabel, DriveHub, BlockingProcess, ImageList; - -static void ToggleImageOption(uint8_t mask); - -/* - * The following is used to allocate slots within the progress bar - * 0 means unused (no operation or no progress allocated to it) - * +n means allocate exactly n bars (n percent of the progress bar) - * -n means allocate a weighted slot of n from all remaining - * bars. E.g. if 80 slots remain and the sum of all negative entries - * is 10, -4 will allocate 4/10*80 = 32 bars (32%) for OP progress - */ -static int nb_slots[OP_MAX]; -static float slot_end[OP_MAX+1]; // shifted +1 so that we can subtract 1 to OP indexes -static float previous_end; +// Number of steps for each FS for FCC_STRUCTURE_PROGRESS +const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10 }; +const char* flash_type[BADLOCKS_PATTERN_TYPES] = { "SLC", "MLC", "TLC" }; // TODO: Remember to update copyright year in stdlg's AboutCallback() WM_INITDIALOG, // localization_data.sh and the .rc when the year changes! -// Set the combo selection according to the data -static void SetComboEntry(HWND hDlg, int data) { - int i; - for (i = 0; i < ComboBox_GetCount(hDlg); i++) { - if (ComboBox_GetItemData(hDlg, i) == data) { - IGNORE_RETVAL(ComboBox_SetCurSel(hDlg, i)); - break; - } - } - if (i == ComboBox_GetCount(hDlg)) - IGNORE_RETVAL(ComboBox_SetCurSel(hDlg, 0)); -} - // Fill in the cluster size names static void SetClusterSizeLabels(void) { @@ -656,6 +620,41 @@ static void SetImageOptions(void) } } +static void SetProposedLabel(int ComboIndex) +{ + const char no_label[] = STR_NO_LABEL, empty[] = ""; + + app_changed_label = TRUE; + // If bootable ISO creation is selected, and we have an ISO selected with a valid name, use that + // Also some distros (eg. Arch) require the USB to have the same label as the ISO + if ((bt == BT_IMAGE) && (image_path != NULL) && (img_report.label[0] != 0)) { + SetWindowTextU(hLabel, img_report.label); + // If we force the ISO label, we need to reset the user_changed_label flag + user_changed_label = FALSE; + return; + } + + // If the user manually changed the label, try to preserve it + if (user_changed_label) { + app_changed_label = FALSE; + return; + } + + // Empty the label if no device is currently selected + if (ComboIndex < 0) { + SetWindowTextU(hLabel, ""); + return; + } + + // Else if no existing label is available, propose one according to the size (eg: "256MB", "8GB") + if ((_stricmp(no_label, DriveLabel.String[ComboIndex]) == 0) || (_stricmp(no_label, empty) == 0) + || (safe_stricmp(lmprintf(MSG_207), DriveLabel.String[ComboIndex]) == 0)) { + SetWindowTextU(hLabel, SelectedDrive.proposed_label); + } else { + SetWindowTextU(hLabel, DriveLabel.String[ComboIndex]); + } +} + // This handles the enabling/disabling of the "Add fixes for old BIOSes" and "Use Rufus MBR" controls static void EnableMBRBootOptions(BOOL enable, BOOL remove_checkboxes) { @@ -740,41 +739,6 @@ static void EnableBootOptions(BOOL enable, BOOL remove_checkboxes) EnableWindow(GetDlgItem(hMainDialog, IDC_EXTENDED_LABEL), actual_enable); } -static void SetProposedLabel(int ComboIndex) -{ - const char no_label[] = STR_NO_LABEL, empty[] = ""; - - app_changed_label = TRUE; - // If bootable ISO creation is selected, and we have an ISO selected with a valid name, use that - // Also some distros (eg. Arch) require the USB to have the same label as the ISO - if ((bt == BT_IMAGE) && (image_path != NULL) && (img_report.label[0] != 0)) { - SetWindowTextU(hLabel, img_report.label); - // If we force the ISO label, we need to reset the user_changed_label flag - user_changed_label = FALSE; - return; - } - - // If the user manually changed the label, try to preserve it - if (user_changed_label) { - app_changed_label = FALSE; - return; - } - - // Empty the label if no device is currently selected - if (ComboIndex < 0) { - SetWindowTextU(hLabel, ""); - return; - } - - // Else if no existing label is available, propose one according to the size (eg: "256MB", "8GB") - if ((_stricmp(no_label, DriveLabel.String[ComboIndex]) == 0) || (_stricmp(no_label, empty) == 0) - || (safe_stricmp(lmprintf(MSG_207), DriveLabel.String[ComboIndex]) == 0)) { - SetWindowTextU(hLabel, SelectedDrive.proposed_label); - } else { - SetWindowTextU(hLabel, DriveLabel.String[ComboIndex]); - } -} - // Toggle controls according to operation static void EnableControls(BOOL bEnable) { @@ -865,128 +829,6 @@ out: return TRUE; } -// Set up progress bar real estate allocation -static void InitProgress(BOOL bOnlyFormat) -{ - int i; - float last_end = 0.0f, slots_discrete = 0.0f, slots_analog = 0.0f; - - memset(nb_slots, 0, sizeof(nb_slots)); - memset(slot_end, 0, sizeof(slot_end)); - previous_end = 0.0f; - - if (bOnlyFormat) { - nb_slots[OP_FORMAT] = -1; - } else { - nb_slots[OP_ANALYZE_MBR] = 1; - if (IsChecked(IDC_BAD_BLOCKS)) { - nb_slots[OP_BADBLOCKS] = -1; - } - if (bt != BT_NON_BOOTABLE) { - // 1 extra slot for PBR writing - switch (selection_default) { - case BT_MSDOS: - nb_slots[OP_DOS] = 3+1; - break; - case BT_FREEDOS: - nb_slots[OP_DOS] = 5+1; - break; - case BT_IMAGE: - nb_slots[OP_DOS] = img_report.is_iso ? -1 : 0; - break; - default: - nb_slots[OP_DOS] = 2+1; - break; - } - } - if (selection_default == BT_IMAGE && !img_report.is_iso) { - nb_slots[OP_FORMAT] = -1; - } else { - nb_slots[OP_ZERO_MBR] = 1; - nb_slots[OP_PARTITION] = 1; - nb_slots[OP_FIX_MBR] = 1; - nb_slots[OP_CREATE_FS] = - nb_steps[ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem))]; - if ( (!IsChecked(IDC_QUICK_FORMAT)) - || ((fs == FS_FAT32) && ((SelectedDrive.DiskSize >= LARGE_FAT32_SIZE) || (force_large_fat32))) ) { - nb_slots[OP_FORMAT] = -1; - } - nb_slots[OP_FINALIZE] = ((selection_default == BT_IMAGE) && (fs == FS_NTFS))?3:2; - } - } - - for (i=0; i 0) { - slots_discrete += nb_slots[i]*1.0f; - } - if (nb_slots[i] < 0) { - slots_analog += nb_slots[i]*1.0f; - } - } - - for (i=0; i 0) { - slot_end[i+1] = last_end + (1.0f * nb_slots[i]); - } else if (nb_slots[i] < 0) { - slot_end[i+1] = last_end + (( (100.0f-slots_discrete) * nb_slots[i]) / slots_analog); - } - last_end = slot_end[i+1]; - } - - // If there's no analog, adjust our discrete ends to fill the whole bar - if (slots_analog == 0.0f) { - for (i=0; i= OP_MAX)) { - duprintf("UpdateProgress: invalid op %d\n", op); - return; - } - if (percent > 100.1f) { -// duprintf("UpdateProgress(%d): invalid percentage %0.2f\n", op, percent); - return; - } - if ((percent < 0.0f) && (nb_slots[op] <= 0)) { - duprintf("UpdateProgress(%d): error negative percentage sent for negative slot value\n", op); - return; - } - if (nb_slots[op] == 0) - return; - if (previous_end < slot_end[op]) { - previous_end = slot_end[op]; - } - - if (percent < 0.0f) { - // Negative means advance one slot (1.0%) - requires a positive slot allocation - previous_end += (slot_end[op+1] - slot_end[op]) / (1.0f * nb_slots[op]); - pos = (int)(previous_end / 100.0f * MAX_PROGRESS); - } else { - pos = (int)((previous_end + ((slot_end[op+1] - previous_end) * (percent / 100.0f))) / 100.0f * MAX_PROGRESS); - } - if (pos > MAX_PROGRESS) { - duprintf("UpdateProgress(%d): rounding error - pos %d is greater than %d\n", op, pos, MAX_PROGRESS); - pos = MAX_PROGRESS; - } - - // Reduce the refresh rate, to avoid weird effects on the sliding part of progress bar - if (GetTickCount64() > LastRefresh + (2 * MAX_REFRESH)) { - LastRefresh = GetTickCount64(); - SendMessage(hProgress, PBM_SETPOS, (WPARAM)pos, 0); - SetTaskbarProgressValue(pos, MAX_PROGRESS); - } -} - // Callback for the log window BOOL CALLBACK LogCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -1160,196 +1002,6 @@ static void DisplayISOProps(void) SetImageOptions(); } -// Move a control along the Y axis -static __inline void MoveCtrlY(HWND hDlg, int nID, int vertical_shift) { - ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, nID), 0, vertical_shift, 0, 0, 1.0f); -} - -static void SetPassesTooltip(void) -{ - const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] = - { BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC }; - int sel = ComboBox_GetCurSel(hNBPasses); - int type = (sel < 2) ? 0 : sel - 2; - CreateTooltip(hNBPasses, lmprintf(MSG_153 + ((sel >= 2) ? 3 : sel), - pattern[type][0], pattern[type][1], pattern[type][2], pattern[type][3]), -1); -} - -static void ResizeDialogs(int shift) -{ - RECT rc; - POINT point; - - // Resize the main dialog - GetWindowRect(hMainDialog, &rc); - point.x = (rc.right - rc.left); - point.y = (rc.bottom - rc.top); - MoveWindow(hMainDialog, rc.left, rc.top, point.x, point.y + shift, TRUE); - - // Resize the log - GetWindowRect(hLogDialog, &rc); - point.x = (rc.right - rc.left); - point.y = (rc.bottom - rc.top); - MoveWindow(hLogDialog, rc.left, rc.top, point.x, point.y + shift, TRUE); - MoveCtrlY(hLogDialog, IDC_LOG_CLEAR, shift); - MoveCtrlY(hLogDialog, IDC_LOG_SAVE, shift); - MoveCtrlY(hLogDialog, IDCANCEL, shift); - GetWindowRect(hLog, &rc); - point.x = (rc.right - rc.left); - point.y = (rc.bottom - rc.top) + shift; - SetWindowPos(hLog, NULL, 0, 0, point.x, point.y, SWP_NOZORDER); - // Don't forget to scroll the edit to the bottom after resize - Edit_Scroll(hLog, 0, Edit_GetLineCount(hLog)); -} - -// Toggle "advanced" options -static void ToggleAdvancedDeviceOptions(BOOL enable) -{ - RECT rc; - SIZE sz; - TBBUTTONINFO button_info; - int i, shift = advanced_device_section_height; - - if (!enable) - shift = -shift; - section_vpos[1] += shift; - section_vpos[2] += shift; - - // Toggle the Hide/Show toolbar text - utf8_to_wchar_no_alloc(lmprintf((enable) ? MSG_122 : MSG_121, lmprintf(MSG_119)), wtbtext[0], ARRAYSIZE(wtbtext[0])); - button_info.cbSize = sizeof(button_info); - button_info.dwMask = TBIF_TEXT; - button_info.pszText = wtbtext[0]; - SendMessage(hAdvancedDeviceToolbar, TB_SETBUTTONINFO, (WPARAM)IDC_ADVANCED_DRIVE_PROPERTIES, (LPARAM)&button_info); - SendMessage(hAdvancedDeviceToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)((enable) ? hUpImageList : hDownImageList)); - GetWindowRect(hAdvancedDeviceToolbar, &rc); - MapWindowPoints(NULL, hMainDialog, (POINT*)&rc, 2); - SendMessage(hAdvancedDeviceToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); - SetWindowPos(hAdvancedDeviceToolbar, hTargetSystem, rc.left, rc.top, sz.cx, rc.bottom - rc.top, 0); - - // Move the controls up or down - for (i = 0; i= 2) ? 0 : row_height; - - assert(__popcnt16(mask) <= 1); - - if (mask & IMOP_WINTOGO) { - if (nWindowsVersion < WINDOWS_8) - return; - image_options ^= IMOP_WINTOGO; - // Set the Windows To Go selection in the dropdown - IGNORE_RETVAL(ComboBox_SetCurSel(GetDlgItem(hMainDialog, IDC_IMAGE_OPTION), windows_to_go_selection)); - } else if (mask & IMOP_PERSISTENCE) { - image_options ^= IMOP_PERSISTENCE; - } - - if (__popcnt16(image_options) >= 2) - shift = 0; - - if (shift != 0) { - if ((mask == 0) || (image_options == 0)) - shift = -shift; - section_vpos[1] += shift; - section_vpos[2] += shift; - - if (__popcnt16(image_options) <= 1) { - // Move the controls up or down - for (i = 0; i < ARRAYSIZE(image_option_move_ids); i++) - MoveCtrlY(hMainDialog, image_option_move_ids[i], shift); - - // Resize the main dialog and log window - ResizeDialogs(shift); - } - } - - // Hide or show the boot options - for (i = 0; i < ARRAYSIZE(image_option_toggle_ids); i++) { - ShowWindow(GetDlgItem(hMainDialog, image_option_toggle_ids[i][0]), - (image_options & image_option_toggle_ids[i][1]) ? SW_SHOW : SW_HIDE); - } - - // If you don't force a redraw here, all kind of bad UI artifacts happen... - InvalidateRect(hMainDialog, NULL, TRUE); -} - -static void SetBootTypeDropdownWidth(void) -{ - HDC hDC; - HFONT hFont; - SIZE sz; - RECT rc; - - if (image_path == NULL) - return; - // Set the maximum width of the dropdown according to the image selected - GetWindowRect(hBootType, &rc); - MapWindowPoints(NULL, hMainDialog, (POINT*)&rc, 2); - hDC = GetDC(hBootType); - hFont = (HFONT)SendMessageA(hBootType, WM_GETFONT, 0, 0); - SelectObject(hDC, hFont); - GetTextExtentPointU(hDC, short_image_path, &sz); - safe_release_dc(hBootType, hDC); - SendMessage(hBootType, CB_SETDROPPEDWIDTH, (WPARAM)max(sz.cx + 10, rc.right - rc.left), (LPARAM)0); -} - // Insert the image name into the Boot selection dropdown static void UpdateImage(void) { @@ -1812,751 +1464,6 @@ static __inline const char* IsAlphaOrBeta(void) #endif } -static INT_PTR CALLBACK ProgressCallback(HWND hCtrl, UINT message, WPARAM wParam, LPARAM lParam) -{ - HDC hDC; - RECT rc, rc2; - PAINTSTRUCT ps; - SIZE size; - LONG full_right; - wchar_t winfo[128]; - static BOOL marquee_mode = FALSE; - static uint32_t pos = 0, min = 0, max = 0xFFFF; - static COLORREF color = PROGRESS_BAR_NORMAL_COLOR; - - switch (message) { - - case PBM_SETSTATE: - switch (wParam) { - case PBST_NORMAL: - color = PROGRESS_BAR_NORMAL_COLOR; - break; - case PBST_PAUSED: - color = PROGRESS_BAR_PAUSED_COLOR; - break; - case PBST_ERROR: - color = PROGRESS_BAR_ERROR_COLOR; - break; - } - return (INT_PTR)TRUE; - - case PBM_SETRANGE: - // Don't bother sanity checking min and max: If *you* want to - // be an ass about the progress bar range, it's *your* problem. - min = (uint32_t)(lParam & 0xFFFF); - max = (uint32_t)(lParam >> 16); - return (INT_PTR)TRUE; - - case PBM_SETPOS: - pos = (WORD)wParam; - InvalidateRect(hProgress, NULL, TRUE); - return (INT_PTR)TRUE; - - case PBM_SETMARQUEE: - if ((wParam == TRUE) && (!marquee_mode)) { - marquee_mode = TRUE; - pos = min; - color = PROGRESS_BAR_NORMAL_COLOR; - SetTimer(hCtrl, TID_MARQUEE_TIMER, MARQUEE_TIMER_REFRESH, NULL); - InvalidateRect(hProgress, NULL, TRUE); - } else if ((wParam == FALSE) && (marquee_mode)) { - marquee_mode = FALSE; - KillTimer(hCtrl, TID_MARQUEE_TIMER); - pos = min; - InvalidateRect(hProgress, NULL, TRUE); - } - return (INT_PTR)TRUE; - - case WM_TIMER: - if ((wParam == TID_MARQUEE_TIMER) && marquee_mode) { - pos += max((max - min) / (1000 / MARQUEE_TIMER_REFRESH), 1); - if ((pos > max) || (pos < min)) - pos = min; - InvalidateRect(hProgress, NULL, TRUE); - return (INT_PTR)TRUE; - } - return (INT_PTR)FALSE; - - case WM_PAINT: - hDC = BeginPaint(hCtrl, &ps); - GetClientRect(hCtrl, &rc); - rc2 = rc; - InflateRect(&rc, -1, -1); - SelectObject(hDC, GetStockObject(DC_PEN)); - SelectObject(hDC, GetStockObject(NULL_BRUSH)); - // TODO: Handle SetText message so we can avoid this call - GetWindowTextW(hProgress, winfo, ARRAYSIZE(winfo)); - SelectObject(hDC, hInfoFont); - GetTextExtentPoint32(hDC, winfo, (int)wcslen(winfo), &size); - if (size.cx > rc.right) - size.cx = rc.right; - if (size.cy > rc.bottom) - size.cy = rc.bottom; - full_right = rc.right; - if (marquee_mode) { - // Optional first segment - if (pos + ((max - min) / 5) > max) { - rc.right = MulDiv(pos + ((max - min) / 5) - max, rc.right, max - min); - SetTextColor(hDC, PROGRESS_BAR_INVERTED_TEXT_COLOR); - SetBkColor(hDC, color); - ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, - ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); - rc.left = rc.right; - rc.right = full_right; - } - // Optional second segment - if (pos > min) { - rc.right = MulDiv(pos - min, rc.right, max - min); - SetTextColor(hDC, PROGRESS_BAR_NORMAL_TEXT_COLOR); - SetBkColor(hDC, PROGRESS_BAR_BACKGROUND_COLOR); - ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, - ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); - rc.left = rc.right; - rc.right = full_right; - } - // Second to last segment - rc.right = MulDiv(pos - min + ((max - min) / 5), rc.right, max - min); - SetTextColor(hDC, PROGRESS_BAR_INVERTED_TEXT_COLOR); - SetBkColor(hDC, color); - ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, - ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); - } else { - // First segment - rc.right = (pos > min) ? MulDiv(pos - min, rc.right, max - min) : rc.left; - SetTextColor(hDC, PROGRESS_BAR_INVERTED_TEXT_COLOR); - SetBkColor(hDC, color); - ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, - ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); - } - // Last segment - rc.left = rc.right; - rc.right = full_right; - SetTextColor(hDC, PROGRESS_BAR_NORMAL_TEXT_COLOR); - SetBkColor(hDC, PROGRESS_BAR_BACKGROUND_COLOR); - ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, - ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); - // Bounding rectangle - SetDCPenColor(hDC, PROGRESS_BAR_BOX_COLOR); - Rectangle(hDC, rc2.left, rc2.top, rc2.right, rc2.bottom); - EndPaint(hCtrl, &ps); - return (INT_PTR)TRUE; - } - - return CallWindowProc(progress_original_proc, hCtrl, message, wParam, lParam); -} - -// We need to create the small toolbar buttons first so that we can compute their width -static void CreateSmallButtons(HWND hDlg) -{ - HIMAGELIST hImageList; - HICON hIconSave, hIconHash; - int icon_offset = 0, i16 = GetSystemMetrics(SM_CXSMICON); - TBBUTTON tbToolbarButtons[1]; - unsigned char* buffer; - DWORD bufsize; - - if (i16 >= 28) - icon_offset = 20; - else if (i16 >= 20) - icon_offset = 10; - - hSaveToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, - 0, 0, 0, 0, hMainDialog, (HMENU)IDC_SAVE_TOOLBAR, hMainInstance, NULL); - hImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE | ILC_MIRROR, 1, 0); - buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDI_SAVE_16 + icon_offset), _RT_RCDATA, "save icon", &bufsize, FALSE); - hIconSave = CreateIconFromResourceEx(buffer, bufsize, TRUE, 0x30000, 0, 0, 0); - ImageList_AddIcon(hImageList, hIconSave); - DestroyIcon(hIconSave); - SendMessage(hSaveToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList); - SendMessage(hSaveToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); - tbToolbarButtons[0].idCommand = IDC_SAVE; - tbToolbarButtons[0].fsStyle = BTNS_AUTOSIZE; - tbToolbarButtons[0].fsState = TBSTATE_ENABLED; - tbToolbarButtons[0].iBitmap = 0; - SendMessage(hSaveToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)&tbToolbarButtons); - - hHashToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, - 0, 0, 0, 0, hMainDialog, (HMENU)IDC_HASH_TOOLBAR, hMainInstance, NULL); - hImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE | ILC_MIRROR, 1, 0); - buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDI_HASH_16 + icon_offset), _RT_RCDATA, "hash icon", &bufsize, FALSE); - hIconHash = CreateIconFromResourceEx(buffer, bufsize, TRUE, 0x30000, 0, 0, 0); - ImageList_AddIcon(hImageList, hIconHash); - DestroyIcon(hIconHash); - SendMessage(hHashToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList); - SendMessage(hHashToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); - tbToolbarButtons[0].idCommand = IDC_HASH; - tbToolbarButtons[0].fsStyle = BTNS_AUTOSIZE; - tbToolbarButtons[0].fsState = TBSTATE_ENABLED; - tbToolbarButtons[0].iBitmap = 0; - SendMessage(hHashToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)&tbToolbarButtons); -} - -static void CreateAdditionalControls(HWND hDlg) -{ - HINSTANCE hDll; - HIMAGELIST hToolbarImageList; - HICON hIcon, hIconUp, hIconDown; - RECT rc; - SIZE sz; - int icon_offset = 0, i, i16, s16, toolbar_dx = -4 - ((fScale > 1.49f) ? 1 : 0) - ((fScale > 1.99f) ? 1 : 0); - TBBUTTON tbToolbarButtons[7]; - unsigned char* buffer; - DWORD bufsize; - - s16 = i16 = GetSystemMetrics(SM_CXSMICON); - if (s16 >= 54) - s16 = 64; - else if (s16 >= 40) - s16 = 48; - else if (s16 >= 28) - s16 = 32; - else if (s16 >= 20) - s16 = 24; - if (i16 >= 28) - icon_offset = 20; - else if (i16 >= 20) - icon_offset = 10; - - // Fetch the up and down expand icons for the advanced options toolbar - hDll = GetLibraryHandle("ComDlg32"); - hIconDown = (HICON)LoadImage(hDll, MAKEINTRESOURCE(577), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); - hIconUp = (HICON)LoadImage(hDll, MAKEINTRESOURCE(578), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); - // Fallback to using Shell32 if we can't locate the icons we want in ComDlg32 - hDll = GetLibraryHandle("Shell32"); - if (hIconUp == NULL) - hIconUp = (HICON)LoadImage(hDll, MAKEINTRESOURCE(16749), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); - if (hIconDown == NULL) - hIconDown = (HICON)LoadImage(hDll, MAKEINTRESOURCE(16750), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); - hUpImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, 1, 0); - hDownImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, 1, 0); - ImageList_AddIcon(hUpImageList, hIconUp); - ImageList_AddIcon(hDownImageList, hIconDown); - - // Create the advanced options toolbars - memset(wtbtext, 0, sizeof(wtbtext)); - utf8_to_wchar_no_alloc(lmprintf((advanced_mode_device) ? MSG_122 : MSG_121, lmprintf(MSG_119)), wtbtext[0], ARRAYSIZE(wtbtext[0])); - hAdvancedDeviceToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, - 0, 0, 0, 0, hMainDialog, (HMENU)IDC_ADVANCED_DEVICE_TOOLBAR, hMainInstance, NULL); - SendMessage(hAdvancedDeviceToolbar, CCM_SETVERSION, (WPARAM)6, 0); - memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); - tbToolbarButtons[0].idCommand = IDC_ADVANCED_DRIVE_PROPERTIES; - tbToolbarButtons[0].fsStyle = BTNS_SHOWTEXT | BTNS_AUTOSIZE; - tbToolbarButtons[0].fsState = TBSTATE_ENABLED; - tbToolbarButtons[0].iString = (INT_PTR)wtbtext[0]; - tbToolbarButtons[0].iBitmap = 0; - SendMessage(hAdvancedDeviceToolbar, TB_SETIMAGELIST, 0, (LPARAM)hUpImageList); - SendMessage(hAdvancedDeviceToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - SendMessage(hAdvancedDeviceToolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbToolbarButtons); - GetWindowRect(GetDlgItem(hDlg, IDC_ADVANCED_DRIVE_PROPERTIES), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - SendMessage(hAdvancedDeviceToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); - // Yeah, so, like, TB_GETIDEALSIZE totally super doesn't work on Windows 7, for low zoom factor and when compiled with MSVC... - if (sz.cx < 16) - sz.cx = fw; - SetWindowPos(hAdvancedDeviceToolbar, hTargetSystem, rc.left + toolbar_dx, rc.top, sz.cx, rc.bottom - rc.top, 0); - - utf8_to_wchar_no_alloc(lmprintf((advanced_mode_format) ? MSG_122 : MSG_121, lmprintf(MSG_120)), wtbtext[1], ARRAYSIZE(wtbtext[1])); - hAdvancedFormatToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, - 0, 0, 0, 0, hMainDialog, (HMENU)IDC_ADVANCED_FORMAT_TOOLBAR, hMainInstance, NULL); - SendMessage(hAdvancedFormatToolbar, CCM_SETVERSION, (WPARAM)6, 0); - memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); - tbToolbarButtons[0].idCommand = IDC_ADVANCED_FORMAT_OPTIONS; - tbToolbarButtons[0].fsStyle = BTNS_SHOWTEXT | BTNS_AUTOSIZE; - tbToolbarButtons[0].fsState = TBSTATE_ENABLED; - tbToolbarButtons[0].iString = (INT_PTR)wtbtext[1]; - tbToolbarButtons[0].iBitmap = 0; - SendMessage(hAdvancedFormatToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hUpImageList); - SendMessage(hAdvancedFormatToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - SendMessage(hAdvancedFormatToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)&tbToolbarButtons); - GetWindowRect(GetDlgItem(hDlg, IDC_ADVANCED_FORMAT_OPTIONS), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - SendMessage(hAdvancedFormatToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); - if (sz.cx < 16) - sz.cx = fw; - SetWindowPos(hAdvancedFormatToolbar, hClusterSize, rc.left + toolbar_dx, rc.top, sz.cx, rc.bottom - rc.top, 0); - - // Create the multi toolbar - hMultiToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, - 0, 0, 0, 0, hMainDialog, (HMENU)IDC_MULTI_TOOLBAR, hMainInstance, NULL); - hToolbarImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, 8, 0); - for (i = 0; i < ARRAYSIZE(multitoolbar_icons); i++) { - buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(multitoolbar_icons[i] + icon_offset), - _RT_RCDATA, "toolbar icon", &bufsize, FALSE); - hIcon = CreateIconFromResourceEx(buffer, bufsize, TRUE, 0x30000, 0, 0, 0); - // Mirror the "world" icon on RTL since we can't use an ImageList mirroring flag for that... - if (right_to_left_mode && (i == 0)) - hIcon = CreateMirroredIcon(hIcon); - ImageList_AddIcon(hToolbarImageList, hIcon); - DestroyIcon(hIcon); - } - SendMessage(hMultiToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hToolbarImageList); - SendMessage(hMultiToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - memset(tbToolbarButtons, 0, sizeof(TBBUTTON) * ARRAYSIZE(tbToolbarButtons)); - tbToolbarButtons[0].idCommand = IDC_LANG; - tbToolbarButtons[0].fsStyle = BTNS_BUTTON; - tbToolbarButtons[0].fsState = TBSTATE_ENABLED; - tbToolbarButtons[0].iBitmap = 0; - tbToolbarButtons[1].fsStyle = BTNS_AUTOSIZE; - tbToolbarButtons[1].fsState = TBSTATE_INDETERMINATE; - tbToolbarButtons[1].iBitmap = I_IMAGENONE; - tbToolbarButtons[1].iString = (fScale < 1.5f) ? (INT_PTR)L"" : (INT_PTR)L" "; - tbToolbarButtons[2].idCommand = IDC_ABOUT; - tbToolbarButtons[2].fsStyle = BTNS_BUTTON; - tbToolbarButtons[2].fsState = TBSTATE_ENABLED; - tbToolbarButtons[2].iBitmap = 1; - tbToolbarButtons[3].fsStyle = BTNS_AUTOSIZE; - tbToolbarButtons[3].fsState = TBSTATE_INDETERMINATE; - tbToolbarButtons[3].iBitmap = I_IMAGENONE; - tbToolbarButtons[3].iString = (fScale < 1.5f) ? (INT_PTR)L"" : (INT_PTR)L" "; - tbToolbarButtons[4].idCommand = IDC_SETTINGS; - tbToolbarButtons[4].fsStyle = BTNS_BUTTON; - tbToolbarButtons[4].fsState = TBSTATE_ENABLED; - tbToolbarButtons[4].iBitmap = 2; - tbToolbarButtons[5].fsStyle = BTNS_AUTOSIZE; - tbToolbarButtons[5].fsState = TBSTATE_INDETERMINATE; - tbToolbarButtons[5].iBitmap = I_IMAGENONE; - tbToolbarButtons[5].iString = (fScale < 1.5f) ? (INT_PTR)L"" : (INT_PTR)L" "; - tbToolbarButtons[6].idCommand = IDC_LOG; - tbToolbarButtons[6].fsStyle = BTNS_BUTTON; - tbToolbarButtons[6].fsState = TBSTATE_ENABLED; - tbToolbarButtons[6].iBitmap = 3; - SendMessage(hMultiToolbar, TB_ADDBUTTONS, (WPARAM)7, (LPARAM)&tbToolbarButtons); - SendMessage(hMultiToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(i16, ddbh)); -} - -// https://stackoverflow.com/a/20926332/1069307 -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818.aspx -static void GetBasicControlsWidth(HWND hDlg) -{ - int checkbox_internal_spacing = 12, dropdown_internal_spacing = 15; - RECT rc = { 0, 0, 4, 8 }; - SIZE sz; - - // Compute base unit sizes since GetDialogBaseUnits() returns garbage data. - // See http://support.microsoft.com/kb/125681 - MapDialogRect(hDlg, &rc); - sz.cx = rc.right; - sz.cy = rc.bottom; - - // TODO: figure out the specifics of each Windows version - if (nWindowsVersion == WINDOWS_10) { - checkbox_internal_spacing = 10; - dropdown_internal_spacing = 13; - } - - // Checkbox and (blank) dropdown widths - cbw = MulDiv(checkbox_internal_spacing, sz.cx, 4); - ddw = MulDiv(dropdown_internal_spacing, sz.cx, 4); - - // Spacing width between half-length dropdowns (sep) as well as left margin - GetWindowRect(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - sw = rc.left; - GetWindowRect(GetDlgItem(hDlg, IDC_PARTITION_TYPE), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - sw -= rc.right; - mw = rc.left; - - // Small button width - SendMessage(hSaveToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); - sbw = sz.cx; - - // Small separator widths and button height - GetWindowRect(GetDlgItem(hDlg, IDC_SAVE), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - bh = rc.bottom - rc.top; - ssw = rc.left; - GetWindowRect(hDeviceList, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - ssw -= rc.right; - - // CSM tooltip separator width - GetWindowRect(GetDlgItem(hDlg, IDS_CSM_HELP_TXT), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - tw = rc.left; - GetWindowRect(hTargetSystem, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - tw -= rc.right; -} - -// Compute the minimum size of the main buttons -static void GetMainButtonsWidth(HWND hDlg) -{ - unsigned int i; - RECT rc; - - GetWindowRect(GetDlgItem(hDlg, main_button_ids[0]), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - bw = rc.right - rc.left; - - for (i = 0; i < ARRAYSIZE(main_button_ids); i++) - bw = max(bw, GetTextWidth(hDlg, main_button_ids[i]) + cbw); - // The 'CLOSE' button is also be used to display 'CANCEL' => measure that too - bw = max(bw, GetTextSize(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)).cx + cbw); -} - -// The following goes over the data that gets populated into the half-width dropdowns -// (Partition scheme, Target System, Disk ID, File system, Cluster size, Nb passes) -// to figure out the minimum width we should allocate. -static void GetHalfDropwdownWidth(HWND hDlg) -{ - RECT rc; - unsigned int i, j, msg_id; - char tmp[256]; - - // Initialize half width to the UI's default size - GetWindowRect(GetDlgItem(hDlg, IDC_PARTITION_TYPE), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - hw = rc.right - rc.left - ddw; - - // "Super Floppy Disk" is the longuest entry in the Partition Scheme dropdown - hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_PARTITION_TYPE), (char*)sfd_name).cx); - - // This is basically the same as SetClusterSizeLabels() except we're adding (Default) to each entry - for (i = 512, j = 1, msg_id = MSG_026; j 8192) { - i /= 1024; - msg_id++; - } - safe_sprintf(tmp, 64, "%d %s", i, lmprintf(msg_id)); - hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_CLUSTER_SIZE), lmprintf(MSG_030, tmp)).cx); - } - // We don't go over file systems, because none of them will be longer than "Super Floppy Disk" - // We do however go over the BIOS vs UEFI entries, as some of these are translated - for (msg_id = MSG_031; msg_id <= MSG_033; msg_id++) - hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), lmprintf(msg_id)).cx); - - // Just in case, we also do the number of passes - for (i = 1; i <= 5; i++) { - char* msg = (i == 1) ? lmprintf(MSG_034, 1) : lmprintf(MSG_035, (i == 2) ? 2 : 4, (i == 2) ? "" : lmprintf(MSG_087, flash_type[i - 3])); - hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), msg).cx); - } - - // Finally, we must ensure that we'll have enough space for the 2 checkbox controls - // that end up with a half dropdown - hw = max(hw, GetTextWidth(hDlg, IDC_RUFUS_MBR) - sw); - hw = max(hw, GetTextWidth(hDlg, IDC_BAD_BLOCKS) - sw); - - // Add the width of a blank dropdown - hw += ddw; -} - -/* - * dbw = dialog border width - * mw = margin width - * fw = full dropdown width - * hd = half dropdown width - * bsw = boot selection dropdown width - * sw = separator width - * ssw = small separator width - * bw = button width - * sbw = small button width - * - * | fw | - * | bsw | ssw | sbw | ssw | bw | - * 8 ->|<- 96 ->|<- 24 ->|<- 96 ->|<- 8 - * mw | hw | sw | hw | mw - * | bw | ssw | bw | - */ -static void GetFullWidth(HWND hDlg) -{ - RECT rc; - int i; - - // Get the dialog border width - GetWindowRect(hDlg, &rc); - dbw = rc.right - rc.left; - GetClientRect(hDlg, &rc); - dbw -= rc.right - rc.left; - - // Compute the minimum size needed for the Boot Selection dropdown - GetWindowRect(GetDlgItem(hDlg, IDC_BOOT_SELECTION), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - - bsw = max(rc.right - rc.left, GetTextSize(hBootType, lmprintf(MSG_279)).cx + ddw); - bsw = max(bsw, GetTextSize(hBootType, lmprintf(MSG_281, lmprintf(MSG_280))).cx + ddw); - - // Initialize full width to the UI's default size - GetWindowRect(GetDlgItem(hDlg, IDC_IMAGE_OPTION), &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - fw = rc.right - rc.left - ddw; - - // Go through the Image Options for Windows To Go - fw = max(fw, GetTextSize(GetDlgItem(hDlg, IDC_IMAGE_OPTION), lmprintf(MSG_117)).cx); - fw = max(fw, GetTextSize(GetDlgItem(hDlg, IDC_IMAGE_OPTION), lmprintf(MSG_118)).cx); - - // Now deal with full length checkbox lines - for (i=0; i> 16; - SendMessage(hSaveToolbar, TB_SETPADDING, 0, MAKELPARAM(sz.cx + 3, sz.cy + 2)); - SetWindowPos(hSaveToolbar, hDeviceList, mw + fw - sbw, rc.top, sbw, ddbh, 0); - - // Reposition the Hash button - hCtrl = GetDlgItem(hDlg, IDC_HASH); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - SendMessage(hHashToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); - SendMessage(hHashToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(sz.cx, ddbh)); - padding = (DWORD) SendMessage(hHashToolbar, TB_GETPADDING, 0, 0); - sz.cx = padding & 0xFFFF; - sz.cy = padding >> 16; - SendMessage(hHashToolbar, TB_SETPADDING, 0, MAKELPARAM(sz.cx + 3, sz.cy + 2)); - SetWindowPos(hHashToolbar, hBootType, mw + bsw + ssw, rc.top, sbw, ddbh, 0); - - // Reposition the CSM help tip - hCtrl = GetDlgItem(hDlg, IDS_CSM_HELP_TXT); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - SetWindowPos(hCtrl, hTargetSystem, mw + fw + tw, rc.top, sbw, rc.bottom - rc.top, 0); - - if (advanced_mode_device) { - // Still need to adjust the width of the device selection dropdown - GetWindowRect(hDeviceList, &rc); - MapWindowPoints(NULL, hMainDialog, (POINT*)&rc, 2); - SetWindowPos(hDeviceList, HWND_TOP, rc.left, rc.top, fw - ssw - sbw, rc.bottom - rc.top, 0); - } - - // Resize the full width controls - for (i = 0; i < ARRAYSIZE(full_width_controls); i++) { - hCtrl = GetDlgItem(hDlg, full_width_controls[i]); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); - SetWindowPos(hCtrl, hPrevCtrl, rc.left, rc.top, fw, rc.bottom - rc.top, 0); - } - - // Resize the half drowpdowns - for (i = 0; i < ARRAYSIZE(half_width_ids); i++) { - hCtrl = GetDlgItem(hDlg, half_width_ids[i]); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - // First 5 controls are on the left handside - // First 2 controls may overflow into separator - hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); - SetWindowPos(hCtrl, hPrevCtrl, (i < 5) ? rc.left : mw + hw + sw, rc.top, - (i <2) ? hw + sw : hw, rc.bottom - rc.top, 0); - } - - // Resize the boot selection dropdown - hCtrl = GetDlgItem(hDlg, IDC_BOOT_SELECTION); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); - SetWindowPos(hCtrl, hPrevCtrl, rc.left, rc.top, bsw, rc.bottom - rc.top, 0); -} - -// Thanks to Microsoft atrocious DPI handling, we must adjust for low DPI -static void AdjustForLowDPI(HWND hDlg) -{ - static int ddy = 4; - int i, j; - RECT rc; - HWND hCtrl, hPrevCtrl; - int dy = 0; - - if (fScale >= 1.3f) - return; - - for (i = 0; i < ARRAYSIZE(adjust_dpi_ids); i++) { - dy += ddy; - // "...and the other thing I really like about Microsoft's UI handling is how " - //."you never have to introduce weird hardcoded constants all over the place, " - // "just to make your UI look good...", said NO ONE ever. - if (adjust_dpi_ids[i][0] == IDC_QUICK_FORMAT) - dy += 1; - for (j = 0; j < 5; j++) { - if (adjust_dpi_ids[i][j] == 0) - break; - hCtrl = GetDlgItem(hDlg, adjust_dpi_ids[i][j]); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); - SetWindowPos(hCtrl, hPrevCtrl, rc.left, rc.top + dy, - rc.right - rc.left, rc.bottom - rc.top, 0); - } - } - - section_vpos[1] += 9 * ddy; - section_vpos[2] += 16 * ddy + 1; - advanced_device_section_height += 3 * ddy; - advanced_format_section_height += 3 * ddy + 1; - - ResizeDialogs(dy + 2*ddy); - InvalidateRect(hDlg, NULL, TRUE); -} - -static void SetSectionHeaders(HWND hDlg) -{ - RECT rc; - HWND hCtrl; - SIZE sz; - HFONT hf; - wchar_t wtmp[128]; - size_t wlen; - int i; - - // Set the section header fonts and resize the static controls accordingly - hf = CreateFontA(-MulDiv(14, GetDeviceCaps(GetDC(hMainDialog), LOGPIXELSY), 72), 0, 0, 0, - FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0, PROOF_QUALITY, 0, "Segoe UI"); - - for (i = 0; i < ARRAYSIZE(section_control_ids); i++) { - SendDlgItemMessageA(hDlg, section_control_ids[i], WM_SETFONT, (WPARAM)hf, TRUE); - hCtrl = GetDlgItem(hDlg, section_control_ids[i]); - memset(wtmp, 0, sizeof(wtmp)); - GetWindowTextW(hCtrl, wtmp, ARRAYSIZE(wtmp)); - wlen = wcslen(wtmp); - wtmp[wlen++] = L' '; - wtmp[wlen++] = L' '; - SetWindowTextW(hCtrl, wtmp); - GetWindowRect(hCtrl, &rc); - MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); - sz = GetTextSize(hCtrl, NULL); - SetWindowPos(hCtrl, NULL, rc.left, rc.top, sz.cx, sz.cy, SWP_NOZORDER); - } -} - -// Create the horizontal section lines -void OnPaint(HDC hdc) -{ - int i; - HPEN hp = CreatePen(0, (fScale < 1.5f)?2:3, RGB(0, 0, 0)); - SelectObject(hdc, hp); - for (i = 0; i < ARRAYSIZE(section_vpos); i++) { - MoveToEx(hdc, mw + 10, section_vpos[i], NULL); - LineTo(hdc, mw + fw, section_vpos[i]); - } -} - static void InitDialog(HWND hDlg) { DWORD len; @@ -2703,16 +1610,13 @@ static void InitDialog(HWND hDlg) CreateAdditionalControls(hDlg); SetSectionHeaders(hDlg); - PositionControls(hDlg); + PositionMainControls(hDlg); AdjustForLowDPI(hDlg); // Because we created the log dialog before we computed our sizes, we need to send a custom message SendMessage(hLogDialog, UM_RESIZE_BUTTONS, 0, 0); // Create the status line and initialize the taskbar icon for progress overlay CreateStatusBar(); - // Subclass the progress bar so that we can write on it - progress_original_proc = (WNDPROC)SetWindowLongPtr(hProgress, GWLP_WNDPROC, (LONG_PTR)ProgressCallback); - // Set the various tooltips CreateTooltip(hFileSystem, lmprintf(MSG_157), -1); CreateTooltip(hClusterSize, lmprintf(MSG_158), -1); @@ -2757,41 +1661,6 @@ static void PrintStatusTimeout(const char* str, BOOL val) PrintStatus(STATUS_MSG_TIMEOUT, (val)?MSG_250:MSG_251, str); } -static void ShowLanguageMenu(RECT rcExclude) -{ - TPMPARAMS tpm; - HMENU menu; - loc_cmd* lcmd = NULL; - char lang[256]; - char *search = "()"; - char *l, *r, *str; - - UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; - menu = CreatePopupMenu(); - list_for_each_entry(lcmd, &locale_list, loc_cmd, list) { - // The appearance of LTR languages must be fixed for RTL menus - if ((right_to_left_mode) && (!(lcmd->ctrl_id & LOC_RIGHT_TO_LEFT))) { - str = safe_strdup(lcmd->txt[1]); - l = strtok(str, search); - r = strtok(NULL, search); - static_sprintf(lang, LEFT_TO_RIGHT_EMBEDDING "(%s) " POP_DIRECTIONAL_FORMATTING "%s", r, l); - safe_free(str); - } else { - static_strcpy(lang, lcmd->txt[1]); - } - InsertMenuU(menu, -1, MF_BYPOSITION|((selected_locale == lcmd)?MF_CHECKED:0), UM_LANGUAGE_MENU_MAX++, lang); - } - - // Open the menu such that it doesn't overlap the specified rect - tpm.cbSize = sizeof(TPMPARAMS); - tpm.rcExclude = rcExclude; - TrackPopupMenuEx(menu, 0, - right_to_left_mode ? rcExclude.right : rcExclude.left, // In RTL languages, the menu should be placed at the bottom-right of the rect - rcExclude.bottom, hMainDialog, &tpm); - - DestroyMenu(menu); -} - static void SaveVHD(void) { static IMG_SAVE img_save = { 0 }; @@ -3013,7 +1882,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case WM_COMMAND: #ifdef RUFUS_TEST if (LOWORD(wParam) == IDC_TEST) { - DownloadSignedFile(FILES_URL "/gendb.sh", "C:\\Downloads\\gendb.sh", hProgress); + DownloadSignedFile(FILES_URL "/gendb.sh", "C:\\Downloads\\gendb.sh", hProgress, TRUE); break; } #endif diff --git a/src/rufus.h b/src/rufus.h index ebd649df..d6eb8e4f 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -428,6 +428,7 @@ extern char* image_path; /* * Shared prototypes */ +extern uint8_t popcnt8(uint8_t val); extern void GetWindowsVersion(void); extern BOOL is_x64(void); extern const char *WindowsErrorString(void); diff --git a/src/rufus.rc b/src/rufus.rc index b05e202e..e09246f2 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 3.2.1329" +CAPTION "Rufus 3.2.1330" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -392,8 +392,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,2,1329,0 - PRODUCTVERSION 3,2,1329,0 + FILEVERSION 3,2,1330,0 + PRODUCTVERSION 3,2,1330,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -410,13 +410,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.2.1329" + VALUE "FileVersion", "3.2.1330" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.2.1329" + VALUE "ProductVersion", "3.2.1330" END END BLOCK "VarFileInfo" diff --git a/src/stdfn.c b/src/stdfn.c index 6f0890b6..be1c6c8c 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -36,6 +36,16 @@ int nWindowsVersion = WINDOWS_UNDEFINED; int nWindowsBuildNumber = -1; char WindowsVersionStr[128] = "Windows "; +// __popcnt16, __popcnt, __popcnt64 are not available for ARM :( +uint8_t popcnt8(uint8_t val) +{ + static const uint8_t nibble_lookup[16] = { + 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 + }; + return nibble_lookup[val & 0x0F] + nibble_lookup[val >> 4]; +} + /* * Hash table functions - modified From glibc 2.3.2: * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 diff --git a/src/stdlg.c b/src/stdlg.c index 6032f1f2..a7067b1d 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -37,6 +37,7 @@ #include "resource.h" #include "msapi_utf8.h" #include "localization.h" +#include "ui.h" #include "registry.h" #include "settings.h" @@ -58,9 +59,6 @@ static WNDPROC update_original_proc = NULL; static HWINEVENTHOOK fp_weh = NULL; static char *fp_title_str = "Microsoft Windows", *fp_button_str = "Format disk"; -extern loc_cmd* selected_locale; -extern int cbw, ddw, ddbh, bh; - static int update_settings_reposition_ids[] = { IDC_POLICY, IDS_UPDATE_SETTINGS_GRP, diff --git a/src/ui.c b/src/ui.c new file mode 100644 index 00000000..5251f85f --- /dev/null +++ b/src/ui.c @@ -0,0 +1,1177 @@ +/* + * Rufus: The Reliable USB Formatting Utility + * UI-related function calls + * Copyright © 2018 Pete Batard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + /* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rufus.h" +#include "drive.h" +#include "missing.h" +#include "resource.h" +#include "msapi_utf8.h" +#include "localization.h" + +#include "ui.h" +#include "ui_data.h" + +UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; +HIMAGELIST hUpImageList, hDownImageList; +int advanced_device_section_height, advanced_format_section_height; +// (empty) check box width, (empty) drop down width, button height (for and without dropdown match) +int cbw, ddw, ddbh = 0, bh = 0; +// Row Height, DropDown Height, Main button width, half dropdown width, full dropdown width +static int rh, ddh, bw, hw, fw; +// See GetFullWidth() for details on how these values are used +static int sw, mw, bsw, sbw, ssw, tw, dbw; +static WNDPROC progress_original_proc = NULL; +static wchar_t wtbtext[2][128]; + +/* + * The following is used to allocate slots within the progress bar + * 0 means unused (no operation or no progress allocated to it) + * +n means allocate exactly n bars (n percent of the progress bar) + * -n means allocate a weighted slot of n from all remaining + * bars. E.g. if 80 slots remain and the sum of all negative entries + * is 10, -4 will allocate 4/10*80 = 32 bars (32%) for OP progress + */ +static int nb_slots[OP_MAX]; +static float slot_end[OP_MAX+1]; // shifted +1 so that we can subtract 1 to OP indexes +static float previous_end; + +// Set the combo selection according to the data +void SetComboEntry(HWND hDlg, int data) +{ + int i; + for (i = 0; i < ComboBox_GetCount(hDlg); i++) { + if (ComboBox_GetItemData(hDlg, i) == data) { + IGNORE_RETVAL(ComboBox_SetCurSel(hDlg, i)); + break; + } + } + if (i == ComboBox_GetCount(hDlg)) + IGNORE_RETVAL(ComboBox_SetCurSel(hDlg, 0)); +} + +// Move a control along the Y axis +static __inline void MoveCtrlY(HWND hDlg, int nID, int vertical_shift) { + ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, nID), 0, vertical_shift, 0, 0, 1.0f); +} + +// https://stackoverflow.com/a/20926332/1069307 +// https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818.aspx +void GetBasicControlsWidth(HWND hDlg) +{ + int checkbox_internal_spacing = 12, dropdown_internal_spacing = 15; + RECT rc = { 0, 0, 4, 8 }; + SIZE sz; + + // Compute base unit sizes since GetDialogBaseUnits() returns garbage data. + // See http://support.microsoft.com/kb/125681 + MapDialogRect(hDlg, &rc); + sz.cx = rc.right; + sz.cy = rc.bottom; + + // TODO: figure out the specifics of each Windows version + if (nWindowsVersion == WINDOWS_10) { + checkbox_internal_spacing = 10; + dropdown_internal_spacing = 13; + } + + // Checkbox and (blank) dropdown widths + cbw = MulDiv(checkbox_internal_spacing, sz.cx, 4); + ddw = MulDiv(dropdown_internal_spacing, sz.cx, 4); + + // Spacing width between half-length dropdowns (sep) as well as left margin + GetWindowRect(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + sw = rc.left; + GetWindowRect(GetDlgItem(hDlg, IDC_PARTITION_TYPE), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + sw -= rc.right; + mw = rc.left; + + // Small button width + SendMessage(hSaveToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); + sbw = sz.cx; + + // Small separator widths and button height + GetWindowRect(GetDlgItem(hDlg, IDC_SAVE), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + bh = rc.bottom - rc.top; + ssw = rc.left; + GetWindowRect(hDeviceList, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + ssw -= rc.right; + + // CSM tooltip separator width + GetWindowRect(GetDlgItem(hDlg, IDS_CSM_HELP_TXT), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + tw = rc.left; + GetWindowRect(hTargetSystem, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + tw -= rc.right; +} + +// Compute the minimum size of the main buttons +void GetMainButtonsWidth(HWND hDlg) +{ + unsigned int i; + RECT rc; + + GetWindowRect(GetDlgItem(hDlg, main_button_ids[0]), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + bw = rc.right - rc.left; + + for (i = 0; i < ARRAYSIZE(main_button_ids); i++) + bw = max(bw, GetTextWidth(hDlg, main_button_ids[i]) + cbw); + // The 'CLOSE' button is also be used to display 'CANCEL' => measure that too + bw = max(bw, GetTextSize(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)).cx + cbw); +} + +// The following goes over the data that gets populated into the half-width dropdowns +// (Partition scheme, Target System, Disk ID, File system, Cluster size, Nb passes) +// to figure out the minimum width we should allocate. +void GetHalfDropwdownWidth(HWND hDlg) +{ + RECT rc; + unsigned int i, j, msg_id; + char tmp[256]; + + // Initialize half width to the UI's default size + GetWindowRect(GetDlgItem(hDlg, IDC_PARTITION_TYPE), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + hw = rc.right - rc.left - ddw; + + // "Super Floppy Disk" is the longuest entry in the Partition Scheme dropdown + hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_PARTITION_TYPE), (char*)sfd_name).cx); + + // This is basically the same as SetClusterSizeLabels() except we're adding (Default) to each entry + for (i = 512, j = 1, msg_id = MSG_026; j 8192) { + i /= 1024; + msg_id++; + } + safe_sprintf(tmp, 64, "%d %s", i, lmprintf(msg_id)); + hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_CLUSTER_SIZE), lmprintf(MSG_030, tmp)).cx); + } + // We don't go over file systems, because none of them will be longer than "Super Floppy Disk" + // We do however go over the BIOS vs UEFI entries, as some of these are translated + for (msg_id = MSG_031; msg_id <= MSG_033; msg_id++) + hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), lmprintf(msg_id)).cx); + + // Just in case, we also do the number of passes + for (i = 1; i <= 5; i++) { + char* msg = (i == 1) ? lmprintf(MSG_034, 1) : lmprintf(MSG_035, (i == 2) ? 2 : 4, (i == 2) ? "" : lmprintf(MSG_087, flash_type[i - 3])); + hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), msg).cx); + } + + // Finally, we must ensure that we'll have enough space for the 2 checkbox controls + // that end up with a half dropdown + hw = max(hw, GetTextWidth(hDlg, IDC_RUFUS_MBR) - sw); + hw = max(hw, GetTextWidth(hDlg, IDC_BAD_BLOCKS) - sw); + + // Add the width of a blank dropdown + hw += ddw; +} + +/* +* dbw = dialog border width +* mw = margin width +* fw = full dropdown width +* hd = half dropdown width +* bsw = boot selection dropdown width +* sw = separator width +* ssw = small separator width +* bw = button width +* sbw = small button width +* +* | fw | +* | bsw | ssw | sbw | ssw | bw | +* 8 ->|<- 96 ->|<- 24 ->|<- 96 ->|<- 8 +* mw | hw | sw | hw | mw +* | bw | ssw | bw | +*/ +void GetFullWidth(HWND hDlg) +{ + RECT rc; + int i; + + // Get the dialog border width + GetWindowRect(hDlg, &rc); + dbw = rc.right - rc.left; + GetClientRect(hDlg, &rc); + dbw -= rc.right - rc.left; + + // Compute the minimum size needed for the Boot Selection dropdown + GetWindowRect(GetDlgItem(hDlg, IDC_BOOT_SELECTION), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + + bsw = max(rc.right - rc.left, GetTextSize(hBootType, lmprintf(MSG_279)).cx + ddw); + bsw = max(bsw, GetTextSize(hBootType, lmprintf(MSG_281, lmprintf(MSG_280))).cx + ddw); + + // Initialize full width to the UI's default size + GetWindowRect(GetDlgItem(hDlg, IDC_IMAGE_OPTION), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + fw = rc.right - rc.left - ddw; + + // Go through the Image Options for Windows To Go + fw = max(fw, GetTextSize(GetDlgItem(hDlg, IDC_IMAGE_OPTION), lmprintf(MSG_117)).cx); + fw = max(fw, GetTextSize(GetDlgItem(hDlg, IDC_IMAGE_OPTION), lmprintf(MSG_118)).cx); + + // Now deal with full length checkbox lines + for (i = 0; i> 16; + SendMessage(hSaveToolbar, TB_SETPADDING, 0, MAKELPARAM(sz.cx + 3, sz.cy + 2)); + SetWindowPos(hSaveToolbar, hDeviceList, mw + fw - sbw, rc.top, sbw, ddbh, 0); + + // Reposition the Hash button + hCtrl = GetDlgItem(hDlg, IDC_HASH); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SendMessage(hHashToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); + SendMessage(hHashToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(sz.cx, ddbh)); + padding = (DWORD)SendMessage(hHashToolbar, TB_GETPADDING, 0, 0); + sz.cx = padding & 0xFFFF; + sz.cy = padding >> 16; + SendMessage(hHashToolbar, TB_SETPADDING, 0, MAKELPARAM(sz.cx + 3, sz.cy + 2)); + SetWindowPos(hHashToolbar, hBootType, mw + bsw + ssw, rc.top, sbw, ddbh, 0); + + // Reposition the CSM help tip + hCtrl = GetDlgItem(hDlg, IDS_CSM_HELP_TXT); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SetWindowPos(hCtrl, hTargetSystem, mw + fw + tw, rc.top, sbw, rc.bottom - rc.top, 0); + + if (advanced_mode_device) { + // Still need to adjust the width of the device selection dropdown + GetWindowRect(hDeviceList, &rc); + MapWindowPoints(NULL, hMainDialog, (POINT*)&rc, 2); + SetWindowPos(hDeviceList, HWND_TOP, rc.left, rc.top, fw - ssw - sbw, rc.bottom - rc.top, 0); + } + + // Resize the full width controls + for (i = 0; i < ARRAYSIZE(full_width_controls); i++) { + hCtrl = GetDlgItem(hDlg, full_width_controls[i]); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); + SetWindowPos(hCtrl, hPrevCtrl, rc.left, rc.top, fw, rc.bottom - rc.top, 0); + } + + // Resize the half drowpdowns + for (i = 0; i < ARRAYSIZE(half_width_ids); i++) { + hCtrl = GetDlgItem(hDlg, half_width_ids[i]); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + // First 5 controls are on the left handside + // First 2 controls may overflow into separator + hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); + SetWindowPos(hCtrl, hPrevCtrl, (i < 5) ? rc.left : mw + hw + sw, rc.top, + (i <2) ? hw + sw : hw, rc.bottom - rc.top, 0); + } + + // Resize the boot selection dropdown + hCtrl = GetDlgItem(hDlg, IDC_BOOT_SELECTION); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); + SetWindowPos(hCtrl, hPrevCtrl, rc.left, rc.top, bsw, rc.bottom - rc.top, 0); +} + +static void ResizeDialogs(int shift) +{ + RECT rc; + POINT point; + + // Resize the main dialog + GetWindowRect(hMainDialog, &rc); + point.x = (rc.right - rc.left); + point.y = (rc.bottom - rc.top); + MoveWindow(hMainDialog, rc.left, rc.top, point.x, point.y + shift, TRUE); + + // Resize the log + GetWindowRect(hLogDialog, &rc); + point.x = (rc.right - rc.left); + point.y = (rc.bottom - rc.top); + MoveWindow(hLogDialog, rc.left, rc.top, point.x, point.y + shift, TRUE); + MoveCtrlY(hLogDialog, IDC_LOG_CLEAR, shift); + MoveCtrlY(hLogDialog, IDC_LOG_SAVE, shift); + MoveCtrlY(hLogDialog, IDCANCEL, shift); + GetWindowRect(hLog, &rc); + point.x = (rc.right - rc.left); + point.y = (rc.bottom - rc.top) + shift; + SetWindowPos(hLog, NULL, 0, 0, point.x, point.y, SWP_NOZORDER); + // Don't forget to scroll the edit to the bottom after resize + Edit_Scroll(hLog, 0, Edit_GetLineCount(hLog)); +} + +// Thanks to Microsoft atrocious DPI handling, we must adjust for low DPI +void AdjustForLowDPI(HWND hDlg) +{ + static int ddy = 4; + int i, j; + RECT rc; + HWND hCtrl, hPrevCtrl; + int dy = 0; + + if (fScale >= 1.3f) + return; + + for (i = 0; i < ARRAYSIZE(adjust_dpi_ids); i++) { + dy += ddy; + // "...and the other thing I really like about Microsoft's UI handling is how " + //."you never have to introduce weird hardcoded constants all over the place, " + // "just to make your UI look good...", said NO ONE ever. + if (adjust_dpi_ids[i][0] == IDC_QUICK_FORMAT) + dy += 1; + for (j = 0; j < 5; j++) { + if (adjust_dpi_ids[i][j] == 0) + break; + hCtrl = GetDlgItem(hDlg, adjust_dpi_ids[i][j]); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + hPrevCtrl = GetNextWindow(hCtrl, GW_HWNDPREV); + SetWindowPos(hCtrl, hPrevCtrl, rc.left, rc.top + dy, + rc.right - rc.left, rc.bottom - rc.top, 0); + } + } + + section_vpos[1] += 9 * ddy; + section_vpos[2] += 16 * ddy + 1; + advanced_device_section_height += 3 * ddy; + advanced_format_section_height += 3 * ddy + 1; + + ResizeDialogs(dy + 2 * ddy); + InvalidateRect(hDlg, NULL, TRUE); +} + +void SetSectionHeaders(HWND hDlg) +{ + RECT rc; + HWND hCtrl; + SIZE sz; + HFONT hf; + wchar_t wtmp[128]; + size_t wlen; + int i; + + // Set the section header fonts and resize the static controls accordingly + hf = CreateFontA(-MulDiv(14, GetDeviceCaps(GetDC(hMainDialog), LOGPIXELSY), 72), 0, 0, 0, + FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0, PROOF_QUALITY, 0, "Segoe UI"); + + for (i = 0; i < ARRAYSIZE(section_control_ids); i++) { + SendDlgItemMessageA(hDlg, section_control_ids[i], WM_SETFONT, (WPARAM)hf, TRUE); + hCtrl = GetDlgItem(hDlg, section_control_ids[i]); + memset(wtmp, 0, sizeof(wtmp)); + GetWindowTextW(hCtrl, wtmp, ARRAYSIZE(wtmp)); + wlen = wcslen(wtmp); + wtmp[wlen++] = L' '; + wtmp[wlen++] = L' '; + SetWindowTextW(hCtrl, wtmp); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + sz = GetTextSize(hCtrl, NULL); + SetWindowPos(hCtrl, NULL, rc.left, rc.top, sz.cx, sz.cy, SWP_NOZORDER); + } +} + +// Toggle "advanced" options +void ToggleAdvancedDeviceOptions(BOOL enable) +{ + RECT rc; + SIZE sz; + TBBUTTONINFO button_info; + int i, shift = advanced_device_section_height; + + if (!enable) + shift = -shift; + section_vpos[1] += shift; + section_vpos[2] += shift; + + // Toggle the Hide/Show toolbar text + utf8_to_wchar_no_alloc(lmprintf((enable) ? MSG_122 : MSG_121, lmprintf(MSG_119)), wtbtext[0], ARRAYSIZE(wtbtext[0])); + button_info.cbSize = sizeof(button_info); + button_info.dwMask = TBIF_TEXT; + button_info.pszText = wtbtext[0]; + SendMessage(hAdvancedDeviceToolbar, TB_SETBUTTONINFO, (WPARAM)IDC_ADVANCED_DRIVE_PROPERTIES, (LPARAM)&button_info); + SendMessage(hAdvancedDeviceToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)((enable) ? hUpImageList : hDownImageList)); + GetWindowRect(hAdvancedDeviceToolbar, &rc); + MapWindowPoints(NULL, hMainDialog, (POINT*)&rc, 2); + SendMessage(hAdvancedDeviceToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); + SetWindowPos(hAdvancedDeviceToolbar, hTargetSystem, rc.left, rc.top, sz.cx, rc.bottom - rc.top, 0); + + // Move the controls up or down + for (i = 0; i= 2) ? 0 : rh; + + assert(popcnt8(mask) <= 1); + + if (mask & IMOP_WINTOGO) { + if (nWindowsVersion < WINDOWS_8) + return; + image_options ^= IMOP_WINTOGO; + // Set the Windows To Go selection in the dropdown + IGNORE_RETVAL(ComboBox_SetCurSel(GetDlgItem(hMainDialog, IDC_IMAGE_OPTION), windows_to_go_selection)); + } else if (mask & IMOP_PERSISTENCE) { + image_options ^= IMOP_PERSISTENCE; + } + + if (popcnt8(image_options) >= 2) + shift = 0; + + if (shift != 0) { + if ((mask == 0) || (image_options == 0)) + shift = -shift; + section_vpos[1] += shift; + section_vpos[2] += shift; + + if (popcnt8(image_options) <= 1) { + // Move the controls up or down + for (i = 0; i < ARRAYSIZE(image_option_move_ids); i++) + MoveCtrlY(hMainDialog, image_option_move_ids[i], shift); + + // Resize the main dialog and log window + ResizeDialogs(shift); + } + } + + // Hide or show the boot options + for (i = 0; i < ARRAYSIZE(image_option_toggle_ids); i++) { + ShowWindow(GetDlgItem(hMainDialog, image_option_toggle_ids[i][0]), + (image_options & image_option_toggle_ids[i][1]) ? SW_SHOW : SW_HIDE); + } + + // If you don't force a redraw here, all kind of bad UI artifacts happen... + InvalidateRect(hMainDialog, NULL, TRUE); +} + +// We need to create the small toolbar buttons first so that we can compute their width +void CreateSmallButtons(HWND hDlg) +{ + HIMAGELIST hImageList; + HICON hIconSave, hIconHash; + int icon_offset = 0, i16 = GetSystemMetrics(SM_CXSMICON); + TBBUTTON tbToolbarButtons[1]; + unsigned char* buffer; + DWORD bufsize; + + if (i16 >= 28) + icon_offset = 20; + else if (i16 >= 20) + icon_offset = 10; + + hSaveToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, + 0, 0, 0, 0, hMainDialog, (HMENU)IDC_SAVE_TOOLBAR, hMainInstance, NULL); + hImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE | ILC_MIRROR, 1, 0); + buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDI_SAVE_16 + icon_offset), _RT_RCDATA, "save icon", &bufsize, FALSE); + hIconSave = CreateIconFromResourceEx(buffer, bufsize, TRUE, 0x30000, 0, 0, 0); + ImageList_AddIcon(hImageList, hIconSave); + DestroyIcon(hIconSave); + SendMessage(hSaveToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList); + SendMessage(hSaveToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); + tbToolbarButtons[0].idCommand = IDC_SAVE; + tbToolbarButtons[0].fsStyle = BTNS_AUTOSIZE; + tbToolbarButtons[0].fsState = TBSTATE_ENABLED; + tbToolbarButtons[0].iBitmap = 0; + SendMessage(hSaveToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)&tbToolbarButtons); + + hHashToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, + 0, 0, 0, 0, hMainDialog, (HMENU)IDC_HASH_TOOLBAR, hMainInstance, NULL); + hImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE | ILC_MIRROR, 1, 0); + buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDI_HASH_16 + icon_offset), _RT_RCDATA, "hash icon", &bufsize, FALSE); + hIconHash = CreateIconFromResourceEx(buffer, bufsize, TRUE, 0x30000, 0, 0, 0); + ImageList_AddIcon(hImageList, hIconHash); + DestroyIcon(hIconHash); + SendMessage(hHashToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList); + SendMessage(hHashToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); + tbToolbarButtons[0].idCommand = IDC_HASH; + tbToolbarButtons[0].fsStyle = BTNS_AUTOSIZE; + tbToolbarButtons[0].fsState = TBSTATE_ENABLED; + tbToolbarButtons[0].iBitmap = 0; + SendMessage(hHashToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)&tbToolbarButtons); +} + +static INT_PTR CALLBACK ProgressCallback(HWND hCtrl, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hDC; + RECT rc, rc2; + PAINTSTRUCT ps; + SIZE size; + LONG full_right; + wchar_t winfo[128]; + static BOOL marquee_mode = FALSE; + static uint32_t pos = 0, min = 0, max = 0xFFFF; + static COLORREF color = PROGRESS_BAR_NORMAL_COLOR; + + switch (message) { + + case PBM_SETSTATE: + switch (wParam) { + case PBST_NORMAL: + color = PROGRESS_BAR_NORMAL_COLOR; + break; + case PBST_PAUSED: + color = PROGRESS_BAR_PAUSED_COLOR; + break; + case PBST_ERROR: + color = PROGRESS_BAR_ERROR_COLOR; + break; + } + return (INT_PTR)TRUE; + + case PBM_SETRANGE: + // Don't bother sanity checking min and max: If *you* want to + // be an ass about the progress bar range, it's *your* problem. + min = (uint32_t)(lParam & 0xFFFF); + max = (uint32_t)(lParam >> 16); + return (INT_PTR)TRUE; + + case PBM_SETPOS: + pos = (WORD)wParam; + InvalidateRect(hProgress, NULL, TRUE); + return (INT_PTR)TRUE; + + case PBM_SETMARQUEE: + if ((wParam == TRUE) && (!marquee_mode)) { + marquee_mode = TRUE; + pos = min; + color = PROGRESS_BAR_NORMAL_COLOR; + SetTimer(hCtrl, TID_MARQUEE_TIMER, MARQUEE_TIMER_REFRESH, NULL); + InvalidateRect(hProgress, NULL, TRUE); + } else if ((wParam == FALSE) && (marquee_mode)) { + marquee_mode = FALSE; + KillTimer(hCtrl, TID_MARQUEE_TIMER); + pos = min; + InvalidateRect(hProgress, NULL, TRUE); + } + return (INT_PTR)TRUE; + + case WM_TIMER: + if ((wParam == TID_MARQUEE_TIMER) && marquee_mode) { + pos += max((max - min) / (1000 / MARQUEE_TIMER_REFRESH), 1); + if ((pos > max) || (pos < min)) + pos = min; + InvalidateRect(hProgress, NULL, TRUE); + return (INT_PTR)TRUE; + } + return (INT_PTR)FALSE; + + case WM_PAINT: + hDC = BeginPaint(hCtrl, &ps); + GetClientRect(hCtrl, &rc); + rc2 = rc; + InflateRect(&rc, -1, -1); + SelectObject(hDC, GetStockObject(DC_PEN)); + SelectObject(hDC, GetStockObject(NULL_BRUSH)); + // TODO: Handle SetText message so we can avoid this call + GetWindowTextW(hProgress, winfo, ARRAYSIZE(winfo)); + SelectObject(hDC, hInfoFont); + GetTextExtentPoint32(hDC, winfo, (int)wcslen(winfo), &size); + if (size.cx > rc.right) + size.cx = rc.right; + if (size.cy > rc.bottom) + size.cy = rc.bottom; + full_right = rc.right; + if (marquee_mode) { + // Optional first segment + if (pos + ((max - min) / 5) > max) { + rc.right = MulDiv(pos + ((max - min) / 5) - max, rc.right, max - min); + SetTextColor(hDC, PROGRESS_BAR_INVERTED_TEXT_COLOR); + SetBkColor(hDC, color); + ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, + ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); + rc.left = rc.right; + rc.right = full_right; + } + // Optional second segment + if (pos > min) { + rc.right = MulDiv(pos - min, rc.right, max - min); + SetTextColor(hDC, PROGRESS_BAR_NORMAL_TEXT_COLOR); + SetBkColor(hDC, PROGRESS_BAR_BACKGROUND_COLOR); + ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, + ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); + rc.left = rc.right; + rc.right = full_right; + } + // Second to last segment + rc.right = MulDiv(pos - min + ((max - min) / 5), rc.right, max - min); + SetTextColor(hDC, PROGRESS_BAR_INVERTED_TEXT_COLOR); + SetBkColor(hDC, color); + ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, + ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); + } else { + // First segment + rc.right = (pos > min) ? MulDiv(pos - min, rc.right, max - min) : rc.left; + SetTextColor(hDC, PROGRESS_BAR_INVERTED_TEXT_COLOR); + SetBkColor(hDC, color); + ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, + ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); + } + // Last segment + rc.left = rc.right; + rc.right = full_right; + SetTextColor(hDC, PROGRESS_BAR_NORMAL_TEXT_COLOR); + SetBkColor(hDC, PROGRESS_BAR_BACKGROUND_COLOR); + ExtTextOut(hDC, (full_right - size.cx) / 2, (rc.bottom - size.cy) / 2, + ETO_CLIPPED | ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, winfo, (int)wcslen(winfo), NULL); + // Bounding rectangle + SetDCPenColor(hDC, PROGRESS_BAR_BOX_COLOR); + Rectangle(hDC, rc2.left, rc2.top, rc2.right, rc2.bottom); + EndPaint(hCtrl, &ps); + return (INT_PTR)TRUE; + } + + return CallWindowProc(progress_original_proc, hCtrl, message, wParam, lParam); +} + +void CreateAdditionalControls(HWND hDlg) +{ + HINSTANCE hDll; + HIMAGELIST hToolbarImageList; + HICON hIcon, hIconUp, hIconDown; + RECT rc; + SIZE sz; + int icon_offset = 0, i, i16, s16, toolbar_dx = -4 - ((fScale > 1.49f) ? 1 : 0) - ((fScale > 1.99f) ? 1 : 0); + TBBUTTON tbToolbarButtons[7]; + unsigned char* buffer; + DWORD bufsize; + + s16 = i16 = GetSystemMetrics(SM_CXSMICON); + if (s16 >= 54) + s16 = 64; + else if (s16 >= 40) + s16 = 48; + else if (s16 >= 28) + s16 = 32; + else if (s16 >= 20) + s16 = 24; + if (i16 >= 28) + icon_offset = 20; + else if (i16 >= 20) + icon_offset = 10; + + // Fetch the up and down expand icons for the advanced options toolbar + hDll = GetLibraryHandle("ComDlg32"); + hIconDown = (HICON)LoadImage(hDll, MAKEINTRESOURCE(577), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); + hIconUp = (HICON)LoadImage(hDll, MAKEINTRESOURCE(578), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); + // Fallback to using Shell32 if we can't locate the icons we want in ComDlg32 + hDll = GetLibraryHandle("Shell32"); + if (hIconUp == NULL) + hIconUp = (HICON)LoadImage(hDll, MAKEINTRESOURCE(16749), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); + if (hIconDown == NULL) + hIconDown = (HICON)LoadImage(hDll, MAKEINTRESOURCE(16750), IMAGE_ICON, s16, s16, LR_DEFAULTCOLOR | LR_SHARED); + hUpImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, 1, 0); + hDownImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, 1, 0); + ImageList_AddIcon(hUpImageList, hIconUp); + ImageList_AddIcon(hDownImageList, hIconDown); + + // Create the advanced options toolbars + memset(wtbtext, 0, sizeof(wtbtext)); + utf8_to_wchar_no_alloc(lmprintf((advanced_mode_device) ? MSG_122 : MSG_121, lmprintf(MSG_119)), wtbtext[0], ARRAYSIZE(wtbtext[0])); + hAdvancedDeviceToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, + 0, 0, 0, 0, hMainDialog, (HMENU)IDC_ADVANCED_DEVICE_TOOLBAR, hMainInstance, NULL); + SendMessage(hAdvancedDeviceToolbar, CCM_SETVERSION, (WPARAM)6, 0); + memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); + tbToolbarButtons[0].idCommand = IDC_ADVANCED_DRIVE_PROPERTIES; + tbToolbarButtons[0].fsStyle = BTNS_SHOWTEXT | BTNS_AUTOSIZE; + tbToolbarButtons[0].fsState = TBSTATE_ENABLED; + tbToolbarButtons[0].iString = (INT_PTR)wtbtext[0]; + tbToolbarButtons[0].iBitmap = 0; + SendMessage(hAdvancedDeviceToolbar, TB_SETIMAGELIST, 0, (LPARAM)hUpImageList); + SendMessage(hAdvancedDeviceToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + SendMessage(hAdvancedDeviceToolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbToolbarButtons); + GetWindowRect(GetDlgItem(hDlg, IDC_ADVANCED_DRIVE_PROPERTIES), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SendMessage(hAdvancedDeviceToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); + // Yeah, so, like, TB_GETIDEALSIZE totally super doesn't work on Windows 7, for low zoom factor and when compiled with MSVC... + if (sz.cx < 16) + sz.cx = fw; + SetWindowPos(hAdvancedDeviceToolbar, hTargetSystem, rc.left + toolbar_dx, rc.top, sz.cx, rc.bottom - rc.top, 0); + + utf8_to_wchar_no_alloc(lmprintf((advanced_mode_format) ? MSG_122 : MSG_121, lmprintf(MSG_120)), wtbtext[1], ARRAYSIZE(wtbtext[1])); + hAdvancedFormatToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, + 0, 0, 0, 0, hMainDialog, (HMENU)IDC_ADVANCED_FORMAT_TOOLBAR, hMainInstance, NULL); + SendMessage(hAdvancedFormatToolbar, CCM_SETVERSION, (WPARAM)6, 0); + memset(tbToolbarButtons, 0, sizeof(TBBUTTON)); + tbToolbarButtons[0].idCommand = IDC_ADVANCED_FORMAT_OPTIONS; + tbToolbarButtons[0].fsStyle = BTNS_SHOWTEXT | BTNS_AUTOSIZE; + tbToolbarButtons[0].fsState = TBSTATE_ENABLED; + tbToolbarButtons[0].iString = (INT_PTR)wtbtext[1]; + tbToolbarButtons[0].iBitmap = 0; + SendMessage(hAdvancedFormatToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hUpImageList); + SendMessage(hAdvancedFormatToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + SendMessage(hAdvancedFormatToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)&tbToolbarButtons); + GetWindowRect(GetDlgItem(hDlg, IDC_ADVANCED_FORMAT_OPTIONS), &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SendMessage(hAdvancedFormatToolbar, TB_GETIDEALSIZE, (WPARAM)FALSE, (LPARAM)&sz); + if (sz.cx < 16) + sz.cx = fw; + SetWindowPos(hAdvancedFormatToolbar, hClusterSize, rc.left + toolbar_dx, rc.top, sz.cx, rc.bottom - rc.top, 0); + + // Create the multi toolbar + hMultiToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, TOOLBAR_STYLE, + 0, 0, 0, 0, hMainDialog, (HMENU)IDC_MULTI_TOOLBAR, hMainInstance, NULL); + hToolbarImageList = ImageList_Create(i16, i16, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, 8, 0); + for (i = 0; i < ARRAYSIZE(multitoolbar_icons); i++) { + buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(multitoolbar_icons[i] + icon_offset), + _RT_RCDATA, "toolbar icon", &bufsize, FALSE); + hIcon = CreateIconFromResourceEx(buffer, bufsize, TRUE, 0x30000, 0, 0, 0); + // Mirror the "world" icon on RTL since we can't use an ImageList mirroring flag for that... + if (right_to_left_mode && (i == 0)) + hIcon = CreateMirroredIcon(hIcon); + ImageList_AddIcon(hToolbarImageList, hIcon); + DestroyIcon(hIcon); + } + SendMessage(hMultiToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hToolbarImageList); + SendMessage(hMultiToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + memset(tbToolbarButtons, 0, sizeof(TBBUTTON) * ARRAYSIZE(tbToolbarButtons)); + tbToolbarButtons[0].idCommand = IDC_LANG; + tbToolbarButtons[0].fsStyle = BTNS_BUTTON; + tbToolbarButtons[0].fsState = TBSTATE_ENABLED; + tbToolbarButtons[0].iBitmap = 0; + tbToolbarButtons[1].fsStyle = BTNS_AUTOSIZE; + tbToolbarButtons[1].fsState = TBSTATE_INDETERMINATE; + tbToolbarButtons[1].iBitmap = I_IMAGENONE; + tbToolbarButtons[1].iString = (fScale < 1.5f) ? (INT_PTR)L"" : (INT_PTR)L" "; + tbToolbarButtons[2].idCommand = IDC_ABOUT; + tbToolbarButtons[2].fsStyle = BTNS_BUTTON; + tbToolbarButtons[2].fsState = TBSTATE_ENABLED; + tbToolbarButtons[2].iBitmap = 1; + tbToolbarButtons[3].fsStyle = BTNS_AUTOSIZE; + tbToolbarButtons[3].fsState = TBSTATE_INDETERMINATE; + tbToolbarButtons[3].iBitmap = I_IMAGENONE; + tbToolbarButtons[3].iString = (fScale < 1.5f) ? (INT_PTR)L"" : (INT_PTR)L" "; + tbToolbarButtons[4].idCommand = IDC_SETTINGS; + tbToolbarButtons[4].fsStyle = BTNS_BUTTON; + tbToolbarButtons[4].fsState = TBSTATE_ENABLED; + tbToolbarButtons[4].iBitmap = 2; + tbToolbarButtons[5].fsStyle = BTNS_AUTOSIZE; + tbToolbarButtons[5].fsState = TBSTATE_INDETERMINATE; + tbToolbarButtons[5].iBitmap = I_IMAGENONE; + tbToolbarButtons[5].iString = (fScale < 1.5f) ? (INT_PTR)L"" : (INT_PTR)L" "; + tbToolbarButtons[6].idCommand = IDC_LOG; + tbToolbarButtons[6].fsStyle = BTNS_BUTTON; + tbToolbarButtons[6].fsState = TBSTATE_ENABLED; + tbToolbarButtons[6].iBitmap = 3; + SendMessage(hMultiToolbar, TB_ADDBUTTONS, (WPARAM)7, (LPARAM)&tbToolbarButtons); + SendMessage(hMultiToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(i16, ddbh)); + + // Subclass the progress bar so that we can write on it + progress_original_proc = (WNDPROC)SetWindowLongPtr(hProgress, GWLP_WNDPROC, (LONG_PTR)ProgressCallback); +} + +// Set up progress bar real estate allocation +void InitProgress(BOOL bOnlyFormat) +{ + int i; + float last_end = 0.0f, slots_discrete = 0.0f, slots_analog = 0.0f; + + memset(nb_slots, 0, sizeof(nb_slots)); + memset(slot_end, 0, sizeof(slot_end)); + previous_end = 0.0f; + + if (bOnlyFormat) { + nb_slots[OP_FORMAT] = -1; + } else { + nb_slots[OP_ANALYZE_MBR] = 1; + if (IsChecked(IDC_BAD_BLOCKS)) { + nb_slots[OP_BADBLOCKS] = -1; + } + if (bt != BT_NON_BOOTABLE) { + // 1 extra slot for PBR writing + switch (selection_default) { + case BT_MSDOS: + nb_slots[OP_DOS] = 3 + 1; + break; + case BT_FREEDOS: + nb_slots[OP_DOS] = 5 + 1; + break; + case BT_IMAGE: + nb_slots[OP_DOS] = img_report.is_iso ? -1 : 0; + break; + default: + nb_slots[OP_DOS] = 2 + 1; + break; + } + } + if (selection_default == BT_IMAGE && !img_report.is_iso) { + nb_slots[OP_FORMAT] = -1; + } else { + nb_slots[OP_ZERO_MBR] = 1; + nb_slots[OP_PARTITION] = 1; + nb_slots[OP_FIX_MBR] = 1; + nb_slots[OP_CREATE_FS] = + nb_steps[ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem))]; + if ((!IsChecked(IDC_QUICK_FORMAT)) + || ((fs == FS_FAT32) && ((SelectedDrive.DiskSize >= LARGE_FAT32_SIZE) || (force_large_fat32)))) { + nb_slots[OP_FORMAT] = -1; + } + nb_slots[OP_FINALIZE] = ((selection_default == BT_IMAGE) && (fs == FS_NTFS)) ? 3 : 2; + } + } + + for (i = 0; i 0) { + slots_discrete += nb_slots[i] * 1.0f; + } + if (nb_slots[i] < 0) { + slots_analog += nb_slots[i] * 1.0f; + } + } + + for (i = 0; i 0) { + slot_end[i + 1] = last_end + (1.0f * nb_slots[i]); + } else if (nb_slots[i] < 0) { + slot_end[i + 1] = last_end + (((100.0f - slots_discrete) * nb_slots[i]) / slots_analog); + } + last_end = slot_end[i + 1]; + } + + // If there's no analog, adjust our discrete ends to fill the whole bar + if (slots_analog == 0.0f) { + for (i = 0; i= OP_MAX)) { + duprintf("UpdateProgress: invalid op %d\n", op); + return; + } + if (percent > 100.1f) { + // duprintf("UpdateProgress(%d): invalid percentage %0.2f\n", op, percent); + return; + } + if ((percent < 0.0f) && (nb_slots[op] <= 0)) { + duprintf("UpdateProgress(%d): error negative percentage sent for negative slot value\n", op); + return; + } + if (nb_slots[op] == 0) + return; + if (previous_end < slot_end[op]) { + previous_end = slot_end[op]; + } + + if (percent < 0.0f) { + // Negative means advance one slot (1.0%) - requires a positive slot allocation + previous_end += (slot_end[op + 1] - slot_end[op]) / (1.0f * nb_slots[op]); + pos = (int)(previous_end / 100.0f * MAX_PROGRESS); + } else { + pos = (int)((previous_end + ((slot_end[op + 1] - previous_end) * (percent / 100.0f))) / 100.0f * MAX_PROGRESS); + } + if (pos > MAX_PROGRESS) { + duprintf("UpdateProgress(%d): rounding error - pos %d is greater than %d\n", op, pos, MAX_PROGRESS); + pos = MAX_PROGRESS; + } + + // Reduce the refresh rate, to avoid weird effects on the sliding part of progress bar + if (GetTickCount64() > LastRefresh + (2 * MAX_REFRESH)) { + LastRefresh = GetTickCount64(); + SendMessage(hProgress, PBM_SETPOS, (WPARAM)pos, 0); + SetTaskbarProgressValue(pos, MAX_PROGRESS); + } +} + +void ShowLanguageMenu(RECT rcExclude) +{ + TPMPARAMS tpm; + HMENU menu; + loc_cmd* lcmd = NULL; + char lang[256]; + char *search = "()"; + char *l, *r, *str; + + UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; + menu = CreatePopupMenu(); + list_for_each_entry(lcmd, &locale_list, loc_cmd, list) { + // The appearance of LTR languages must be fixed for RTL menus + if ((right_to_left_mode) && (!(lcmd->ctrl_id & LOC_RIGHT_TO_LEFT))) { + str = safe_strdup(lcmd->txt[1]); + l = strtok(str, search); + r = strtok(NULL, search); + static_sprintf(lang, LEFT_TO_RIGHT_EMBEDDING "(%s) " POP_DIRECTIONAL_FORMATTING "%s", r, l); + safe_free(str); + } else { + static_strcpy(lang, lcmd->txt[1]); + } + InsertMenuU(menu, -1, MF_BYPOSITION | ((selected_locale == lcmd) ? MF_CHECKED : 0), UM_LANGUAGE_MENU_MAX++, lang); + } + + // Open the menu such that it doesn't overlap the specified rect + tpm.cbSize = sizeof(TPMPARAMS); + tpm.rcExclude = rcExclude; + TrackPopupMenuEx(menu, 0, + // In RTL languages, the menu should be placed at the bottom-right of the rect + right_to_left_mode ? rcExclude.right : rcExclude.left, + rcExclude.bottom, hMainDialog, &tpm); + + DestroyMenu(menu); +} + +void SetPassesTooltip(void) +{ + const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] = + { BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC }; + int sel = ComboBox_GetCurSel(hNBPasses); + int type = (sel < 2) ? 0 : sel - 2; + CreateTooltip(hNBPasses, lmprintf(MSG_153 + ((sel >= 2) ? 3 : sel), + pattern[type][0], pattern[type][1], pattern[type][2], pattern[type][3]), -1); +} + +void SetBootTypeDropdownWidth(void) +{ + HDC hDC; + HFONT hFont; + SIZE sz; + RECT rc; + + if (image_path == NULL) + return; + // Set the maximum width of the dropdown according to the image selected + GetWindowRect(hBootType, &rc); + MapWindowPoints(NULL, hMainDialog, (POINT*)&rc, 2); + hDC = GetDC(hBootType); + hFont = (HFONT)SendMessageA(hBootType, WM_GETFONT, 0, 0); + SelectObject(hDC, hFont); + GetTextExtentPointU(hDC, short_image_path, &sz); + safe_release_dc(hBootType, hDC); + SendMessage(hBootType, CB_SETDROPPEDWIDTH, (WPARAM)max(sz.cx + 10, rc.right - rc.left), (LPARAM)0); +} + +// Create the horizontal section lines +void OnPaint(HDC hdc) +{ + int i; + HPEN hp = CreatePen(0, (fScale < 1.5f) ? 2 : 3, RGB(0, 0, 0)); + SelectObject(hdc, hp); + for (i = 0; i < ARRAYSIZE(section_vpos); i++) { + MoveToEx(hdc, mw + 10, section_vpos[i], NULL); + LineTo(hdc, mw + fw, section_vpos[i]); + } +} diff --git a/src/ui.h b/src/ui.h index ff3aeebb..254ac604 100644 --- a/src/ui.h +++ b/src/ui.h @@ -1,6 +1,6 @@ /* * Rufus: The Reliable USB Formatting Utility - * UI element lists + * UI-related function calls * Copyright © 2018 Pete Batard * * This program is free software: you can redistribute it and/or modify @@ -18,6 +18,7 @@ */ #include +#include #include "resource.h" #pragma once @@ -42,180 +43,31 @@ TBSTYLE_AUTOSIZE | TBSTYLE_LIST | \ TBSTYLE_TOOLTIPS ) -static int section_control_ids[] = { - IDS_DRIVE_PROPERTIES_TXT, - IDS_FORMAT_OPTIONS_TXT, - IDS_STATUS_TXT -}; +extern HWND hMultiToolbar, hSaveToolbar, hHashToolbar, hAdvancedDeviceToolbar, hAdvancedFormatToolbar; +extern HFONT hInfoFont; +extern UINT_PTR UM_LANGUAGE_MENU_MAX; +extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32; +extern loc_cmd* selected_locale; +extern const char *sfd_name, *flash_type[BADLOCKS_PATTERN_TYPES]; +extern char *short_image_path; +extern int advanced_device_section_height, advanced_format_section_height, windows_to_go_selection; +extern int selection_default, cbw, ddw, ddbh, bh; -static int section_vpos[ARRAYSIZE(section_control_ids)]; - -static int image_option_move_ids[] = { - IDS_PARTITION_TYPE_TXT, - IDC_PARTITION_TYPE, - IDS_TARGET_SYSTEM_TXT, - IDC_TARGET_SYSTEM, - IDS_CSM_HELP_TXT, - IDC_ADVANCED_DEVICE_TOOLBAR, - IDC_LIST_USB_HDD, - IDC_OLD_BIOS_FIXES, - IDC_RUFUS_MBR, - IDC_DISK_ID, - IDS_FORMAT_OPTIONS_TXT, - IDS_LABEL_TXT, - IDC_LABEL, - IDS_FILE_SYSTEM_TXT, - IDC_FILE_SYSTEM, - IDS_CLUSTER_SIZE_TXT, - IDC_CLUSTER_SIZE, - IDC_ADVANCED_FORMAT_TOOLBAR, - IDC_QUICK_FORMAT, - IDC_BAD_BLOCKS, - IDC_NB_PASSES, - IDC_EXTENDED_LABEL, - IDS_STATUS_TXT, - IDC_PROGRESS, - IDC_ABOUT, - IDC_LOG, - IDC_MULTI_TOOLBAR, - IDC_TEST, - IDC_START, - IDCANCEL, - IDC_STATUS, - IDC_STATUS_TOOLBAR, -}; - -static int image_option_toggle_ids[][2] = { - { IDS_IMAGE_OPTION_TXT, 0x03 }, - { IDC_IMAGE_OPTION, 0x01 }, - { IDC_PERSISTENCE_SLIDER, 0x02 }, - { IDC_PERSISTENCE_SIZE, 0x02 }, - { IDC_PERSISTENCE_UNITS, 0x02 } -}; - -static int advanced_device_move_ids[] = { - IDC_LIST_USB_HDD, - IDC_OLD_BIOS_FIXES, - IDC_RUFUS_MBR, - IDS_FORMAT_OPTIONS_TXT, - IDS_LABEL_TXT, - IDC_LABEL, - IDS_FILE_SYSTEM_TXT, - IDC_FILE_SYSTEM, - IDS_CLUSTER_SIZE_TXT, - IDC_CLUSTER_SIZE, - IDC_ADVANCED_FORMAT_TOOLBAR, - IDC_QUICK_FORMAT, - IDC_BAD_BLOCKS, - IDC_NB_PASSES, - IDC_EXTENDED_LABEL, - IDS_STATUS_TXT, - IDC_PROGRESS, - IDC_ABOUT, - IDC_LOG, - IDC_MULTI_TOOLBAR, - IDC_TEST, - IDC_START, - IDCANCEL, - IDC_STATUS, - IDC_STATUS_TOOLBAR, -}; - -static int advanced_device_toggle_ids[] = { - IDC_SAVE_TOOLBAR, - IDC_LIST_USB_HDD, - IDC_OLD_BIOS_FIXES, - IDC_RUFUS_MBR, - IDC_DISK_ID, -}; - -static int advanced_format_move_ids[] = { - IDS_STATUS_TXT, - IDC_PROGRESS, - IDC_ABOUT, - IDC_LOG, - IDC_MULTI_TOOLBAR, - IDC_TEST, - IDC_START, - IDCANCEL, - IDC_STATUS, - IDC_STATUS_TOOLBAR, -}; - -static int advanced_format_toggle_ids[] = { - IDC_QUICK_FORMAT, - IDC_BAD_BLOCKS, - IDC_NB_PASSES, - IDC_EXTENDED_LABEL, -}; - -static int main_button_ids[] = { - IDC_SELECT, - IDC_START, - IDCANCEL, -}; - -static int full_width_controls[] = { - IDS_DEVICE_TXT, - IDS_BOOT_SELECTION_TXT, - IDS_IMAGE_OPTION_TXT, - IDC_IMAGE_OPTION, - IDS_LABEL_TXT, - IDC_LABEL, - IDC_ADVANCED_DRIVE_PROPERTIES, - IDC_LIST_USB_HDD, - IDC_OLD_BIOS_FIXES, - IDC_ADVANCED_FORMAT_OPTIONS, - IDC_QUICK_FORMAT, - IDC_EXTENDED_LABEL, - IDC_PROGRESS, -}; - -static int full_width_checkboxes[] = { - IDC_LIST_USB_HDD, - IDC_OLD_BIOS_FIXES, - IDC_QUICK_FORMAT, - IDC_EXTENDED_LABEL, -}; - -static int half_width_ids[] = { - IDC_BAD_BLOCKS, - IDC_RUFUS_MBR, - IDS_PARTITION_TYPE_TXT, - IDC_PARTITION_TYPE, - IDC_FILE_SYSTEM, - IDS_TARGET_SYSTEM_TXT, - IDC_TARGET_SYSTEM, - IDC_DISK_ID, - IDS_CLUSTER_SIZE_TXT, - IDC_CLUSTER_SIZE, - IDC_NB_PASSES, -}; - -static int adjust_dpi_ids[][5] = { - {IDS_DEVICE_TXT, IDC_DEVICE, IDC_SAVE_TOOLBAR, 0, 0}, - {IDS_BOOT_SELECTION_TXT, IDC_BOOT_SELECTION, IDC_HASH_TOOLBAR, IDC_SELECT, 0}, - {IDS_IMAGE_OPTION_TXT, IDC_IMAGE_OPTION, IDC_PERSISTENCE_SLIDER, IDC_PERSISTENCE_SIZE, IDC_PERSISTENCE_UNITS}, - {IDS_PARTITION_TYPE_TXT, IDC_PARTITION_TYPE, IDS_TARGET_SYSTEM_TXT, IDC_TARGET_SYSTEM, IDS_CSM_HELP_TXT}, - {IDC_ADVANCED_DEVICE_TOOLBAR, 0, 0, 0, 0}, - {IDC_LIST_USB_HDD, 0, 0, 0, 0 }, - {IDC_OLD_BIOS_FIXES, 0, 0, 0, 0}, - {IDC_RUFUS_MBR, IDC_DISK_ID, 0, 0, 0}, - {IDS_FORMAT_OPTIONS_TXT, 0, 0, 0, 0}, - {IDS_LABEL_TXT, IDC_LABEL, 0, 0, 0}, - {IDS_FILE_SYSTEM_TXT, IDC_FILE_SYSTEM, IDS_CLUSTER_SIZE_TXT, IDC_CLUSTER_SIZE, 0}, - {IDC_ADVANCED_FORMAT_TOOLBAR, 0, 0, 0, 0}, - {IDC_QUICK_FORMAT, 0, 0, 0, 0}, - {IDC_EXTENDED_LABEL, 0, 0, 0, 0}, - {IDC_BAD_BLOCKS, IDC_NB_PASSES, 0, 0, 0}, - {IDS_STATUS_TXT, 0, 0, 0, 0}, - {IDC_PROGRESS, 0, 0, 0, 0 }, - {IDC_MULTI_TOOLBAR, IDC_TEST, IDC_START, IDCANCEL, 0} -}; - -static int multitoolbar_icons[] = { - IDI_LANG_16, - IDI_INFO_16, - IDI_SETTINGS_16, - IDI_LOG_16 -}; +extern void SetComboEntry(HWND hDlg, int data); +extern void GetBasicControlsWidth(HWND hDlg); +extern void GetMainButtonsWidth(HWND hDlg); +extern void GetHalfDropwdownWidth(HWND hDlg); +extern void GetFullWidth(HWND hDlg); +extern void PositionMainControls(HWND hDlg); +extern void AdjustForLowDPI(HWND hDlg); +extern void SetSectionHeaders(HWND hDlg); +extern void ToggleAdvancedDeviceOptions(BOOL enable); +extern void ToggleAdvancedFormatOptions(BOOL enable); +extern void ToggleImageOption(uint8_t mask); +extern void CreateSmallButtons(HWND hDlg); +extern void CreateAdditionalControls(HWND hDlg); +extern void InitProgress(BOOL bOnlyFormat); +extern void ShowLanguageMenu(RECT rcExclude); +extern void SetPassesTooltip(void); +extern void SetBootTypeDropdownWidth(void); +extern void OnPaint(HDC hdc); diff --git a/src/ui_data.h b/src/ui_data.h new file mode 100644 index 00000000..5401ad04 --- /dev/null +++ b/src/ui_data.h @@ -0,0 +1,201 @@ +/* + * Rufus: The Reliable USB Formatting Utility + * UI element lists + * Copyright © 2018 Pete Batard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "resource.h" + +#pragma once + +static int section_control_ids[] = { + IDS_DRIVE_PROPERTIES_TXT, + IDS_FORMAT_OPTIONS_TXT, + IDS_STATUS_TXT +}; + +static int section_vpos[ARRAYSIZE(section_control_ids)]; + +static int image_option_move_ids[] = { + IDS_PARTITION_TYPE_TXT, + IDC_PARTITION_TYPE, + IDS_TARGET_SYSTEM_TXT, + IDC_TARGET_SYSTEM, + IDS_CSM_HELP_TXT, + IDC_ADVANCED_DEVICE_TOOLBAR, + IDC_LIST_USB_HDD, + IDC_OLD_BIOS_FIXES, + IDC_RUFUS_MBR, + IDC_DISK_ID, + IDS_FORMAT_OPTIONS_TXT, + IDS_LABEL_TXT, + IDC_LABEL, + IDS_FILE_SYSTEM_TXT, + IDC_FILE_SYSTEM, + IDS_CLUSTER_SIZE_TXT, + IDC_CLUSTER_SIZE, + IDC_ADVANCED_FORMAT_TOOLBAR, + IDC_QUICK_FORMAT, + IDC_BAD_BLOCKS, + IDC_NB_PASSES, + IDC_EXTENDED_LABEL, + IDS_STATUS_TXT, + IDC_PROGRESS, + IDC_ABOUT, + IDC_LOG, + IDC_MULTI_TOOLBAR, + IDC_TEST, + IDC_START, + IDCANCEL, + IDC_STATUS, + IDC_STATUS_TOOLBAR, +}; + +static int image_option_toggle_ids[][2] = { + { IDS_IMAGE_OPTION_TXT, 0x03 }, + { IDC_IMAGE_OPTION, 0x01 }, + { IDC_PERSISTENCE_SLIDER, 0x02 }, + { IDC_PERSISTENCE_SIZE, 0x02 }, + { IDC_PERSISTENCE_UNITS, 0x02 } +}; + +static int advanced_device_move_ids[] = { + IDC_LIST_USB_HDD, + IDC_OLD_BIOS_FIXES, + IDC_RUFUS_MBR, + IDS_FORMAT_OPTIONS_TXT, + IDS_LABEL_TXT, + IDC_LABEL, + IDS_FILE_SYSTEM_TXT, + IDC_FILE_SYSTEM, + IDS_CLUSTER_SIZE_TXT, + IDC_CLUSTER_SIZE, + IDC_ADVANCED_FORMAT_TOOLBAR, + IDC_QUICK_FORMAT, + IDC_BAD_BLOCKS, + IDC_NB_PASSES, + IDC_EXTENDED_LABEL, + IDS_STATUS_TXT, + IDC_PROGRESS, + IDC_ABOUT, + IDC_LOG, + IDC_MULTI_TOOLBAR, + IDC_TEST, + IDC_START, + IDCANCEL, + IDC_STATUS, + IDC_STATUS_TOOLBAR, +}; + +static int advanced_device_toggle_ids[] = { + IDC_SAVE_TOOLBAR, + IDC_LIST_USB_HDD, + IDC_OLD_BIOS_FIXES, + IDC_RUFUS_MBR, + IDC_DISK_ID, +}; + +static int advanced_format_move_ids[] = { + IDS_STATUS_TXT, + IDC_PROGRESS, + IDC_ABOUT, + IDC_LOG, + IDC_MULTI_TOOLBAR, + IDC_TEST, + IDC_START, + IDCANCEL, + IDC_STATUS, + IDC_STATUS_TOOLBAR, +}; + +static int advanced_format_toggle_ids[] = { + IDC_QUICK_FORMAT, + IDC_BAD_BLOCKS, + IDC_NB_PASSES, + IDC_EXTENDED_LABEL, +}; + +static int main_button_ids[] = { + IDC_SELECT, + IDC_START, + IDCANCEL, +}; + +static int full_width_controls[] = { + IDS_DEVICE_TXT, + IDS_BOOT_SELECTION_TXT, + IDS_IMAGE_OPTION_TXT, + IDC_IMAGE_OPTION, + IDS_LABEL_TXT, + IDC_LABEL, + IDC_ADVANCED_DRIVE_PROPERTIES, + IDC_LIST_USB_HDD, + IDC_OLD_BIOS_FIXES, + IDC_ADVANCED_FORMAT_OPTIONS, + IDC_QUICK_FORMAT, + IDC_EXTENDED_LABEL, + IDC_PROGRESS, +}; + +static int full_width_checkboxes[] = { + IDC_LIST_USB_HDD, + IDC_OLD_BIOS_FIXES, + IDC_QUICK_FORMAT, + IDC_EXTENDED_LABEL, +}; + +static int half_width_ids[] = { + IDC_BAD_BLOCKS, + IDC_RUFUS_MBR, + IDS_PARTITION_TYPE_TXT, + IDC_PARTITION_TYPE, + IDC_FILE_SYSTEM, + IDS_TARGET_SYSTEM_TXT, + IDC_TARGET_SYSTEM, + IDC_DISK_ID, + IDS_CLUSTER_SIZE_TXT, + IDC_CLUSTER_SIZE, + IDC_NB_PASSES, +}; + +static int adjust_dpi_ids[][5] = { + { IDS_DEVICE_TXT, IDC_DEVICE, IDC_SAVE_TOOLBAR, 0, 0 }, + { IDS_BOOT_SELECTION_TXT, IDC_BOOT_SELECTION, IDC_HASH_TOOLBAR, IDC_SELECT, 0 }, + { IDS_IMAGE_OPTION_TXT, IDC_IMAGE_OPTION, IDC_PERSISTENCE_SLIDER, IDC_PERSISTENCE_SIZE, IDC_PERSISTENCE_UNITS }, + { IDS_PARTITION_TYPE_TXT, IDC_PARTITION_TYPE, IDS_TARGET_SYSTEM_TXT, IDC_TARGET_SYSTEM, IDS_CSM_HELP_TXT }, + { IDC_ADVANCED_DEVICE_TOOLBAR, 0, 0, 0, 0 }, + { IDC_LIST_USB_HDD, 0, 0, 0, 0 }, + { IDC_OLD_BIOS_FIXES, 0, 0, 0, 0 }, + { IDC_RUFUS_MBR, IDC_DISK_ID, 0, 0, 0 }, + { IDS_FORMAT_OPTIONS_TXT, 0, 0, 0, 0 }, + { IDS_LABEL_TXT, IDC_LABEL, 0, 0, 0 }, + { IDS_FILE_SYSTEM_TXT, IDC_FILE_SYSTEM, IDS_CLUSTER_SIZE_TXT, IDC_CLUSTER_SIZE, 0 }, + { IDC_ADVANCED_FORMAT_TOOLBAR, 0, 0, 0, 0 }, + { IDC_QUICK_FORMAT, 0, 0, 0, 0 }, + { IDC_EXTENDED_LABEL, 0, 0, 0, 0 }, + { IDC_BAD_BLOCKS, IDC_NB_PASSES, 0, 0, 0 }, + { IDS_STATUS_TXT, 0, 0, 0, 0 }, + { IDC_PROGRESS, 0, 0, 0, 0 }, + { IDC_MULTI_TOOLBAR, IDC_TEST, IDC_START, IDCANCEL, 0 } +}; + +static int multitoolbar_icons[] = { + IDI_LANG_16, + IDI_INFO_16, + IDI_SETTINGS_16, + IDI_LOG_16 +};