Page 1 of 2

Cross Platform MessageRequester

Posted: Wed May 30, 2012 9:39 pm
by Frarth
While searching the PB forum I noticed that there is not very much to find on a cross platform MessageRequester. Most examples are for windows only, while those developing on Linux have to do more of the hard work themselves (like showing icons). So I picked some examples and wrote some simple code to provide a cross platform MessageRequester. Any suggestions are welcome.

Include file ExtMessageRequester.pbi

Code: Select all

; Extended Message Requester include file (p) 2012 Frarth
; ------------------------------------------------------------------
EnableExplicit

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  #GTK_BUTTONS_YESNOCANCEL = 6
  #MR_BUTTON_YES = #GTK_RESPONSE_YES
  #MR_BUTTON_NO = #GTK_RESPONSE_NO
  #MR_BUTTON_CANCEL = #GTK_RESPONSE_CANCEL
  #MR_ICON_ERROR = #GTK_MESSAGE_ERROR * $200
  #MR_ICON_INFORMATION = #GTK_MESSAGE_INFO * $200
  #MR_ICON_QUESTION = #GTK_MESSAGE_QUESTION * $200
  #MR_ICON_WARNING = #GTK_MESSAGE_WARNING * $200
CompilerElse
  #MR_BUTTON_YES = #PB_MessageRequester_Yes
  #MR_BUTTON_NO = #PB_MessageRequester_No
  #MR_BUTTON_CANCEL = #PB_MessageRequester_Cancel
  #MR_ICON_ERROR = #MB_ICONERROR
  #MR_ICON_INFORMATION = #MB_ICONINFORMATION
  #MR_ICON_QUESTION = #MB_ICONQUESTION
  #MR_ICON_WARNING = #MB_ICONWARNING
