diff --git a/README.md b/README.md index b154432a..58fc830e 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,7 @@ Features Compilation ----------- -Use either Visual Studio (2017 or later), WDK 7.1 (Windows Driver Kit) or MinGW and then -invoke the `.sln`, `wdk_build.cmd` or `configure`/`make` respectively. +Use either Visual Studio (2017 or later) or MinGW and then invoke the `.sln` or `configure`/`make` respectively. #### Visual Studio Note that, since Rufus is an OSI compliant Open Source project, you are entitled to diff --git a/res/localization/rufus.loc b/res/localization/rufus.loc index 971bd58c..b6457cf8 100644 --- a/res/localization/rufus.loc +++ b/res/localization/rufus.loc @@ -251,7 +251,7 @@ t MSG_064 "Read error." t MSG_065 "Write error." t MSG_066 "Installation failure" t MSG_067 "Could not open media. It may be in use by another process. " - "Please check the log for additional details." + "Please re-plug the media and try again." t MSG_068 "Error while partitioning drive." t MSG_069 "Could not copy files to target drive." t MSG_070 "Cancelled by user." @@ -5273,7 +5273,7 @@ t MSG_064 "Erreur de lecture." t MSG_065 "Erreur d'écriture." t MSG_066 "L'installation a échoué" t MSG_067 "Impossible d'accéder au média. Il peut être en cours d'utilisation par une autre application. " - "Veuillez consulter le log pour avoir des détails supplémentaires." + "Essayer de déconnecter le média et essayez à nouveau." t MSG_068 "Erreur de partitionnement." t MSG_069 "Impossible de copier les fichiers sur le périphérique de destination." t MSG_070 "Opération annulée par l'utilisateur." diff --git a/src/format.c b/src/format.c index f9e70a72..c0ba4a1c 100644 --- a/src/format.c +++ b/src/format.c @@ -1325,7 +1325,7 @@ int SetWinToGoIndex(void) (StrArrayAdd(&version_index, get_token_data_file_indexed("IMAGE INDEX", xml_file, i + 1), FALSE) >= 0); i++); if (i > 1) - i = Selection(lmprintf(MSG_291), lmprintf(MSG_292), version_name.String, i); + i = SelectionDialog(lmprintf(MSG_291), lmprintf(MSG_292), version_name.String, i); if (i < 0) { wintogo_index = -2; // Cancelled by the user } else if (i == 0) { diff --git a/src/process.c b/src/process.c index b0fb834c..c13b98cc 100644 --- a/src/process.c +++ b/src/process.c @@ -57,6 +57,7 @@ PF_TYPE_DECL(NTAPI, NTSTATUS, NtAdjustPrivilegesToken, (HANDLE, BOOLEAN, PTOKEN_ PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE)); static PVOID PhHeapHandle = NULL; +extern StrArray BlockingProcess; /* * Convert an NT Status to an error message @@ -399,6 +400,7 @@ NTSTATUS PhQueryProcessesUsingVolumeOrFile(HANDLE VolumeOrFileHandle, BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) { const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" }; + char tmp[MAX_PATH]; NTSTATUS status = STATUS_SUCCESS; PSYSTEM_HANDLE_INFORMATION_EX handles = NULL; POBJECT_NAME_INFORMATION buffer = NULL; @@ -426,6 +428,8 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) PF_INIT_OR_SET_STATUS(RtlInitUnicodeString, NtDll); #endif + StrArrayClear(&BlockingProcess); + if (NT_SUCCESS(status)) status = PhCreateHeap(); @@ -481,7 +485,9 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) // If we're switching process and found a match, print it if (bFound) { - uprintf("o '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]); + uprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]); + static_sprintf(tmp, "● %s (pid %ld)", exe_path, pid[cur_pid]); + StrArrayAdd(&BlockingProcess, tmp, TRUE); bFound = FALSE; access_rights = 0; } diff --git a/src/resource.h b/src/resource.h index 4991f722..e9fa0fba 100644 --- a/src/resource.h +++ b/src/resource.h @@ -11,6 +11,7 @@ #define IDD_UPDATE_POLICY 107 #define IDD_NEW_VERSION 108 #define IDD_CHECKSUM 109 +#define IDD_LIST 110 #define IDI_ICON 120 #define IDI_UP 121 #define IDI_DOWN 122 @@ -148,6 +149,26 @@ #define IDC_SELECTION_CHOICE14 1090 #define IDC_SELECTION_CHOICE15 1091 #define IDC_SELECTION_CHOICEMAX 1092 +#define IDC_LIST_ICON 1093 +#define IDC_LIST_TEXT 1094 +#define IDC_LIST_LINE 1095 +#define IDC_LIST_ITEM1 1096 +#define IDC_LIST_ITEM2 1097 +#define IDC_LIST_ITEM3 1098 +#define IDC_LIST_ITEM4 1099 +#define IDC_LIST_ITEM5 1100 +#define IDC_LIST_ITEM6 1101 +#define IDC_LIST_ITEM7 1102 +#define IDC_LIST_ITEM8 1103 +#define IDC_LIST_ITEM9 1104 +#define IDC_LIST_ITEM10 1105 +#define IDC_LIST_ITEM11 1106 +#define IDC_LIST_ITEM12 1107 +#define IDC_LIST_ITEM13 1108 +#define IDC_LIST_ITEM14 1109 +#define IDC_LIST_ITEM15 1110 +#define IDC_LIST_ITEMMAX 1111 +#define IDC_SELECTION_CHOICEMAX 1092 #define IDS_DEVICE_TXT 2000 #define IDS_PARTITION_TYPE_TXT 2001 #define IDS_FILESYSTEM_TXT 2002 diff --git a/src/rufus.c b/src/rufus.c index 072189da..5e9bf2fc 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -114,7 +114,7 @@ uint16_t rufus_version[3], embedded_sl_version[2]; char embedded_sl_version_str[2][12] = { "?.??", "?.??" }; char embedded_sl_version_ext[2][32]; RUFUS_UPDATE update = { {0,0,0}, {0,0}, NULL, NULL}; -StrArray DriveID, DriveLabel; +StrArray DriveID, DriveLabel, BlockingProcess; extern char* szStatusMessage; static HANDLE format_thid = NULL, dialog_handle = NULL; @@ -1802,6 +1802,7 @@ static void InitDialog(HWND hDlg) // Create the string array StrArrayCreate(&DriveID, MAX_DRIVES); StrArrayCreate(&DriveLabel, MAX_DRIVES); + StrArrayCreate(&BlockingProcess, 16); // Set various checkboxes CheckDlgButton(hDlg, IDC_QUICKFORMAT, BST_CHECKED); CheckDlgButton(hDlg, IDC_BOOT, BST_CHECKED); @@ -2240,6 +2241,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA PostQuitMessage(0); StrArrayDestroy(&DriveID); StrArrayDestroy(&DriveLabel); + StrArrayDestroy(&BlockingProcess); DestroyAllTooltips(); DestroyWindow(hLogDlg); GetWindowRect(hDlg, &relaunch_rc); @@ -2455,6 +2457,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA return (INT_PTR)TRUE; } FormatStatus = 0; + StrArrayClear(&BlockingProcess); format_op_in_progress = TRUE; no_confirmation_on_cancel = FALSE; // Reset all progress bars @@ -2493,7 +2496,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA char* iso_image = lmprintf(MSG_036); char* dd_image = lmprintf(MSG_095); char* choices[2] = { lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image) }; - i = Selection(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image), + i = SelectionDialog(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image), choices, 2); if (i < 0) { // Cancel format_op_in_progress = FALSE; @@ -2826,9 +2829,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0); SetTaskbarProgressState(TASKBAR_ERROR); PrintInfo(0, MSG_212); - Notification(MSG_ERROR, NULL, lmprintf(MSG_042), lmprintf(MSG_043, StrError(FormatStatus, FALSE))); MessageBeep(MB_ICONERROR); FlashTaskbar(dialog_handle); + if (BlockingProcess.Index > 0) + ListDialog(lmprintf(MSG_042), lmprintf(MSG_055), BlockingProcess.String, BlockingProcess.Index); + else + Notification(MSG_ERROR, NULL, lmprintf(MSG_042), lmprintf(MSG_043, StrError(FormatStatus, FALSE))); } FormatStatus = 0; format_op_in_progress = FALSE; diff --git a/src/rufus.h b/src/rufus.h index 4aabdf5c..99a469e5 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -432,7 +432,8 @@ extern BOOL CreateTooltip(HWND hControl, const char* message, int duration); extern void DestroyTooltip(HWND hWnd); extern void DestroyAllTooltips(void); extern BOOL Notification(int type, const notification_info* more_info, char* title, char* format, ...); -extern int Selection(char* title, char* message, char** choices, int size); +extern int SelectionDialog(char* title, char* message, char** choices, int size); +extern void ListDialog(char* title, char* message, char** items, int size); extern SIZE GetTextSize(HWND hCtrl); extern BOOL ExtractDOS(const char* path); extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); diff --git a/src/rufus.rc b/src/rufus.rc index 1d163277..e6b4f384 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 2.15.1124" +CAPTION "Rufus 2.15.1125" FONT 8, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -164,6 +164,34 @@ BEGIN CONTROL "Choice 16",IDC_SELECTION_CHOICEMAX,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,213,269,10,WS_EX_TRANSPARENT END +IDD_LIST DIALOGEX 0, 0, 312, 59 +STYLE DS_SETFONT | DS_NOFAILCREATE | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME +CAPTION "Rufus" +FONT 8, "Segoe UI Symbol", 400, 0, 0x0 +BEGIN + LTEXT "",IDC_LIST_LINE,0,0,312,32 + LTEXT "",IDC_STATIC,0,0,312,31 + ICON IDI_ICON,IDC_LIST_ICON,6,6,20,20,0,WS_EX_TRANSPARENT + LTEXT "Message",IDC_LIST_TEXT,35,5,269,8 + PUSHBUTTON "OK",IDOK,254,39,50,14 + LTEXT "List 1",IDC_LIST_ITEM1,35,17,269,10,SS_PATHELLIPSIS + LTEXT "List 2",IDC_LIST_ITEM2,35,28,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 3",IDC_LIST_ITEM3,35,39,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 4",IDC_LIST_ITEM4,35,50,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 5",IDC_LIST_ITEM5,35,61,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 6",IDC_LIST_ITEM6,35,72,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 7",IDC_LIST_ITEM7,35,73,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 8",IDC_LIST_ITEM8,35,84,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 9",IDC_LIST_ITEM9,35,95,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 10",IDC_LIST_ITEM10,35,106,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 11",IDC_LIST_ITEM11,35,117,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 12",IDC_LIST_ITEM12,35,128,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 13",IDC_LIST_ITEM13,35,139,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 14",IDC_LIST_ITEM14,35,150,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 15",IDC_LIST_ITEM15,35,161,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS + LTEXT "List 16",IDC_LIST_ITEMMAX,35,172,269,10,NOT WS_VISIBLE|SS_PATHELLIPSIS +END + IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 198 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Update policy and settings" @@ -206,12 +234,12 @@ END // TEXTINCLUDE // -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#ifndef _USING_V110_SDK71_\r\n" "#define _USING_V110_SDK71_\r\n" @@ -223,7 +251,7 @@ BEGIN "\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "#ifdef RUFUS_LOC\r\n" @@ -317,6 +345,10 @@ BEGIN BEGIN END + IDD_LIST, DIALOG + BEGIN + END + IDD_UPDATE_POLICY, DIALOG BEGIN END @@ -334,8 +366,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,15,1124,0 - PRODUCTVERSION 2,15,1124,0 + FILEVERSION 2,15,1125,0 + PRODUCTVERSION 2,15,1125,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -352,13 +384,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.15.1124" + VALUE "FileVersion", "2.15.1125" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", " 2011-2017 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.15.1124" + VALUE "ProductVersion", "2.15.1125" END END BLOCK "VarFileInfo" @@ -413,24 +445,24 @@ IDR_FD_KB1_SYS RCDATA "../res/freedos/KEYBOARD.SYS" IDR_FD_KB2_SYS RCDATA "../res/freedos/KEYBRD2.SYS" IDR_FD_KB3_SYS RCDATA "../res/freedos/KEYBRD3.SYS" IDR_FD_KB4_SYS RCDATA "../res/freedos/KEYBRD4.SYS" -IDR_FD_EGA1_CPX RCDATA "../res/freedos/ega.cpx" -IDR_FD_EGA2_CPX RCDATA "../res/freedos/ega2.cpx" -IDR_FD_EGA3_CPX RCDATA "../res/freedos/ega3.cpx" -IDR_FD_EGA4_CPX RCDATA "../res/freedos/ega4.cpx" -IDR_FD_EGA5_CPX RCDATA "../res/freedos/ega5.cpx" -IDR_FD_EGA6_CPX RCDATA "../res/freedos/ega6.cpx" -IDR_FD_EGA7_CPX RCDATA "../res/freedos/ega7.cpx" -IDR_FD_EGA8_CPX RCDATA "../res/freedos/ega8.cpx" -IDR_FD_EGA9_CPX RCDATA "../res/freedos/ega9.cpx" -IDR_FD_EGA10_CPX RCDATA "../res/freedos/ega10.cpx" -IDR_FD_EGA11_CPX RCDATA "../res/freedos/ega11.cpx" -IDR_FD_EGA12_CPX RCDATA "../res/freedos/ega12.cpx" -IDR_FD_EGA13_CPX RCDATA "../res/freedos/ega13.cpx" -IDR_FD_EGA14_CPX RCDATA "../res/freedos/ega14.cpx" -IDR_FD_EGA15_CPX RCDATA "../res/freedos/ega15.cpx" -IDR_FD_EGA16_CPX RCDATA "../res/freedos/ega16.cpx" -IDR_FD_EGA17_CPX RCDATA "../res/freedos/ega17.cpx" -IDR_FD_EGA18_CPX RCDATA "../res/freedos/ega18.cpx" +IDR_FD_EGA1_CPX RCDATA "../res/freedos/EGA.CPX" +IDR_FD_EGA2_CPX RCDATA "../res/freedos/EGA2.CPX" +IDR_FD_EGA3_CPX RCDATA "../res/freedos/EGA3.CPX" +IDR_FD_EGA4_CPX RCDATA "../res/freedos/EGA4.CPX" +IDR_FD_EGA5_CPX RCDATA "../res/freedos/EGA5.CPX" +IDR_FD_EGA6_CPX RCDATA "../res/freedos/EGA6.CPX" +IDR_FD_EGA7_CPX RCDATA "../res/freedos/EGA7.CPX" +IDR_FD_EGA8_CPX RCDATA "../res/freedos/EGA8.CPX" +IDR_FD_EGA9_CPX RCDATA "../res/freedos/EGA9.CPX" +IDR_FD_EGA10_CPX RCDATA "../res/freedos/EGA10.CPX" +IDR_FD_EGA11_CPX RCDATA "../res/freedos/EGA11.CPX" +IDR_FD_EGA12_CPX RCDATA "../res/freedos/EGA12.CPX" +IDR_FD_EGA13_CPX RCDATA "../res/freedos/EGA13.CPX" +IDR_FD_EGA14_CPX RCDATA "../res/freedos/EGA14.CPX" +IDR_FD_EGA15_CPX RCDATA "../res/freedos/EGA15.CPX" +IDR_FD_EGA16_CPX RCDATA "../res/freedos/EGA16.CPX" +IDR_FD_EGA17_CPX RCDATA "../res/freedos/EGA17.CPX" +IDR_FD_EGA18_CPX RCDATA "../res/freedos/EGA18.CPX" IDR_XT_HOGGER RCDATA "../res/hogger/hogger.exe" IDR_UEFI_NTFS RCDATA "../res/uefi/uefi-ntfs.img" IDR_TOGO_SAN_POLICY_XML RCDATA "../res/togo/san_policy.xml" diff --git a/src/stdlg.c b/src/stdlg.c index a784a90e..310e2ef9 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -52,8 +52,8 @@ PF_TYPE_DECL(WINAPI, LPITEMIDLIST, SHSimpleIDListFromPath, (PCWSTR pszPath)); static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE; static char* szMessageText = NULL; static char* szMessageTitle = NULL; -static char **szSelectionChoice; -static int nSelectionChoices; +static char **szDialogItem; +static int nDialogItems; static HWND hBrowseEdit; extern HWND hUpdatesDlg; static WNDPROC pOrgBrowseWndproc; @@ -846,8 +846,8 @@ BOOL Notification(int type, const notification_info* more_info, char* title, cha } /* -* Custom dialog for radio button selection dialog -*/ + * Custom dialog for radio button selection dialog + */ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT loc; @@ -866,10 +866,10 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA switch (message) { case WM_INITDIALOG: // Don't overflow our max radio button - if (nSelectionChoices > (IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1 + 1)) { + if (nDialogItems > (IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1 + 1)) { uprintf("Warning: Too many options requested for Selection (%d vs %d)", - nSelectionChoices, IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1); - nSelectionChoices = IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1; + nDialogItems, IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1); + nDialogItems = IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1; } // TODO: This shouldn't be needed when using DS_SHELLFONT // Get the system message box font. See http://stackoverflow.com/a/6057761 @@ -888,7 +888,7 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA // Set the dialog to use the system message box font SendMessage(hDlg, WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hDlg, IDC_SELECTION_TEXT), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); - for (i = 0; i < nSelectionChoices; i++) + for (i = 0; i < nDialogItems; i++) SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hDlg, IDYES), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hDlg, IDNO), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); @@ -903,8 +903,8 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA SetWindowTextU(hDlg, szMessageTitle); SetWindowTextU(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)); SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_TEXT), szMessageText); - for (i = 0; i < nSelectionChoices; i++) { - SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), szSelectionChoice[i]); + for (i = 0; i < nDialogItems; i++) { + SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), szDialogItem[i]); ShowWindow(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), SW_SHOW); } // Move/Resize the controls as needed to fit our text @@ -918,12 +918,12 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA if (hDC != NULL) ReleaseDC(hCtrl, hDC); ResizeMoveCtrl(hDlg, hCtrl, 0, 0, 0, dh, 1.0f); - for (i = 0; i < nSelectionChoices; i++) + for (i = 0; i < nDialogItems; i++) ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), 0, dh, 0, 0, 1.0f); - if (nSelectionChoices > 2) { - GetWindowRect(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), &rect); - GetWindowRect(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), &rect2); - dh += (nSelectionChoices - 2) * (rect2.top - rect.top) + 5; + if (nDialogItems > 2) { + GetWindowRect(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), &rect); + GetWindowRect(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + nDialogItems - 1), &rect2); + dh += rect2.top - rect.top; } ResizeMoveCtrl(hDlg, hDlg, 0, 0, 0, dh, 1.0f); ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, -1), 0, 0, 0, dh, 1.0f); // IDC_STATIC = -1 @@ -954,9 +954,9 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: - for (i = 0; (i < nSelectionChoices) && + for (i = 0; (i < nDialogItems) && (Button_GetCheck(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i)) != BST_CHECKED); i++); - if (i < nSelectionChoices) + if (i < nDialogItems) r = i + 1; // Fall through case IDNO: @@ -970,23 +970,152 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA } /* -* Display a selection question -*/ -int Selection(char* title, char* message, char** choices, int size) + * Display an item selection dialog + */ +int SelectionDialog(char* title, char* message, char** choices, int size) { int ret; dialog_showing++; szMessageTitle = title; szMessageText = message; - szSelectionChoice = choices; - nSelectionChoices = size; + szDialogItem = choices; + nDialogItems = size; ret = (int)MyDialogBox(hMainInstance, IDD_SELECTION, hMainDialog, SelectionCallback); dialog_showing--; return ret; } +/* + * Custom dialog for list dialog + */ +INT_PTR CALLBACK ListCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT loc; + int i, dh, r = -1; + // Prevent resizing + static LRESULT disabled[9] = { HTLEFT, HTRIGHT, HTTOP, HTBOTTOM, HTSIZE, + HTTOPLEFT, HTTOPRIGHT, HTBOTTOMLEFT, HTBOTTOMRIGHT }; + static HBRUSH background_brush, separator_brush; + // To use the system message font + NONCLIENTMETRICS ncm; + RECT rect, rect2; + HFONT hDlgFont; + HWND hCtrl; + HDC hDC; + + switch (message) { + case WM_INITDIALOG: + // Don't overflow our max radio button + if (nDialogItems > (IDC_LIST_ITEMMAX - IDC_LIST_ITEM1 + 1)) { + uprintf("Warning: Too many items requested for List (%d vs %d)", + nDialogItems, IDC_LIST_ITEMMAX - IDC_LIST_ITEM1); + nDialogItems = IDC_LIST_ITEMMAX - IDC_LIST_ITEM1; + } + // TODO: This shouldn't be needed when using DS_SHELLFONT + // Get the system message box font. See http://stackoverflow.com/a/6057761 + ncm.cbSize = sizeof(ncm); + // If we're compiling with the Vista SDK or later, the NONCLIENTMETRICS struct + // will be the wrong size for previous versions, so we need to adjust it. +#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) + if (nWindowsVersion >= WINDOWS_VISTA) { + // In versions of Windows prior to Vista, the iPaddedBorderWidth member + // is not present, so we need to subtract its size from cbSize. + ncm.cbSize -= sizeof(ncm.iPaddedBorderWidth); + } +#endif + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0); + hDlgFont = CreateFontIndirect(&(ncm.lfMessageFont)); + // Set the dialog to use the system message box font + SendMessage(hDlg, WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); + SendMessage(GetDlgItem(hDlg, IDC_LIST_TEXT), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); + for (i = 0; i < nDialogItems; i++) + SendMessage(GetDlgItem(hDlg, IDC_LIST_ITEM1 + i), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); + SendMessage(GetDlgItem(hDlg, IDYES), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); + SendMessage(GetDlgItem(hDlg, IDNO), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); + + apply_localization(IDD_LIST, hDlg); + background_brush = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + separator_brush = CreateSolidBrush(GetSysColor(COLOR_3DLIGHT)); + SetTitleBarIcon(hDlg); + CenterDialog(hDlg); + // Change the default icon and set the text + Static_SetIcon(GetDlgItem(hDlg, IDC_LIST_ICON), LoadIcon(NULL, IDI_EXCLAMATION)); + SetWindowTextU(hDlg, szMessageTitle); + SetWindowTextU(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)); + SetWindowTextU(GetDlgItem(hDlg, IDC_LIST_TEXT), szMessageText); + for (i = 0; i < nDialogItems; i++) { + SetWindowTextU(GetDlgItem(hDlg, IDC_LIST_ITEM1 + i), szDialogItem[i]); + ShowWindow(GetDlgItem(hDlg, IDC_LIST_ITEM1 + i), SW_SHOW); + } + // Move/Resize the controls as needed to fit our text + hCtrl = GetDlgItem(hDlg, IDC_LIST_TEXT); + hDC = GetDC(hCtrl); + SelectFont(hDC, hDlgFont); // Yes, you *MUST* reapply the font to the DC, even after SetWindowText! + GetWindowRect(hCtrl, &rect); + dh = rect.bottom - rect.top; + DrawTextU(hDC, szMessageText, -1, &rect, DT_CALCRECT | DT_WORDBREAK); + dh = rect.bottom - rect.top - dh; + if (hDC != NULL) + ReleaseDC(hCtrl, hDC); + ResizeMoveCtrl(hDlg, hCtrl, 0, 0, 0, dh, 1.0f); + for (i = 0; i < nDialogItems; i++) + ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_LIST_ITEM1 + i), 0, dh, 0, 0, 1.0f); + if (nDialogItems > 1) { + GetWindowRect(GetDlgItem(hDlg, IDC_LIST_ITEM1), &rect); + GetWindowRect(GetDlgItem(hDlg, IDC_LIST_ITEM1 + nDialogItems - 1), &rect2); + dh += rect2.top - rect.top; + } + ResizeMoveCtrl(hDlg, hDlg, 0, 0, 0, dh, 1.0f); + ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, -1), 0, 0, 0, dh, 1.0f); // IDC_STATIC = -1 + ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_LIST_LINE), 0, dh, 0, 0, 1.0f); + ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDOK), 0, dh, 0, 0, 1.0f); + ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDCANCEL), 0, dh, 0, 0, 1.0f); + return (INT_PTR)TRUE; + case WM_CTLCOLORSTATIC: + // Change the background colour for static text and icon + SetBkMode((HDC)wParam, TRANSPARENT); + if ((HWND)lParam == GetDlgItem(hDlg, IDC_NOTIFICATION_LINE)) { + return (INT_PTR)separator_brush; + } + return (INT_PTR)background_brush; + case WM_NCHITTEST: + // Check coordinates to prevent resize actions + loc = DefWindowProc(hDlg, message, wParam, lParam); + for (i = 0; i < 9; i++) { + if (loc == disabled[i]) { + return (INT_PTR)TRUE; + } + } + return (INT_PTR)FALSE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case IDNO: + case IDCANCEL: + EndDialog(hDlg, r); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +/* + * Display a dialog with a list of items + */ +void ListDialog(char* title, char* message, char** items, int size) +{ + dialog_showing++; + szMessageTitle = title; + szMessageText = message; + szDialogItem = items; + nDialogItems = size; + MyDialogBox(hMainInstance, IDD_LIST, hMainDialog, ListCallback); + dialog_showing--; +} + static struct { HWND hTip; // Tooltip handle HWND hCtrl; // Handle of the control the tooltip belongs to