In the previous section, you learned how an application can provide custom thumbnails and
custom live previews to make these user-interface features more useful and productive.
However, we focused on top-level Windows 7 only; these are the Windows 7 recognized by the
DWM. Some other Windows 7, such as child Windows 7 in an MDI or TDI application, are not toplevel
Windows 7 and nonetheless require separate window thumbnails for each document or
tab. The ability to create thumbnails and live previews for child Windows 7 (or tabs) is the
subject of this section.
Internet Explorer 8 is a TDI application that takes advantage of this customization
functionality. Although it has only one top-level window, when the user opens multiple tabs
multiple thumbnails are spawned from the taskbar button. Hovering over each produces a live
preview of the individual tab within the Internet Explorer frame, as shown in the following
screen shot:

This is clearly more user-friendly than allowing the DWM to exercise its default behavior and
provide a single thumbnail of the Internet Explorer window with all tabs visible in one thumbnail.
Some other tabbed Web browsers have not yet adapted to the Windows 7 7 taskbar environment
and offer an inferior visual experience in this area.
To provide thumbnails and live previews for child Windows 7, extra work is required to
circumvent the following DWM limitation: the current version of the DWM is incapable of
communicating with non-top-level Windows 7. This means that for each child window, a proxy
top-level window must be created this proxy receives DWM window messages on the child
window’s behalf so that an appropriate thumbnail and live preview can be rendered. Here is
the process for doing so using the native DWM interfaces:
In the WM_CREATE message handler, the window procedure of the child window creates
a proxy window (usually an invisible top-level window with a 1-by-1 size) and passes the
handle to the proxy window to the ITaskbarList3::RegisterTab function. The main window
handle also needs to be passed as the second parameter so that the taskbar knows where
to group the new tab. Next, the ITaskbarList3::SetTabOrder function is called to let the
taskbar know where the tab belongs in the thumbnail group. (Passing NULL for the last
hwndInsertBefore parameter places it at the end of the list.)
The application then repeats the steps from the previous sections (Custom Thumbnails
and Custom Live Previews) to let the DWM know that it’s interested in customizing the thumbnail and live preview for the proxy window. Note that the handle to the top-level
proxy window must be passed to the relevant APIs because the DWM will not
communicate with non-top-level Windows 7.
In the WM_DWMSENDICONICTHUMBNAIL and
WM_DWMSENDICONLIVEPREVIEWBITMAP message handlers of the proxy window
procedure, render the thumbnail or live preview, respectively, of the child window that
corresponds to this proxy window, and then pass it to the DWM using the
DwmSetIconicThumbnail and DwmSetIconicLivePreviewBitmap APIs, as described in the
previous section.
In the WM_ACTIVATE message handler of the proxy window procedure, activate the child
window within the context of the application. In the case of a Web browser tab, this
means switching to the tab making it active and visible. (Remember to ensure that the
wParam parameter of the window message is WA_ACTIVE or WA_CLICKACTIVE.)
In the WM_CLOSE message handler of the proxy window procedure, close the child
window within the context of the application and call the ITaskbarList3::UnregisterTab
function with the proxy window as a parameter to let the taskbar know that the proxy
window is no longer relevant. At this time, the proxy window itself can also be destroyed.
The following code shows a skeletal implementation of a proxy window that can be used to
delegate DWM thumbnail and live preview requests as described earlier:
ITaskbarList3* pTaskbar; //Initialized elsewhere
HWND hMainWnd;
//Child window procedure:
if (msg == WM_CREATE) {
HWND hPrx = CreateWindow(...);
pTaskbar->RegisterTab(hPrx, hMainWnd);
pTaskbar->SetTabOrder(hPrx, NULL);
BOOL truth = TRUE;
DwmSetWindowAttribute(hPrx, DWMWA_HAS_ICONIC_BITMAP, &truth, sizeof(truth));
DwmSetWindowAttribute(hPrx, DWMWA_FORCE_ICONIC_REPRESENTATION, &truth, sizeof(truth));
}
HWND hChildWnd;
//Proxy window procedure:
if (msg == WM_DWMSENDICONICTHUMBNAIL) {
HBITMAP hbmp = GrabThumbnailOf(hChildWnd);
DwmSetIconicThumbnail(hwnd, hbmp, 0);
}
if (msg == WM_DWMSENDICONICLIVEPREVIEWBITMAP) {
HBITMAP hbmp = GrabScreenShotOf(hChildWnd);
DwmSetIconicLivePreviewBitmap(hwnd, hbmp, NULL, 0);
}
if (msg == WM_ACTIVATE && (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE)) {
ActivateTheChildWindow(hChildWnd);
}
if (msg == WM_CLOSE) {
CloseTheChildWindow(hChildWnd);
DestroyWindow(hProxyWnd);
}
This difficult process is significantly simplified in the managed equivalent, the already-familiar
TaskbarManager.Instance.TabbedThumbnail property from the Windows 7 API Code Pack. (We
used this property in the previous sections.) This time, when creating the
TabbedThumbnailPreview instance, pass the main (parent) window handle as the first
parameter and the child window handle as the second parameter. The underlying library code
automatically creates a proxy window for you, so you can continue using the SetImage
method to provide a preview when necessary, or you can let the library attempt to generate a
thumbnail and live preview for you.
Note In this case, relying on the default behavior, which automatically generates a screen shot of
the child window, is even riskier than before it’s not always possible to render a screen shot of
any child window. For example, a tab page in a tab control that is not currently visible does not
draw so there is no way of obtaining its screen shot without intimate familiarity with its rendering
code. In fact, it might be the case that the child window is not even rendered before it is made
visible!
The Windows 7 Training Kit for Developers contains an excellent example of window switchers
in native code. Specifically, it has the infrastructure for setting up a thumbnail preview and live
preview for tab pages in a standard Win32 tab control. This infrastructure can be easily reused
in your applications. |