I've hit an issue with using the Dialog Preserve command. I get the error message "Invalid Dialog preserve command. There is no active dialog". As far as I can tell I've followed the guidance provided in the MapBasic reference guide. Here is a subset of my code which reproduces the error in MapInfo 11.5 and 12
' * Include mapbasic.def - required for various MapBasic commands including "CMD_INFO_XXX"
Include "mapbasic.def"
' * OK button handler for Dialog
Declare Sub gmeu_goToGridReference ( gmeu_userEnteredGridRef As String )
Sub gmeu_goToGridReference ( gmeu_userEnteredGridRef As String )
Dialog Preserve
Print "You entered: " + gmeu_userEnteredGridRef
End Sub
Declare Sub Main
Sub Main
' * Create a custom dialog box to obtain the grid reference from the user
Dim gmeu_userEnteredGridRef As String
Dialog
Title "Go to Grid Reference"
Control StaticText
Title "Enter a grid reference:"
Control EditText
Into gmeu_userEnteredGridRef
Control OKButton
Control CancelButton
If CommandInfo( CMD_INFO_DLG_OK ) Then
Call gmeu_goToGridReference( gmeu_userEnteredGridRef )
End If
End Sub
I've tried moving the position of the declare statements from the top to just before the Subs are coded but this has not changed the result - I didn't think it would but wanted to be thorough.
3 Answers 3
What you are describing (The Calling clause) is not a work-around; it is the documented way that MapBasic custom dialogs work. See the documentation for the Dialog Preserve statement, under "Restrictions".
As far as sharing the string with the "Calling" sub, instead of using a Global, use the ReadControlValue function to examine the current value of the text box. I don't think the MB dialog will assign the text to the string variable until the dialog is truly dismissed, in which case a Global would not work.
- Dave Smith (I am a Pitney Bowes employee)
-
Thanks Dave. I've reverted to using the ReadControlValue function instead. It does exactly what I needPaul Barrington– Paul Barrington2016年08月09日 13:25:19 +00:00Commented Aug 9, 2016 at 13:25
The problem is that when you call CommandInfo(CMD_INFO_DLG_OK)
the dialog box is dismissed (as this signals that the user has clicked ok), hence the error message you were getting. The call to CommandInfo(CMD_INFO_DLG_OK)
also triggers the values from your controls to be written to any variables you've assigned (e.g. in your case Into gmeu_userEnteredGridRef
) - if you don't call CommandInfo(CMD_INFO_DLG_OK)
then the value will never get assigned to the variable.
It looks like you want your dialog to be modeless (able to stay open and not lock the main application window while it is open). Unfortunately a pure MapBasic application only supports modal dialog boxes. If you want your dialog to be modeless your best bet is to use a custom .NET dialog box compiled into a dll and called from your MapBasic application. You might find some of the information here helpful with regards to achieving that.
-
Thanks T_Bacon. Unfortunately for me you are correct. I was hoping to write a solution in pure MapBasic but I now know this is not possible.Paul Barrington– Paul Barrington2016年07月19日 16:37:54 +00:00Commented Jul 19, 2016 at 16:37
-
@T_Bacon, you are almost correct. However, it's not the CommandInfo(CMD_INFO_DLG_OK) that dismisses the dialog. It's the user when closing the dialog via the OKButton, CancelButton or the cross in the upper right corner. The Dialog Preserve can only be used within a handler of a control on the dialog. It's often used when validating the users entry in the handler of the OKButton. If you come across an issue, you can use the Dialog Preserve statement to "recreate" the dialog as it was when the user clicked the OKButton. But you are right, modeless dialogs can't be created with MapBasic only.Peter Horsbøll Møller– Peter Horsbøll Møller2016年08月02日 09:23:32 +00:00Commented Aug 2, 2016 at 9:23
I have figured out a workaround. Instead of calling Sub gmeu_goToGridReference via
If CommandInfo( CMD_INFO_DLG_OK )
I am instead using the 'Calling' command directly below the OKButton control as follows
Dialog
Title "Go to Grid Reference"
Control StaticText
Title "Enter a grid reference:"
Control EditText
Into gmeu_userEnteredGridRef
Control OKButton
Calling gmeu_goToGridReference
Control CancelButton
The disadvantage is that I can't pass a variable to a Sub called in this way. So for the time being I have made gmeu_userEnteredGridRef Global. For the avoidance of doubt the full working source code is as follows...
' Simple script to isolate and test the Dialog Preserve command
' * Include mapbasic.def - required for various MapBasic commands including "CMD_INFO_XXX"
Include "mapbasic.def"
Declare Sub Main
Declare Sub gmeu_goToGridReference
Global gmeu_userEnteredGridRef As String
Sub Main
' * Create a custom dialog box to obtain the grid reference from the user
Dialog
Title "Go to Grid Reference"
Control StaticText
Title "Enter a grid reference:"
Control EditText
Into gmeu_userEnteredGridRef
Control OKButton
Calling gmeu_goToGridReference
Control CancelButton
End Sub
' * OK button handler for Dialog
Sub gmeu_goToGridReference
Dialog Preserve
Note "You entered: " + gmeu_userEnteredGridRef
End Sub