Skip to content
This repository has been archived by the owner on Nov 7, 2023. It is now read-only.

Commit

Permalink
Add message box dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
jchristopherson committed Aug 18, 2020
1 parent 586b326 commit 0455d1b
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 0 deletions.
24 changes: 24 additions & 0 deletions include/ui_dialogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@
extern "C" {
#endif

#define DIALOG_RESULT_CANCEL 0
#define DIALOG_RESULT_OK 1
#define DIALOG_RESULT_YES 2
#define DIALOG_RESULT_NO 3
#define DIALOG_RESULT_RETRY 4
#define DIALOG_RESULT_ABORT 5
#define DIALOG_RESULT_IGNORE 6
#define DIALOG_RESULT_CONTINUE 7
#define MSGBX_NO_ICON 0
#define MSGBX_NO_BUTTON 0
#define MSGBX_ICON_ERROR 1000
#define MSGBX_ICON_WARNING 1001
#define MSGBX_ICON_QUESTION 1002
#define MSGBX_ICON_INFORMATION 1003
#define MSGBX_BTN_OK 1004
#define MSGBX_BTN_OK_CANCEL 1005
#define MSGBX_BTN_YES_NO 1006
#define MSGBX_BTN_YES_NO_CANCEL 1007
#define MSGBX_BTN_RETRY_CANCEL 1008
#define MSGBX_BTN_ABORT_RETRY_IGNORE 1009
#define MSGBX_BTN_CANCEL_RETRY_CONTINUE 1010

bool init_ui_env_c();
void clean_up_ui_env_c();
void show_open_file_dialog_c(char *nameBuffer, int bufferSize, int *numChars,
Expand All @@ -18,6 +40,8 @@ void show_save_file_dialog_c(const char *defaultExt, int nfilters,
const char **filterName, const char **filterPattern, char *name,
int bufferSize, int *numChars);
void show_browse_folder_dialog_c(char *buffer, int bufferSize, int *numChars);
int show_message_box_c(void *parent, const char *txt, const char *title,
int buttons, int icon);

#ifdef __cplusplus
}
Expand Down
123 changes: 123 additions & 0 deletions src/ui_dialogs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,126 @@ void show_browse_folder_dialog_c(char *buffer, int bufferSize, int *numChars)
// End Window-Specific Code
}


