diff --git a/v2/internal/frontend/desktop/windows/dialog.go b/v2/internal/frontend/desktop/windows/dialog.go index 89659591..ab41df33 100644 --- a/v2/internal/frontend/desktop/windows/dialog.go +++ b/v2/internal/frontend/desktop/windows/dialog.go @@ -9,6 +9,7 @@ import ( "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd" "golang.org/x/sys/windows" "path/filepath" + "strings" "syscall" ) @@ -152,6 +153,26 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e return result, nil } +func calculateMessageDialogFlags(options frontend.MessageDialogOptions) uint32 { + var flags uint32 + + switch options.Type { + case frontend.InfoDialog: + flags = windows.MB_OK | windows.MB_ICONINFORMATION + case frontend.ErrorDialog: + flags = windows.MB_ICONERROR | windows.MB_OK + case frontend.QuestionDialog: + flags = windows.MB_YESNO + if strings.TrimSpace(strings.ToLower(options.DefaultButton)) == "no" { + flags |= windows.MB_DEFBUTTON2 + } + case frontend.WarningDialog: + flags = windows.MB_OK | windows.MB_ICONWARNING + } + + return flags +} + // MessageDialog show a message dialog to the user func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string, error) { @@ -163,17 +184,8 @@ func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string, if err != nil { return "", err } - var flags uint32 - switch options.Type { - case frontend.InfoDialog: - flags = windows.MB_OK | windows.MB_ICONINFORMATION - case frontend.ErrorDialog: - flags = windows.MB_ICONERROR | windows.MB_OK - case frontend.QuestionDialog: - flags = windows.MB_YESNO - case frontend.WarningDialog: - flags = windows.MB_OK | windows.MB_ICONWARNING - } + + flags := calculateMessageDialogFlags(options) button, _ := windows.MessageBox(windows.HWND(f.getHandleForDialog()), message, title, flags|windows.MB_SYSTEMMODAL) // This maps MessageBox return values to strings diff --git a/v2/internal/frontend/desktop/windows/dialog_test.go b/v2/internal/frontend/desktop/windows/dialog_test.go new file mode 100644 index 00000000..96d8b784 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/dialog_test.go @@ -0,0 +1,74 @@ +package windows + +import ( + "github.com/wailsapp/wails/v2/internal/frontend" + "golang.org/x/sys/windows" + "testing" +) + +func Test_calculateMessageDialogFlags(t *testing.T) { + tests := []struct { + name string + options frontend.MessageDialogOptions + want uint32 + }{ + { + name: "Test Info Dialog", + options: frontend.MessageDialogOptions{ + Type: frontend.InfoDialog, + }, + want: windows.MB_OK | windows.MB_ICONINFORMATION, + }, + { + name: "Test Error Dialog", + options: frontend.MessageDialogOptions{ + Type: frontend.ErrorDialog, + }, + want: windows.MB_ICONERROR | windows.MB_OK, + }, + { + name: "Test Question Dialog", + options: frontend.MessageDialogOptions{ + Type: frontend.QuestionDialog, + }, + want: windows.MB_YESNO, + }, + { + name: "Test Question Dialog with default cancel", + options: frontend.MessageDialogOptions{ + Type: frontend.QuestionDialog, + DefaultButton: "No", + }, + want: windows.MB_YESNO | windows.MB_DEFBUTTON2, + }, + { + name: "Test Question Dialog with default cancel (lowercase)", + options: frontend.MessageDialogOptions{ + Type: frontend.QuestionDialog, + DefaultButton: "no", + }, + want: windows.MB_YESNO | windows.MB_DEFBUTTON2, + }, + { + name: "Test Warning Dialog", + options: frontend.MessageDialogOptions{ + Type: frontend.WarningDialog, + }, + want: windows.MB_OK | windows.MB_ICONWARNING, + }, + { + name: "Test Error Dialog", + options: frontend.MessageDialogOptions{ + Type: frontend.ErrorDialog, + }, + want: windows.MB_ICONERROR | windows.MB_OK, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := calculateMessageDialogFlags(tt.options); got != tt.want { + t.Errorf("calculateMessageDialogFlags() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/website/docs/reference/runtime/dialog.mdx b/website/docs/reference/runtime/dialog.mdx index 2f487ee3..a15b9ac4 100644 --- a/website/docs/reference/runtime/dialog.mdx +++ b/website/docs/reference/runtime/dialog.mdx @@ -117,19 +117,32 @@ type MessageDialogOptions struct { } ``` -| Field | Description | Win | Mac | Lin | -| ------------- | ------------------------------------------------------------------------- | --- | --- | --- | -| Type | The type of message dialog, eg question, info... | ✅ | ✅ | ✅ | -| Title | Title for the dialog | ✅ | ✅ | ✅ | -| Message | The message to show the user | ✅ | ✅ | ✅ | -| Buttons | A list of button titles | | ✅ | | -| DefaultButton | The button with this text should be treated as default. Bound to `return` | | ✅ | | -| CancelButton | The button with this text should be treated as cancel. Bound to `escape` | | ✅ | | +| Field | Description | Win | Mac | Lin | +|---------------|----------------------------------------------------------------------------|----------------|-----|-----| +| Type | The type of message dialog, eg question, info... | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| Message | The message to show the user | ✅ | ✅ | ✅ | +| Buttons | A list of button titles | | ✅ | | +| DefaultButton | The button with this text should be treated as default. Bound to `return`. | ✅[*](#windows) | ✅ | | +| CancelButton | The button with this text should be treated as cancel. Bound to `escape` | | ✅ | | #### Windows Windows has standard dialog types in which the buttons are not customisable. -The value returned will be one of: "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" or "Continue" +The value returned will be one of: "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" or "Continue". + +For Question dialogs, the default button is "Yes" and the cancel button is "No". +This can be changed by setting the `DefaultButton` value to `"No"`. + +Example: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` #### Linux