MacroPackage: cgToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version


Arguments: (hdc-var window &optional non-client-p) &body body

A macro that ensures that window has a device-context while body is executed. While generic windows do have permanent device-contexts in common graphics, controls that are implemented by the operating system do not. If you need to draw on a window that might be a Windows control, then you probably need to wrap the drawing code inside a with-device-context call. If you want to draw on the screen, over any windows that are displayed, you need to wrap the drawing code in a with-device-context form as well. See the information under `Drawing on the screen' below.

If window does already have a device-context, then the hdc-var variable is bound to that existing device-context and the body is executed. If window has no device-context, then one is created for it and stored as the device-context property of the window while body is executed, then the device-context is removed from the window and destroyed, leaving the device-context of window as nil.

If non-client-p is true, then the hdc-var variable will be bound to a non-client device-context (for drawing on the frame of the window) rather than a client-area device-context as usual. Also, if the window has a device-context already, a fresh non-client device-context will always be used in place of the existing client-area device-context of the window, which will be returned to the window after the execution of body. So with-device-context is still needed for drawing on a generic window that already has a device context if the drawing is to be done on the frame (or border) of the window.

From the description of device-context:

Returns an integer that identifies the device-context of window if it has one, or nil otherwise. A device-context is a construct used in the Windows API to specify a set of parameters that are used when drawing on a window. A common graphics application does not normally need to deal with a window's device-context directly, but if you need to pass the window to a winapi function that calls for the window's device-context (or hDC), then you should pass the integer returned by this function for that argument. cg:handle returns the window's "handle".

Every non-control window in common graphics (and every lisp-widget window) is automatically assigned a device-context, which it keeps until it is closed. Controls supplied by the OS (all controls except lisp-widgets), on the other hand, are not automatically given device-contexts in lisp since it is normally only the OS rather than lisp that draws on the control. If you do want to draw directly on a non-lisp control, then you must give the window of the control a device-context while drawing on it. The easy way to do this is to wrap a call to with-device-context around the code that draws on the control.

Drawing on the screen

A with-device-context form is also needed in order to draw directly on the screen (over any windows that happen to be where the drawing is done). Any current drawing attributes such as line-width or font must also be set up within the same with-device-context form as the drawing that uses it. If drawing is attempted on the screen without setting up the device-context, an error dialog will appear noting that with-device-context needs to be used.

In the past, the screen was internally given a permanent device context as with regular windows, but the device context eventually became invalid at some unpredictable time.

The Common Graphics utility functions such as get-line and get-shape-box are often used to draw rubber-banding lines directly on the screen; these utilities set up the needed device context for the screen internally.

Example of drawing directly on the screen:

(let* ((screen (screen *system*)))
  (with-positions (pos1 pos2) ;; to avoid consing
    (with-device-context (hdc screen)
      (with-foreground-color (screen blue)
        (dotimes (j 11)
          (draw-line screen (nmake-position pos1 100 200)
                     (nmake-position pos2 (+ 100 (* j 10)) 300))))
      (with-foreground-color (screen dark-green)
        (dotimes (j 11)
          (draw-line screen (nmake-position pos1 200 300)
                     (nmake-position pos2 (+ 100 (* j 10)) 200)))))))

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

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