CompilerEndIf

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  Declare GTK_MessageRequester(Title.s, Message.s, Buttons.l = #GTK_BUTTONS_OK, Type.l = #GTK_MESSAGE_INFO, Sub1.s = "", Sub2.s = "")
CompilerEndIf

Declare.i MessageRequesterX(Title.s, Message.s, Flags.l = 0)
Module ExtMessageRequester.pb

Code: Select all

; Extended MessageRequester (p) 2012 Frarth
; ----------------------------------------------------
EnableExplicit

XIncludeFile "ExtMessageRequester.pbi"

CompilerIf #PB_Compiler_OS = #PB_OS_Linux

Procedure GTK_MessageRequester(Title.s, Message.s, Buttons.l = #GTK_BUTTONS_OK, Type.l = #GTK_MESSAGE_INFO, Sub1.s = "", Sub2.s = "")
  Protected *dialog.GtkMessageDialog
  Protected result.i
  
  *dialog = gtk_message_dialog_new_(0, #True, Type, Buttons, Message, Sub1, Sub2)
  gtk_window_set_title_(*dialog, Title)
  
  If Buttons = #GTK_BUTTONS_YESNOCANCEL
    gtk_dialog_add_button_(*dialog, #GTK_STOCK_CANCEL, #GTK_RESPONSE_CANCEL)
    gtk_dialog_add_button_(*dialog, #GTK_STOCK_NO, #GTK_RESPONSE_NO)
    gtk_dialog_add_button_(*dialog, #GTK_STOCK_YES, #GTK_RESPONSE_YES)
  EndIf
  
  result = gtk_dialog_run_(*dialog)
  gtk_widget_destroy_(*dialog)
  
  ProcedureReturn result
EndProcedure

CompilerEndIf

Procedure.i MessageRequesterX(Title.s, Message.s, Flags.l = 0)
  Protected buttons.l, result.l, type.l
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Select Flags & $1FF
    Case #PB_MessageRequester_YesNo 
      buttons = #GTK_BUTTONS_YES_NO
    Case #PB_MessageRequester_YesNoCancel
      buttons = #GTK_BUTTONS_YESNOCANCEL
    Case #PB_MessageRequester_Ok
      buttons = #GTK_BUTTONS_OK
    EndSelect
    ; TYPE
    type = Flags / $200
    result = GTK_MessageRequester(Title, Message, buttons, type)
  CompilerElse ; Windows, Mac
    result = MessageRequester(Title, Message, Flags)
  CompilerEndIf
  ProcedureReturn result
EndProcedure

; Example
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  gtk_init_(0,0)
CompilerEndIf

Define response.i
response = MessageRequesterX("Test", "Are you sure you want to use this stuff?", #PB_MessageRequester_YesNoCancel | #MR_ICON_QUESTION)
If response = #MR_BUTTON_YES
  Debug "That is a YES!"
ElseIf response = #MR_BUTTON_NO
  Debug "No, too bad."
Else
  Debug "Please make up your mind!"
EndIf

Re: Cross Platform MessageRequester

Posted: Wed May 30, 2012 9:59 pm
by IdeasVacuum
I think it's necessary to to reorganise CompilerCase. As-is, cannot compile on Windows (#GTK constants not defined, structure GtkMessageDialog not defined etc.)

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 6:49 am
by Frarth
Thanks for the input. Will redo my homework. :-)

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 7:10 am
by ts-soft
There is a problem on linux. I can press any button of the requester, the result is always: "Please make up your mind!"

(Ubuntu 12.04 x64)

// edit
The problem occurs only on x64!

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 8:29 am
by Frarth
I don't have the ability to test on x64!

Have you debugged the output? It should generate three different results.

Please let me know if you've found a solution.

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 8:44 am
by ts-soft
Here the fixed version.

changed:
- some variable types to long
- added compilerdirectives to run under macos and windows

Code: Select all

; Extended MessageRequester (p) 2012 Frarth
; -------------------------------------------------------
EnableExplicit

#GTK_BUTTONS_YESNOCANCEL = 6

CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
  #MR_BUTTON_YES = #GTK_RESPONSE_YES
  #MR_BUTTON_NO = #GTK_RESPONSE_NO
  #MR_BUTTON_CANCEL = #GTK_RESPONSE_CANCEL
  #MR_ICON_ERROR = #GTK_MESSAGE_ERROR * $200
  #MR_ICON_INFORMATION = #GTK_MESSAGE_INFO * $200
  #MR_ICON_QUESTION = #GTK_MESSAGE_QUESTION * $200
  #MR_ICON_WARNING = #GTK_MESSAGE_WARNING * $200
CompilerDefault
  #MR_BUTTON_YES = #PB_MessageRequester_Yes
  #MR_BUTTON_NO = #PB_MessageRequester_No
  #MR_BUTTON_CANCEL = #PB_MessageRequester_Cancel
  #MR_ICON_ERROR = #MB_ICONERROR
  #MR_ICON_INFORMATION = #MB_ICONINFORMATION
  #MR_ICON_QUESTION = #MB_ICONQUESTION
  #MR_ICON_WARNING = #MB_ICONWARNING
CompilerEndSelect

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
Procedure GTK_MessageRequester(Title.s, Message.s, Buttons.l = #GTK_BUTTONS_OK, Type.l = #GTK_MESSAGE_INFO, Sub1.s = "", Sub2.s = "")
  Protected *dialog.GtkMessageDialog
  Protected result.i
 
  *dialog = gtk_message_dialog_new_(0, #True, Type, Buttons, Message, Sub1, Sub2)
  gtk_window_set_title_(*dialog, Title)
 
  If Buttons = #GTK_BUTTONS_YESNOCANCEL
    gtk_dialog_add_button_(*dialog, #GTK_STOCK_CANCEL, #GTK_RESPONSE_CANCEL)
    gtk_dialog_add_button_(*dialog, #GTK_STOCK_NO, #GTK_RESPONSE_NO)
    gtk_dialog_add_button_(*dialog, #GTK_STOCK_YES, #GTK_RESPONSE_YES)
  EndIf
 
  result = gtk_dialog_run_(*dialog)
  gtk_widget_destroy_(*dialog)
 
  ProcedureReturn result
EndProcedure
CompilerEndIf

Procedure.i MessageRequesterX(Title.s, Message.s, Flags.l = 0)
  Protected buttons.l, result.l, type.l
  CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    Select Flags & $1FF
    Case #PB_MessageRequester_YesNo
      buttons = #GTK_BUTTONS_YES_NO
    Case #PB_MessageRequester_YesNoCancel
      buttons = #GTK_BUTTONS_YESNOCANCEL
     Case #PB_MessageRequester_Ok
      buttons = #GTK_BUTTONS_OK
    EndSelect
    ; TYPE
    type = Flags / $200
    result = GTK_MessageRequester(Title, Message, buttons, type)
  CompilerDefault ; Windows, Mac
    result = MessageRequester(Title, Message, Flags)
  CompilerEndSelect
  ProcedureReturn result
EndProcedure

;- Example
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  gtk_init_(0,0)
CompilerEndIf

Define response.i
response = MessageRequesterX("Test", "Are you sure you want to use this stuff?", #PB_MessageRequester_YesNoCancel | #MR_ICON_QUESTION)
If response = #MR_BUTTON_YES
  Debug "That is a YES!"
ElseIf response = #MR_BUTTON_NO
  Debug "No, too bad."
Else
  Debug "Please make up your mind!"
EndIf 
Greetings - Thomas

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 8:49 am
by Frarth
I have updated the code snippet above. It should work fine on Windows now (tested on Windows XP SP3).

So LONG should be used instead of INTEGER on x64.

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 8:53 am
by Frarth
Thanks for testing Thomas!

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 8:56 am
by ts-soft
Frarth wrote:So LONG should be used instead of INTEGER on x64.
No, the best is integer, but if you make some bitshifting (<< >>) or bitwise or (&), you have to use
the required type (mostly long)

Re: Cross Platform MessageRequester

Posted: Thu May 31, 2012 8:59 am
by Frarth
Got it!

Re: Cross Platform MessageRequester

Posted: Sat Jun 02, 2012 2:02 am
by Guimauve
Hello everyone,

This my vision of the Frarth's original code :

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : Extended Message Requester
; File Name : Extended Message Requester.pb
; File version: 1.0.0
; Programming : OK
; Programmed by : Guimauve
; Date : 01-06-2012
; Last Update : 01-06-2012
; PureBasic code : 4.61
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Notes :
;
; Extended Message Requester include file
; 2012 Frarth

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  
  #GTK_BUTTONS_YESNOCANCEL = 6
  #MR_BUTTON_YES = #GTK_RESPONSE_YES
  #MR_BUTTON_NO = #GTK_RESPONSE_NO
  #MR_BUTTON_CANCEL = #GTK_RESPONSE_CANCEL
  #MR_ICON_ERROR = #GTK_MESSAGE_ERROR * $200
  #MR_ICON_INFORMATION = #GTK_MESSAGE_INFO * $200
  #MR_ICON_QUESTION = #GTK_MESSAGE_QUESTION * $200
  #MR_ICON_WARNING = #GTK_MESSAGE_WARNING * $200
  
  Procedure GTK_MessageRequester(Title.s, Message.s, Buttons.l = #GTK_BUTTONS_OK, Type.l = #GTK_MESSAGE_INFO, Sub1.s = "", Sub2.s = "")
    
    Protected *dialog.GtkMessageDialog, result.i
    Static OneShot.b
    
    If OneShot = #False
      gtk_init_(0,0)
      OneShot = #True
    EndIf
    
    *dialog = gtk_message_dialog_new_(0, #True, Type, Buttons, Message, Sub1, Sub2)
    gtk_window_set_title_(*dialog, Title)
    
    If Buttons = #GTK_BUTTONS_YESNOCANCEL
      gtk_dialog_add_button_(*dialog, #GTK_STOCK_YES, #GTK_RESPONSE_YES)
      gtk_dialog_add_button_(*dialog, #GTK_STOCK_NO, #GTK_RESPONSE_NO)
      gtk_dialog_add_button_(*dialog, #GTK_STOCK_CANCEL, #GTK_RESPONSE_CANCEL)
    EndIf
    
    result = gtk_dialog_run_(*dialog)
    gtk_widget_destroy_(*dialog)
    
    ProcedureReturn result
  EndProcedure
  
CompilerElse
  
  #MR_BUTTON_YES = #PB_MessageRequester_Yes
  #MR_BUTTON_NO = #PB_MessageRequester_No
  #MR_BUTTON_CANCEL = #PB_MessageRequester_Cancel
  #MR_ICON_ERROR = #MB_ICONERROR
  #MR_ICON_INFORMATION = #MB_ICONINFORMATION
  #MR_ICON_QUESTION = #MB_ICONQUESTION
  #MR_ICON_WARNING = #MB_ICONWARNING
  
CompilerEndIf

; Extended MessageRequester (p) 2012 Frarth
; ----------------------------------------------------

Procedure.i MessageRequesterEx(Title.s, Message.s, Flags.l = 0)
  
  Protected buttons.l, result.l, type.l
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    
    Select Flags & $1FF
        
      Case #PB_MessageRequester_YesNo 
        buttons = #GTK_BUTTONS_YES_NO
        
      Case #PB_MessageRequester_YesNoCancel
        buttons = #GTK_BUTTONS_YESNOCANCEL
        
      Case #PB_MessageRequester_Ok
        buttons = #GTK_BUTTONS_OK
        
    EndSelect
    
    result = GTK_MessageRequester(Title, Message, buttons, Flags / $200)
    
  CompilerElse ; Windows, Mac
    result = MessageRequester(Title, Message, Flags)
    
  CompilerEndIf
  
  ProcedureReturn result
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<< 
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<< 
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<< 
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

Select MessageRequesterEx("Test", "Are you sure you want to use this stuff?", #PB_MessageRequester_YesNoCancel | #MR_ICON_QUESTION)
    
  Case #MR_BUTTON_YES
    Debug "That is a YES!"
    
  Case #MR_BUTTON_NO
    Debug "No, too bad."
    
  Case #MR_BUTTON_CANCEL
    Debug "Please make up your mind!"
    
EndSelect

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Best regards
Guimauve

Re: Cross Platform MessageRequester

Posted: Sat Jun 02, 2012 6:31 am
by Frarth
Looks nice, only you forgot to remove the type.l variable declaration in MessageRequesterEx. :wink:

I put constant, structure, procedure declarations etc. in include files because my apps always have this set up:

Code: Select all

;- include files for public declarations (no procedure definitions here)

;- app flow

;- include modules including private declarations (all procedure definitions here)
That is why I got things separated. :!:

Re: Cross Platform MessageRequester

Posted: Sat Oct 03, 2015 5:33 pm
by Keya
Great thread, thankyou everyone for contributions!:)

The following is a mashup mostly based on code in this thread but also some by wilbert to add Mac OSX support. (NOW it's "Cross Platform" heehee :D)

Ive called this MsgAlert() ... a simple (simplicity/minimal over flexibility) cross-platform messagebox with an OK button, and your choice of Information, Warning, or Error icon (easily extended).

Code: Select all

EnableExplicit

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Global Workspace.i = CocoaMessage(0, 0, "NSWorkspace sharedWorkspace")
  #MB_ICONINFORMATION = $40      
  #MB_ICONWARNING     = $30
  #MB_ICONERROR       = $10
  
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux  
  #MB_ICONINFORMATION = #GTK_MESSAGE_INFO      
  #MB_ICONWARNING     = #GTK_MESSAGE_WARNING
  #MB_ICONERROR       = #GTK_MESSAGE_ERROR
CompilerEndIf


Procedure.i ToAscii(inbuf$)  ;required for Linux unicode-compiled version
  Protected *outbuf = AllocateMemory(Len(inbuf$)+1)
  If *outbuf
    PokeS(*outbuf, inbuf$, -1, #PB_Ascii)   ;perhaps this should be #PB_Utf8 seeing as thats what the Linux one wants
  EndIf
  ProcedureReturn *outbuf
EndProcedure


Procedure MsgAlert (hWnd.i, Title.s, Message.s, MB_ICON.i)   ;Supports #MB_ICONINFORMATION, #MB_ICONERROR, #MB_ICONWARNING
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    MessageBox_(hWnd, Message, Title, #MB_OK + MB_ICON)
    
  CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS    ;based on example by wilbert
    Protected Type.s, Alert.i = CocoaMessage(0, CocoaMessage(0, 0, "NSAlert new"), "autorelease")
    Select MB_ICON
      Case #MB_ICONWARNING: Type.s = "'caut'"
      Case #MB_ICONERROR: Type.s = "'stop'"
      Default: Type.s = "'note'"
    EndSelect
    CocoaMessage(0, CocoaMessage(0, Alert, "window"), "setParentWindow:", hWnd)
    CocoaMessage(0, Alert, "setMessageText:$", @Title)
    CocoaMessage(0, Alert, "setInformativeText:$", @Message)
    CocoaMessage(0, Alert, "setIcon:", CocoaMessage(0, Workspace, "iconForFileType:$", @Type))
    CocoaMessage(0, Alert, "runModal")

  CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux    ;based on example by Frarth & Guimauve
    Protected *dlgmsgbox.GtkMessageDialog, result.i, Sub1.i, Sub2.i, pMsg.i, pTitle.i
    pMsg = ToAscii(Message):  pTitle = ToAscii(Title)
    *dlgmsgbox = gtk_message_dialog_new_(hWnd, #True, MB_ICON, #GTK_BUTTONS_OK, pMsg, Sub1, Sub2)
    gtk_window_set_title_(*dlgmsgbox, pTitle)   
    result = gtk_dialog_run_(*dlgmsgbox)
    gtk_widget_destroy_(*dlgmsgbox)   
    
  CompilerEndIf
  
EndProcedure



CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  gtk_init_(0,0)
CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
  InitCommonControls_()
CompilerEndIf  


Define hWnd.i = 0  ;#HWND_DESKTOP
MsgAlert(hWnd, "My INFO!", "My message line 1" + Chr($D) + Chr($A) + "Line 2", #MB_ICONINFORMATION)  ;$0A, $0D, and $0D0A all work fine on all 3 OS for messageboxes in my tests
MsgAlert(hWnd, "My ERROR!", "My message line 1" + Chr($D) + "Line 2", #MB_ICONERROR)
MsgAlert(hWnd, "My WARNING!", "My message line 1" + Chr($A) + "Line 2", #MB_ICONWARNING)
It supports Windows + Linux + Mac, 32 + 64, Ascii + Unicode, but i had to add the ToAscii function to support unicode-compiled Linux... is there a better way?

Re: Cross Platform MessageRequester

Posted: Tue Oct 06, 2015 5:12 pm
by Oma
Hi
@Frarth and Keya

sorry, i'm a little late, i know, but time is rare!

A few words to your Linux versions:
To show not only the first letters on the Requester texts, buttons and window title on Unicode OR no Umlauts with Ascii use proper Imports. All textes must be in UTF8-format.

@Keya: to get a feedback if more then 1 button is shown, make a ProcedureReturn of the 'result'-variable AND this 'result' AND the function type must be 'long' for proper return on Linux-64Bit.

Two examples:
http://www.chabba.de/Linux/Requester/Me ... p_Modal.pb
http://www.chabba.de/Linux/Requester/Me ... unction.pb

Best Regards
Charly

Re: Cross Platform MessageRequester

Posted: Tue Oct 06, 2015 5:37 pm
by Keya
Oma wrote:@Keya: to get a feedback if more then 1 button is shown...
just for this 'MsgAlert' function i was aiming purely for simplicity and minimal code over flexibility, so just the one OK button and i intentionally stripped the responder out as it seemed i could, being single button
I will get around to rewriting it for flexibility at a later stage, and will certainly be using your examples, thankyou! :) but before that, next on my Todo list is get accustomed to using p-ascii/p-utf8 as we prepare for Unicode-only PB :D
I want to feel comfortable using Ascii from Unicode-compiled, but ive still got a lot more learning to do there. But I am more than willing to put in the time, because it feels good to overcome these hurdles, and then i can get on programming with "the whole ascii/unicode thing" being a tool instead of an obstruction. I hope :)