int show_message_box_c(void *parent, const char *txt, const char *title,
int buttons, int icon)
{
// Windows-Specific Code
HWND hWnd = (HWND)parent;
UINT btn, icn, type;
int result;
size_t nchars;
wchar_t txtBuffer[4096], titleBuffer[4096];

switch (buttons) {
case MSGBX_BTN_OK:
btn = MB_OK;
break;

case MSGBX_BTN_OK_CANCEL:
btn = MB_OKCANCEL;
break;

case MSGBX_BTN_YES_NO:
btn = MB_YESNO;
break;

case MSGBX_BTN_YES_NO_CANCEL:
btn = MB_YESNOCANCEL;
break;

case MSGBX_BTN_RETRY_CANCEL:
btn = MB_RETRYCANCEL;
break;

case MSGBX_BTN_ABORT_RETRY_IGNORE:
btn = MB_ABORTRETRYIGNORE;
break;

case MSGBX_BTN_CANCEL_RETRY_CONTINUE:
btn = MB_CANCELTRYCONTINUE;
break;

default:
btn = MSGBX_NO_BUTTON;
break;
}

switch (icon) {
case MSGBX_ICON_ERROR:
icn = MB_ICONERROR;
break;

case MSGBX_ICON_WARNING:
icn = MB_ICONWARNING;
break;

case MSGBX_ICON_QUESTION:
icn = MB_ICONQUESTION;
break;

case MSGBX_ICON_INFORMATION:
icn = MB_ICONINFORMATION;
break;

default:
icn = MSGBX_NO_ICON;
break;
}

if (btn == MSGBX_NO_BUTTON && icn == MSGBX_NO_ICON) {
type = 0;
}
else if (btn == MSGBX_NO_BUTTON && icn != MSGBX_NO_ICON) {
type = icn;
}
else if (btn != MSGBX_NO_BUTTON && icn == MSGBX_NO_ICON) {
type = btn;
}
else {
type = btn | icn;
}

nchars = mbstowcs(txtBuffer, txt, MIN(4096, strlen(txt) + 1));
nchars = mbstowcs(titleBuffer, title, MIN(4096, strlen(title) + 1));
result = MessageBox(hWnd, txtBuffer, titleBuffer, type);

switch (result) {
case IDABORT:
result = DIALOG_RESULT_ABORT;
break;

case IDCANCEL:
result = DIALOG_RESULT_CANCEL;
break;

case IDCONTINUE:
result = DIALOG_RESULT_CONTINUE;
break;

case IDIGNORE:
result = DIALOG_RESULT_IGNORE;
break;

case IDNO:
result = DIALOG_RESULT_NO;
break;

case IDOK:
result = DIALOG_RESULT_OK;
break;

case IDRETRY:
result = DIALOG_RESULT_RETRY;
break;

case IDYES:
result = DIALOG_RESULT_YES;
break;
}

// End Window-Specific Code

// End
return result;
}
102 changes: 102 additions & 0 deletions src/ui_dialogs.f90
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ module ui_dialogs
public :: DIALOG_RESULT_RETRY
public :: DIALOG_RESULT_ABORT
public :: DIALOG_RESULT_IGNORE
public :: DIALOG_RESULT_CONTINUE
public :: MSGBX_NO_ICON
public :: MSGBX_NO_BUTTON
public :: MSGBX_ICON_ERROR
public :: MSGBX_ICON_WARNING
public :: MSGBX_ICON_QUESTION
public :: MSGBX_ICON_INFORMATION
public :: MSGBX_BTN_OK
public :: MSGBX_BTN_OK_CANCEL
public :: MSGBX_BTN_YES_NO
public :: MSGBX_BTN_YES_NO_CANCEL
public :: MSGBX_BTN_RETRY_CANCEL
public :: MSGBX_BTN_ABORT_RETRY_IGNORE
public :: MSGBX_BTN_CANCEL_RETRY_CONTINUE
public :: dialog_result
public :: text_output_dialog_result
public :: file_filter
Expand All @@ -23,6 +37,7 @@ module ui_dialogs
public :: show_open_multifile_dialog
public :: show_save_file_dialog
public :: show_browse_folder_dialog
public :: show_message_box

! TO DO: Message-Box type dialog & associated icons, buttons, etc.

Expand All @@ -41,6 +56,34 @@ module ui_dialogs
integer(int32), parameter :: DIALOG_RESULT_ABORT = 5
!> @brief The dialog result is an ignore button press.
integer(int32), parameter :: DIALOG_RESULT_IGNORE = 6
!> @brief The dialog result is a continue button press.
integer(int32), parameter :: DIALOG_RESULT_CONTINUE = 7
!> @brief Indicates that no icon should be used for the dialog.
integer(int32), parameter :: MSGBX_NO_ICON = 0
!> @brief Indicates that no button should be used for the dialog.
integer(int32), parameter :: MSGBX_NO_BUTTON = 0
!> @brief Indicates that an error icon should be used for the dialog.
integer(int32), parameter :: MSGBX_ICON_ERROR = 1000
!> @brief Indicates that a warning icon should be used for the dialog.
integer(int32), parameter :: MSGBX_ICON_WARNING = 1001
!> @brief Indicates that a question icon should be used for the dialog.
integer(int32), parameter :: MSGBX_ICON_QUESTION = 1002
!> @brief Indicates that an information icon should be used for the dialog.
integer(int32), parameter :: MSGBX_ICON_INFORMATION = 1003
!> @brief Indicates that an OK button should be used.
integer(int32), parameter :: MSGBX_BTN_OK = 1004
!> @brief Indicates that an OK-Cancel button pair should be used.
integer(int32), parameter :: MSGBX_BTN_OK_CANCEL = 1005
!> @brief Indicates that a Yes-No button pair should be used.
integer(int32), parameter :: MSGBX_BTN_YES_NO = 1006
!> @brief Indicates that a Yes-No-Cancel button set should be used.
integer(int32), parameter :: MSGBX_BTN_YES_NO_CANCEL = 1007
!> @brief Indicates that a Retry-Cancel button set should be used.
integer(int32), parameter :: MSGBX_BTN_RETRY_CANCEL = 1008
!> @brief Indicates that an Abory-Retry-Ignore button set should be used.
integer(int32), parameter :: MSGBX_BTN_ABORT_RETRY_IGNORE = 1009
!> @brief Indicates that a Cancel-Retry-Continue button set should be used.
integer(int32), parameter :: MSGBX_BTN_CANCEL_RETRY_CONTINUE = 1010

