### 4.4. Common Graphics and the Integrated Development Environment [Windows only]

> Q 4.4-1) How do I not save prefs.cl when I exit the ide?
> Q 4.4-2) Sometimes when I run my project, I get mysterious redefinition warnings. Why and should I worry about them?
> Q 4.4-3) I have developed my application in the IDE, and when I test it there it runs fine. But when I try to run the application as generated by File | Build Project Distribution, it starts and the application window appears, but it then immediately exits.

Go to main FAQ page.

Q 4.4-1) How do I not save prefs.cl when I exit the ide?

A 4.4-1) The idea of writing prefs.cl each time is to "remember" where you last placed your windows (as well as other settings) so that they will be "where you left them" the next time you start up.

If you do not want this behavior, as soon as you start up, toggle Tools | Save Options on Exit to off (unchecked). Then click Tools | Save Options Now. That will write a prefs.cl file with saving prefs.cl on exit disabled (meaning you do not have to toggle it off the next time you use the IDE).

If you remove (or rename) the prefs.cl file, the IDE will start in the default configuration.

Q 4.4-2) Sometimes when I run my project, I get mysterious redefinition warnings. Why and should I worry about them?

A 4.4-2) The warning likely looks like this:

    Warning: FORM1-BUTTON4-ON-CHANGE, :OPERATOR was defined in
    EDITOR 1.unsaved and is now being defined in C:\Program Files\acl501\form1.cl

This warning occurred after placing a button on a form, displaying the Events tab of the Inspector for the button, and clicking on the extended editor button for the on-change event handler. (There is nothing special about buttons. The same behavior would be seen with any control with event handlers.) That generated code for the function FORM1-BUTTON4-ON-CHANGE, which you see in the form1 editor buffer. However, for system reasons it is first stored in a hidden buffer and evaluated (to ensure that the function is defined). When the definition is later read from the form1 buffer, a redefinition warning is signaled.

This is a minor design flaw. You will not get the warning if you display the form1 editor buffer before clicking on the on-change extended editor button. You do this by displaying the Project Manager, View | Project Manager, selecting form1 in the pane, and clicking on the View Selected Code button. Those actions cause a form1 buffer to be displayed in the Editor Workbook, making storing and evaluating the FORM1-BUTTON4-ON-CHANGE code in a hidden buffer unnecessary.

Q 4.4-3) I have developed my application in the IDE, and when I test it there it runs fine. But when I try to run the application as generated by File | Build Project Distribution, it starts and the application window appears, but it then immediately exits.

A 4.4-3) Since the question is asked, we assume that exiting immediately is not what is intended. There are programs that run in batch mode and exit when they are done, with no indication to users. However, other programs display windows and the windows stick around until the user explicitly exits the program. The question above typically arises in these cases. It runs fine when tested with Run | Run Project in the IDE but the application created by File | Build Project Distribution starts up and immediately exits without user action of any sort.

The most likely cause of such behavior is that your project initialization function is not returning your application window, but is instead returning something that is either not a window or is a temporary window. The project initialization function is the value of the on-initialization event handler for your project. It appears in the Init Function field of the Options Tab of the Project manager dialog (displayed with View | Project Manager).

A project application is generated with the menu commands File | Build Project Exe (which produces a .exe file and a .dxl file) or File | Build Project Distribution (which also produces an exe and a dxl file, and puts them along with other files in a directory).

When the application starts up, at the end of the startup procedure, it calls cg::do-default-restart (which is the value of excl:*restart-init-function*). The source for that function looks like:

    (defun do-default-restart (&key (console-state SW_HIDE))
      (initialize-session)
      ;; use SW_NORMAL to expose
      (ShowWindow (console-hwnd (app *system*)) console-state)
      (let ((main-window (do-initialization)))
        (event-loop main-window)))

It calls (do-initialization), which is the project initialization function, takes the return value and passes it to event-loop, whose source looks like:

    (defun event-loop (&optional main-window)
      (unless qmsg (setq qmsg (callocate msg)))
        (do ()
            ((or (not (streamp main-window))
                 (closed-stream-p main-window))
             (exit 0))
          (process-single-event nil)))

event-loop is supposed to be looping until main-window, its argument, is closed (assuming main-window is a stream of some sort). main-window, again, is the value returned by the project initialization function. If that return value is not a window, then the event-loop falls through immediately and exit is called.

You can fix the problem by having your project initialization function return your main window. The main window, recall, is the window which an application user closes when they want to exit the application.

The default-init-function, which is the initial project initialization function, creates and returns the window associated with the project main form. While it suffices for many applications, many application developers write their own project initialization function because they want more than one window created, or a preliminary window (to verify a license or to set configuration options) to appear prior to the main window, or to perform other initializations not conveniently done elsewhere. If this function returns, it must return the main window after doing whatever else it does.

Note that running a project within the IDE does call the project initialization function but does not embed it in an event loop as detailed above (the standard IDE event loop is used instead). Therefore, the exiting behavior of an application will not be seen when testing a project application within the IDE.

Note we said "if this function [the project init function] returns, it must ..." above. The init function does not have to return or it can (more or less equivalently) return nil when complete since returning nil causes the application to exit. Instead, it can run its own event loop and handle exiting entirely on its own. Thus, here is an outline of a project init function that does not return until the main application window is closed, at which point it returns nil.To make this work, of course, things surrounded by angle brackets (< and >) or brackets ([ and ]) must be replaced by actual Lisp code doing what is indicated:

    (defun my-init-function ()
      <initialize things here>
      (let* ((my-main-window [find my main window]))
        (loop ;; keep going after handling an error
          (handler-case
            (loop (process-single-event)
              (when (closed-stream-p my-main-window)
                (return-from my-init-function nil)))
            (error (condition)
              <Handle the error some way here>)))))

Next FAQ topic: 4.5. Runtime

Previous FAQ topic: 4.3. CLIM

© Copyright 1999, 2002, 2004, Franz Inc., Berkeley, CA. All rights reserved.
$Revision: 1.1.1.1 $