Generic FunctionPackage: cgToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version


Arguments: dialog &key stream initial-focus bring-thread-to-front

Exposes and selects a dialog in a modal way, where the user must interact with and exit that dialog before proceeding with anything else.

Specifically, the modal dialog will be displayed indefinitely until some user action causes the call to pop-up-modal-dialog to return.

While the modal dialog is present, all mouse events are disabled on stream as well as on all of the child and owned windows of stream (except for the modal dialog itself). And no windows are disabled if stream is the screen, or if the value of *modal-dialogs-disable-owner* is nil. This is done to force the user to complete a response to the modal dialog before continuing to interact with the rest of the application. The dialog can be said to be "modal with respect to stream ". Typically stream should be a top-level window, to establish modality with respect to its whole window hierarchy. stream can be the screen, which is the value returned by (screen *system*). See screen and *system*. stream defaults to the uppermost parent of the modal dialog, as returned by calling top-level-window on the dialog.

If an application includes multiple top-level windows and it is unsatisfactory for modal dialogs to be modal with respect to only one of the top-level windows, then an invisible window can be added to the application that serves as the owner of all of the top-level windows, and that invisible owner window can be passed as the stream argument to pop-up-modal-dialog to achieve modality with respect to the entire set of the top-level windows. To make an invisible window, simply call make-window, passing :state :shrunk as one of the initargs. To create a top-level owned window on the invisible window, call make-window again, passing the invisible window as the :owner initarg and passing the :child-p initarg as nil (which makes an owned window rather than a child window).

initial-focus may be one of the controls on the dialog, in which case that control will have the keyboard focus when the dialog appears. (This parameter exists because it does not work to call set-focus on the control before the dialog is exposed, and it is too late to call set-focus once pop-up-modal-dialog has been called to expose the dialog.) The value of this argument may be the widget object or the widget name. See the example below where the name is used.

If bring-thread-to-front is true, then set-foreground-window is called on the dialog to bring its application to the front if it was not in front already. This may be useful for a particularly important modal dialog to ensure that the user sees it. This call to set-foreground-window is always done if the owner of the dialog is the screen.

A call to pop-up-modal-dialog will return only in these cases:

pop-up-modal-dialog should be called only in the process that created the dialog. If called in another process, an error is signaled. If a dialog needs to be used in multiple processes, then a separate instance should be created for each process. The Common Graphics utility dialogs that are invoked by such functions as ask-user-for-choice-from-list automatically create a separate instance for each process in which they are used. The reason for this restriction is that each process maintains an indpenedent stack of currently-invoked modal windows, and so the process that is waiting in a call to pop-up-modal-dialog needs to be the same as the creation-process that handles the events in the window.


Here is a simple example that creates a modal dialog and then displays it by calling pop-up-modal-dialog. This example sets the pop-up property, which coerces certain other properties to appropriate values for modal dialogs. It also uses the fact that its default-button and cancel-button have built-in on-change functions that will call flag-modal-completion with t and nil respectively -- that causes pop-up-modal-dialog to return true if and only if the user does not cancel the dialog.

The dialog is shown twice to illustrate the fact that dismissing a modal dialog simply hides it until further use, rather than closing it.

(let* ((margin 8)
       (spacing 6)
       (widget-height 24)
       (width 300)
       (inner-width (- width (* 2 margin)))
       (height (+ (* 2 margin)(* 3 widget-height)(* 2 spacing)))
       (button-top (- height margin widget-height))
       (button-width 60)
       (dialog (make-window :modal-dialog-test
                 :class 'dialog
                 :title "Enter Two Strings"
                 :pop-up t
                 :interior (make-box-relative 100 200 width height)
                  (make-instance 'editable-text
                    :name :string1
                    :value ""
                    :left margin :top margin
                    :width inner-width :height widget-height)
                  (make-instance 'editable-text
                    :name :string2
                    :value ""
                    :left margin :top (+ margin widget-height spacing)
                    :width inner-width :height widget-height)
                  (make-instance 'default-button
                    :name :ok
                    :title "~OK"
                    :left margin :top button-top
                    :width button-width :height widget-height)
                  (make-instance 'cancel-button
                    :name :cancel
                    :title "~Cancel"
                    :left (+ margin button-width spacing)
                    :top button-top
                    :width button-width :height widget-height))))
       first-answer second-answer)
  (when (pop-up-modal-dialog dialog :initial-focus :string1)
    (setq first-answer (list (dialog-field dialog :string1)
                             (dialog-field dialog :string2)))
    (setf (title dialog) "Enter Two MORE Strings")
    (set-dialog-fields dialog :string1 "" :string2 "")
    (when (pop-up-modal-dialog dialog :initial-focus :string1)
      (setq second-answer (list (dialog-field dialog :string1)
                                (dialog-field dialog :string2)))
      (list first-answer second-answer))))

Copyright (c) 1998-2022, Franz Inc. Lafayette, CA., USA. All rights reserved.
This page was not revised from the 10.0 page.
Created 2019.8.20.

Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version