The CAPI provides a number of built-in dialogs which should cover the majority of most programmers' needs. However, there is always the occasional need to create custom built dialogs, and the CAPI makes this very simple, using the function popup-confirmer which displays any CAPI interface as a dialog, and the functions exit-confirmer to return from such a dialog.
The function popup-confirmer is a higher level function provided to add the standard buttons to dialogs. In order to create a dialog using
popup-confirmer, all you need to do is to supply a pane to be placed inside the dialog along with the buttons and the title. The function also expects a title, like all of the prompter functions described earlier.
Since interfaces and layouts are panes too, the pane argument to popup-confirmer can be a layout or an interface, and often it is. Layouts are used for simple combinations of panes, and interfaces are used for complex dialogs. All the dialogs in the LispWorks IDE which are not either native, just a message or asking for a single item of input are interfaces displayed by popup-confirmer. As an example, you can load the Othello example file:
An interface intended for display by popup-confirmer can also be displayed by display (not at the same time), in which case it is just another window. That is especially useful during development of your dialog code, because you can then work on the callbacks while the interface is displayed.
A common thing to want to do with a dialog is to get the return value from some state in the pane specified. For instance, in order to create a dialog that prompts for an integer the string entered into the text-input-pane would need to be converted into an integer. It is possible to do this once the dialog has returned, but popup-confirmer has a more convenient mechanism. The function provides a keyword argument,
:value-function, which gets passed the pane, and this function should return the value to return from the dialog. It can also indicate that the dialog cannot return by returning a second value which is non-nil.
You now have enough information to write a primitive version of
Note that the dialog's
button never becomes activated, yet pressing
Return once you have entered a valid integer
return the correct value. This is because the
button is not being dynamically updated on each keystroke in the text-input-pane so that it activates when the pane contains a valid integer. The activation of the
button is recalculated by the function redisplay-interface, and the CAPI provides a standard callback,
:redisplay-interface, which calls this as appropriate.
Thus, to have an
button that becomes activated and deactivated dynamically, you need to specify the
for the text-input-pane to be
Note that the OK button now changes dynamically so that it is only ever active when the text in the text-input-pane is a valid integer.
Note that the
Escape key activates the
button - this too was set up by popup-confirmer.
The next thing that you might want to do with your integer prompter is to make it accept only certain values. For instance, you may only want to accept negative numbers. This can be specified to popup-confirmer by providing a validation function with the keyword argument
:ok-check. This function receives the potential return value (the value returned by the value function) and it must return non-nil if that value is valid. Thus to accept only negative numbers we could pass
minusp as the
popup-confirmer creates an interface (of an internal class) around the pane that you give it which displays the pane and the buttons it adds, and then calls
display-dialog to actually display it. If you have an interface and do not want any of the buttons, you can call display-dialog directly.
display-dialog takes an interface (unlike popup-confirmer, which can take any pane) and displays it as a dialog. The keyword arguments can be used to control the exact behavior. You can use exit-dialog and abort-dialog to dismiss the dialog programmatically.
By default popup-confirmer and display-dialog create modal dialog windows which prevent input to other application windows until they are dismissed by the user clicking on a button or another appropriate gesture. You can change this behavior by passing the modal keyword argument.
The function current-popup can be used to find the current popup pane, if there is any, and is useful inside callbacks.
The function current-dialog-handle returns the "handle" of the dialog in the underlying GUI system, which may be useful in some circumstances.
CAPI User Guide and Reference Manual (Windows version) - 3 Aug 2017