! ------------------------------------------------------------------------------
!> @brief A type containing results from the dialog interaction.
Expand Down Expand Up @@ -172,6 +215,25 @@ subroutine show_browse_folder_dialog_c(buffer, bufferSize, numChars) &
integer(c_int), intent(in), value :: bufferSize
integer(c_int), intent(out) :: numChars
end subroutine

!> @brief Shows the user a message box.
!!
!! @param[in] parent A pointer to the parent window. This can be null
!! in the event there isn't a parent window.
!! @param[in] txt The message box text.
!! @param[in] title The title of the message box.
!! @param[in] buttons
!! @param[in] icon
!!
!! @return The dialog result.
function show_message_box_c(parent, txt, title, buttons, icon) &
result(rst) bind(C, name = "show_message_box_c")
use iso_c_binding
type(c_ptr), intent(in), value :: parent
character(kind = c_char), intent(in) :: txt(*), title(*)
integer(c_int), intent(in), value :: buttons, icon
integer(c_int) :: rst
end function
end interface

! ------------------------------------------------------------------------------
Expand Down Expand Up @@ -396,5 +458,45 @@ function show_browse_folder_dialog() result(rst)
end if
end function

! ------------------------------------------------------------------------------
!> @brief Shows the user a message box dialog.
!!
!! @param[in] txt The text to display in the message box.
!! @param[in] title The title to display in the header of the message box.
!! @param[in] buttons Defines what button group to display. The following
!! choices are acceptable: MSGBX_BTN_OK, MSGBX_BTN_OK_CANCEL,
!! MSGBX_BTN_YES_NO, MSGBX_BTN_YES_NO_CANCEL, MSGBX_BTN_RETRY_CANCEL,
!! MSGBX_BTN_ABORT_RETRY_IGNORE, MSGBX_BTN_CANCEL_RETRY_CONTINUE.
!! @param[in] icon Defines what icons to display. The following choices
!! are acceptable: MSGBX_NO_ICON, MSGBX_NO_BUTTON, MSGBX_ICON_ERROR,
!! MSGBX_ICON_WARNING, MSGBX_ICON_QUESTION, MSGBX_ICON_INFORMATION.
!! @param[in] parent An optional argument defining a pointer to the parent
!! window. If not supplied, no parent is assumed.
!!
!! @return The results from the dialog.
function show_message_box(txt, title, buttons, icon, parent) result(rst)
! Arguments
character(len = *), intent(in) :: txt, title
integer(int32), intent(in) :: buttons, icon
type(c_ptr), optional :: parent
type(dialog_result) :: rst

! Local Variables
character(kind = c_char, len = :), allocatable :: ctxt, ctitle
type(c_ptr) :: parentPtr

! Initialization
ctxt = txt // C_NULL_CHAR
ctitle = title // C_NULL_CHAR
if (present(parent)) then
parentPtr = parent
else
parentPtr = c_null_ptr
end if

! Process
rst%result = show_message_box_c(parentPtr, ctxt, ctitle, buttons, icon)
end function

! ------------------------------------------------------------------------------
end module

0 comments on commit 0455d1b

Please sign in to comment.