2 Concepts
dxtr edited this page 2026-10-18 16:25:37 +02:00

Concepts

Handles

Windows names what it makes with handles: a window is an HWND, the running program an HINSTANCE, an event object a HANDLE. cl-win32 gives them all as integers, of the type handle. 0 is no handle, so a function that takes a window, an event or a cursor refuses it with a type-error. Integers are plain Lisp values: they compare with =, go into hash tables, and passing them to Windows allocates nothing.

window-p tells whether an integer is a window that exists.

Window classes and window procedures

Every window has a window class, a name registered with register-window-class. The class names the window's window procedure: the function Windows calls with each message for the window.

A message is an integer, such as +wm-size+, with two integer parameters, wparam and lparam, whose meaning depends on the message. For +wm-size+, wparam says whether the window is minimised and lparam's two 16-bit halves are the new width and height. The constants' docstrings say what each message's parameters are.

A window procedure returns the message's result, an integer, or nil. nil leaves the message to Windows' default handling, default-window-procedure, which does what an ordinary window does: draws the frame, moves and sizes the window when the user drags it, and so on. Most messages should go there.

See Window Procedures and Classes.

Windows belong to threads

A window belongs to the thread that created it, for its whole life:

  • Its messages go to that thread's message queue, and only that thread can take them, with run-message-loop or process-messages.
  • Only that thread may destroy it.
  • Its window procedure runs on that thread, whoever sends it a message.

So a thread that creates windows must also run their message loop, and keep running it: a window whose thread does not take its messages stops responding, and Windows marks it "Not responding" after a few seconds.

Other threads may still use the window: move it, set its title, post and send it messages. Windows passes the work to the window's thread where it must.

Posted and sent messages

There are two ways to give a window a message:

  • Posting, with post-message, puts the message on the queue of the window's thread and returns at once. The message loop takes it later. Input from the user, such as keys and the pointer, arrives this way.
  • Sending, with send-message, calls the window procedure and returns its result. From the window's own thread, that is a plain function call. From another thread, Windows hands the message to the window's thread and waits; that thread takes it while it waits for messages, in run-message-loop.

Many of Windows' own calls send messages. create-window sends +wm-nccreate+ and +wm-create+ before it returns, destroy-window sends +wm-destroy+, and set-window-bounds sends +wm-size+.

See Messages and Message Loops.

Errors in window procedures

Windows calls a window procedure from inside its own code. An error must not unwind through that code, so cl-win32 catches it in the procedure, gives the message its default handling, and signals the error again once Windows has returned: from the cl-win32 function during which Windows called the procedure. See Errors.

Pixels and DPI

With per-monitor DPI awareness, which set-thread-dpi-awareness turns on for a thread, Windows gives sizes and positions in pixels, and tells each window the DPI of the display it is on: 96 at 100%, 144 at 150%. A program that draws at the same physical size everywhere scales by the DPI over 96. See DPI.