Changes to a window can be tracked by a device driver through a WNDOBJ. A WNDOBJ is a driver level window object that contains information about the position, size, and the visible client region of a window. That is, by creating a WNDOBJ corresponding to an application's window, the driver can track the size, position, and client region changes in that window.
An application uses the Win32 API to access the WNDOBJ_SETUP functionality implemented by the device driver. Access is gained through the Win32 ExtEscape function. GDI passes this escape call to the device driver with DrvEscape, implemented by the device driver with WNDOBJ_SETUP for the value of iEsc.
An application calls ExtEscape(hdc, WNDOBJ_SETUP,...) and passes a handle to the application-created window (created by means of CreateWindow or some equivalent Win32 function) via the input buffer to the driver. If the driver is to keep track of the window, it calls EngCreateWnd, within the context of the ExtEscape call, to create a WNDOBJ structure for the given window. From that point on, any changes to that window will pass down to the driver.
The driver should handle the ExtEscape call in a manner similar to the following.
ULONG DrvEscape(
SURFOBJ *pso,
ULONG iEsc,
ULONG cjIn,
PVOID pvIn,
ULONG cjOut,
PVOID pvOut)
{
WNDOBJ *pwo;
WNDDATA *pwd;
if (iEsc == WNDOBJ_SETUP)
{
pwo = EngCreateWnd(pso,*((HWND *)pvIn),&DrvVideo,
WO_RGN_CLIENT, 0);
// Allocate space for caching client rects. Remember the pointer
// in the pvConsumer field.
pwd = EngAllocMem(0, sizeof(WNDDATA), DRIVER_TAG);
WNDOBJ_vSetConsumer(pwo,pwd);
// Update the rectangle list for this wndobj.
vUpdateRects(pwo);
return(1);
}
}
Since creating a window object involves locking special window resources, EngCreateWnd should be called only in the context of the WNDOBJ_SETUP escape in DrvEscape or DrvSetPixelFormat.
The EngCreateWnd function supports window tracking by multiple drivers. Through EngCreateWnd, each driver identifies its own callback routine that GDI is to call for changes to the corresponding window. This feature allows, for example, a live video driver to track changes to live video windows while an OpenGL driver is tracking changes to OpenGL windows.
GDI will call back to the driver with the most recent window states if a new WNDOBJ is created in DrvSetPixelFormat or ExtEscape. GDI will also callback to the driver when a window referenced by a WNDOBJ is destroyed.
As an accelerator, the driver may access public fields of the WNDOBJ, defined as follows.
typedef struct {
CLIPOBJ coClient;
PVOID pvConsumer;
RECTL rclClient;
} WNDOBJ;
where coClient is a CLIPOBJ which describes the region of the window, pvConsumer is a driver-defined value for identifying this particular WNDOBJ, and rclClient is a lower-right exclusive rectangle of the client area of the window in screen coordinates.
Note These public fields are guaranteed to remain unchanged only in the context of the driver callback routine supplied to GDI in the EngCreateWnd function call or the DDI functions where a WNDOBJ is given.
Tracking window changes involves the use of three callback functions provided to support the WNDOBJ. The visible client region may be enumerated by calling the WNDOBJ_cEnumStart and WNDOBJ_bEnum callback functions. A driver may associate its own data with a WNDOBJ by calling the WNDOBJ_vSetConsumer callback function.