289 lines
8.1 KiB
C
289 lines
8.1 KiB
C
/*****************************************************************************
|
|
*
|
|
* Obscure.c
|
|
*
|
|
* Copyright (c) 1997 Microsoft Corporation.
|
|
*
|
|
* Abstract:
|
|
*
|
|
* Sample program to demonstrate how a program can detect
|
|
* whether its client area is totally obscured.
|
|
*
|
|
* A program may wish to do this in order to suppress
|
|
* computationally expensive graphics operations when
|
|
* there is no way for the user to see the output.
|
|
*
|
|
* Details:
|
|
*
|
|
* This program displays the time in its client area.
|
|
* When the client area is completely obscured, there is no
|
|
* point in drawing the time (since the user can't see it),
|
|
* so the application goes to sleep until the client area
|
|
* is again visible.
|
|
*
|
|
* To see this program in action, run this application and
|
|
* Notepad simultaneously. Drag the Notepad window so that
|
|
* it covers this sample program. Observe that the title
|
|
* changes to "Covered". Move the Notepad window away, and
|
|
* observe that the title changes to "Uncovered" or "Partially
|
|
* Covered", as appropriate.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define STRICT
|
|
#include <windows.h>
|
|
#include <strsafe.h>
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Overview
|
|
*
|
|
* To determine whether the client area is obscured, determine
|
|
* whether it has an empty clip region.
|
|
*
|
|
* To be notified when the client area is again unobscured,
|
|
* invalidate the entire client rectangle and wait for
|
|
* Windows to send a WM_PAINT message. (Explicit invalidation
|
|
* is required, for if you were obscured by a menu or a window
|
|
* with the CS_SAVEBITS class style, Windows will restore your
|
|
* client area automatically instead of sending a WM_PAINT message.)
|
|
*
|
|
* So that you can see the behavior of the application, we will
|
|
* put information in the title of the window. Watch the taskbar
|
|
* to see the application change its state.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL g_fTimerActive = FALSE;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* GetClientObscuredness
|
|
*
|
|
* Returns one of the OBS_* values.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define OBS_COMPLETELYCOVERED 0
|
|
#define OBS_PARTIALLYVISIBLE 1
|
|
#define OBS_COMPLETELYVISIBLE 2
|
|
|
|
int
|
|
GetClientObscuredness(HWND hwnd)
|
|
{
|
|
HDC hdc;
|
|
RECT rc, rcClient;
|
|
int iType;
|
|
|
|
hdc = GetDC(hwnd);
|
|
iType = GetClipBox(hdc, &rc);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
if (iType == NULLREGION)
|
|
return OBS_COMPLETELYCOVERED;
|
|
if (iType == COMPLEXREGION)
|
|
return OBS_PARTIALLYVISIBLE;
|
|
|
|
GetClientRect(hwnd, &rcClient);
|
|
if (EqualRect(&rc, &rcClient))
|
|
return OBS_COMPLETELYVISIBLE;
|
|
|
|
return OBS_PARTIALLYVISIBLE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Obscure_EnsureTimerStopped
|
|
*
|
|
* If the timer that causes us to do work is running, then stop it.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void
|
|
Obscure_EnsureTimerStopped(HWND hwnd)
|
|
{
|
|
if (g_fTimerActive) {
|
|
KillTimer(hwnd, 1);
|
|
g_fTimerActive = FALSE;
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
SetWindowText(hwnd, TEXT("Covered (Paused)"));
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Obscure_TimerProc
|
|
*
|
|
* If we have become obscured, then stop the timer.
|
|
*
|
|
* Otherwise, invalidate our rectangle so we will redraw with
|
|
* the new time.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void CALLBACK
|
|
Obscure_TimerProc(HWND hwnd, UINT uiMsg, UINT_PTR idTimer, DWORD tm)
|
|
{
|
|
/*
|
|
* If the client area is totally obscured, then stop the timer
|
|
* so we don't waste any more CPU.
|
|
*/
|
|
int iState = GetClientObscuredness(hwnd);
|
|
if (iState == OBS_COMPLETELYCOVERED) {
|
|
Obscure_EnsureTimerStopped(hwnd);
|
|
} else {
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
if (iState == OBS_PARTIALLYVISIBLE) {
|
|
SetWindowText(hwnd, TEXT("Partially Visible"));
|
|
} else if (iState == OBS_COMPLETELYVISIBLE) {
|
|
SetWindowText(hwnd, TEXT("Completely Visible"));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Obscure_EnsureTimerRunning
|
|
*
|
|
* If the timer that causes us to do work is not running, then start it.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void
|
|
Obscure_EnsureTimerRunning(HWND hwnd)
|
|
{
|
|
if (!g_fTimerActive) {
|
|
SetTimer(hwnd, 1, 100, Obscure_TimerProc);
|
|
g_fTimerActive = TRUE;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Obscure_OnPaint
|
|
*
|
|
* Draw the current time and restart the timer if needed.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void
|
|
Obscure_OnPaint(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
if (hdc) {
|
|
TCHAR sz[64];
|
|
RECT rc;
|
|
HFONT hfOld;
|
|
COLORREF crTextOld, crBkOld;
|
|
int cch;
|
|
|
|
if (IsRectEmpty(&ps.rcPaint)) {
|
|
/*
|
|
* Nothing to do. Don't wake up either.
|
|
*/
|
|
} else {
|
|
hfOld = SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
|
|
crTextOld = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
|
crBkOld = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
cch = StringCchPrintf(sz, 64, TEXT("%u"), GetTickCount());
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, sz, cch, NULL);
|
|
|
|
SetBkColor(hdc, crBkOld);
|
|
SetTextColor(hdc, crTextOld);
|
|
SelectObject(hdc, hfOld);
|
|
|
|
Obscure_EnsureTimerRunning(hwnd);
|
|
}
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Obscure_WndProc
|
|
*
|
|
* Window procedure for obscured window demo.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
LRESULT CALLBACK
|
|
Obscure_WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uiMsg) {
|
|
|
|
case WM_CREATE:
|
|
Obscure_EnsureTimerRunning(hwnd);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
Obscure_OnPaint(hwnd);
|
|
break;
|
|
|
|
/*
|
|
* The app exits when this window is destroyed.
|
|
*/
|
|
case WM_DESTROY:
|
|
Obscure_EnsureTimerStopped(hwnd);
|
|
PostQuitMessage(0);
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* WinMain
|
|
*
|
|
* Program entry point.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
int WINAPI
|
|
WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine, int nCmdShow)
|
|
{
|
|
WNDCLASS wc;
|
|
MSG msg;
|
|
HWND hwnd;
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = Obscure_WndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hinst;
|
|
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = TEXT("Obscure");
|
|
|
|
RegisterClass(&wc);
|
|
|
|
hwnd = CreateWindow(
|
|
TEXT("Obscure"), /* Class Name */
|
|
TEXT("Obscure"), /* Title */
|
|
WS_OVERLAPPEDWINDOW, /* Style */
|
|
CW_USEDEFAULT, CW_USEDEFAULT, /* Position */
|
|
CW_USEDEFAULT, CW_USEDEFAULT, /* Size */
|
|
NULL, /* Parent */
|
|
NULL, /* Use class menu */
|
|
hinst, /* Instance */
|
|
0); /* No special parameters */
|
|
|
|
ShowWindow(hwnd, nCmdShow);
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return 0;
|
|
}
|