mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1165 lines
33 KiB
1165 lines
33 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: mrshadow.c - MrShadow application
|
|
*
|
|
* Copyright (c) 1992 Sanford Staab
|
|
*
|
|
\***************************************************************************/
|
|
#define NOGDICAPMASKS
|
|
#define NOATOM
|
|
#define NOCLIPBOARD
|
|
#define NOLOGERROR
|
|
#define NOMETAFILE
|
|
#define NOOEMRESOURCE
|
|
#define NOSCROLL
|
|
#define NOPROFILER
|
|
#define NODRIVERS
|
|
#define NOCOMM
|
|
#define NODBCS
|
|
#define NOSYSTEMPARAMSINFO
|
|
#define NOSCALABLEFONT
|
|
#include "mrshadow.h"
|
|
#include "itsybits.h"
|
|
|
|
#define RHITCIRCLE 4
|
|
#define RSHADOWCIRCLE 16
|
|
#define CXCOLORBAR 8
|
|
#define BACKCOLOR RGB(0, 255, 255)
|
|
#define GLINTSENSITIVITY 1
|
|
#define DBGSHOWRGN(hrgn)
|
|
//#define DBGSHOWRGN(hrgn) if (IsWindowVisible(hwndMrShadow)) { \
|
|
HRGN hrgnSave; \
|
|
HDC hdc; \
|
|
\
|
|
hrgnSave = CreateRectRgn(0, 0, 0, 0); \
|
|
CombineRgn(hrgnSave, hrgn, NULL, RGN_COPY); \
|
|
SetWindowRgn(hwndMrShadow, hrgnSave, TRUE); \
|
|
UpdateWindow(hwndMrShadow); \
|
|
MessageBeep(0); \
|
|
Sleep(1000); \
|
|
}
|
|
|
|
#ifndef HLOCAL
|
|
#define HLOCAL HANDLE
|
|
#endif /* HLOCAL */
|
|
|
|
#ifndef MAX_PATH
|
|
#define MAX_PATH 128
|
|
#endif
|
|
|
|
UINT wmRefreshMsg;
|
|
HINSTANCE hInst;
|
|
HKEY hKeyMrShadow = NULL;
|
|
HWND hwndMrShadow = NULL;
|
|
TCHAR pszTitle[] = TEXT("Mr Shadow");
|
|
TCHAR pszTitle2[] = TEXT("Invisible Mr Shadow");
|
|
int cxShift = 2;
|
|
int cyShift = 2;
|
|
RECT rcDesk;
|
|
HCURSOR hCurCross = NULL;
|
|
HCURSOR hCurArrow = NULL;
|
|
HCURSOR hCurUpDown = NULL;
|
|
BYTE bShadowColor = 0;
|
|
HRGN hrgnHMask = NULL;
|
|
HRGN hrgnVMask = NULL;
|
|
HRGN hrgnCheckers = NULL;
|
|
HRGN hrgnGlintMask = NULL;
|
|
BOOL fVMask = FALSE;
|
|
BOOL fHMask = FALSE;
|
|
BOOL fGlint = TRUE;
|
|
int cHwnds = 0;
|
|
|
|
typedef struct tagWINFO {
|
|
HWND hwnd;
|
|
RECT rc;
|
|
int Depth;
|
|
} WINFO, *PWINFO;
|
|
|
|
PWINFO paWinfo = NULL;
|
|
PWINFO paWinfoLast = NULL;
|
|
BOOL *aRegional = NULL;
|
|
|
|
|
|
VOID InitBigRegions()
|
|
{
|
|
HRGN hrgn1;
|
|
int cx, cy;
|
|
|
|
hrgn1 = CreateRectRgn(0, 0, 1, 1); // create working region.
|
|
|
|
hrgnVMask = CreateRectRgn(0, 0, 1, rcDesk.bottom);
|
|
for (cx = 2; cx < rcDesk.right; cx <<= 1) {
|
|
CombineRgn(hrgn1, hrgnVMask, NULL, RGN_COPY);
|
|
OffsetRgn(hrgn1, cx, 0);
|
|
CombineRgn(hrgnVMask, hrgnVMask, hrgn1, RGN_OR);
|
|
}
|
|
if (cx > rcDesk.right) {
|
|
cx >>= 1;
|
|
CombineRgn(hrgn1, hrgnVMask, NULL, RGN_COPY);
|
|
OffsetRgn(hrgn1, (rcDesk.right - cx + 1) & ~1, 0); // even offset!
|
|
CombineRgn(hrgnVMask, hrgnVMask, hrgn1, RGN_OR);
|
|
}
|
|
|
|
hrgnHMask = CreateRectRgn(0, 0, rcDesk.right, 1);
|
|
for (cy = 2; cy < rcDesk.bottom; cy <<= 1) {
|
|
CombineRgn(hrgn1, hrgnHMask, NULL, RGN_COPY);
|
|
OffsetRgn(hrgn1, 0, cy);
|
|
CombineRgn(hrgnHMask, hrgnHMask, hrgn1, RGN_OR);
|
|
}
|
|
if (cy > rcDesk.bottom) {
|
|
cy >>= 1;
|
|
CombineRgn(hrgn1, hrgnHMask, NULL, RGN_COPY);
|
|
OffsetRgn(hrgn1, 0, (rcDesk.bottom - cy + 1) & ~1); // even offset!
|
|
CombineRgn(hrgnHMask, hrgnHMask, hrgn1, RGN_OR);
|
|
}
|
|
|
|
DeleteObject(hrgn1);
|
|
}
|
|
|
|
|
|
|
|
HRGN CreateWindowRgn(
|
|
int i)
|
|
{
|
|
int iResult;
|
|
HRGN hrgn;
|
|
|
|
hrgn = CreateRectRgnIndirect(&paWinfo[i].rc);
|
|
iResult = GetWindowRgn(paWinfo[i].hwnd, hrgn);
|
|
if (iResult != NULLREGION && iResult != ERROR) {
|
|
OffsetRgn(hrgn, paWinfo[i].rc.left, paWinfo[i].rc.top);
|
|
if (fGlint) {
|
|
aRegional[i] = TRUE;
|
|
}
|
|
}
|
|
return(hrgn);
|
|
}
|
|
|
|
|
|
|
|
VOID CalculateRegion(
|
|
BOOL fForceRecalc)
|
|
{
|
|
HWND hwnd;
|
|
HRGN hrgnShadow, hrgn1, hrgn2, hrgn3;
|
|
RECT rc;
|
|
HRGN *aGlintHrgn = NULL;
|
|
PWINFO paWinfoNew;
|
|
int cHwndsAlloc, iHwnd, i, iCastTarget;
|
|
static int cLastHwnds = 10;
|
|
static int cHwndInfoLast = 0;
|
|
int Depth;
|
|
|
|
hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
|
|
cHwnds = 0;
|
|
cHwndsAlloc = cLastHwnds;
|
|
paWinfo = LocalAlloc(LPTR, sizeof(WINFO) * cHwndsAlloc);
|
|
if (paWinfo == NULL) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* This higher this number, the more the topmost window stands out.
|
|
*/
|
|
Depth = 2;
|
|
|
|
/*
|
|
* Count the top-level windows and store their rects, depths and hwnds.
|
|
*/
|
|
while (hwnd) {
|
|
/*
|
|
* Only do windows that are visible, not us, and intersect with
|
|
* the desktop.
|
|
*/
|
|
if (hwnd != hwndMrShadow
|
|
&& IsWindowVisible(hwnd)
|
|
&& !IsIconic(hwnd)
|
|
) {
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
IntersectRect(&rc, &rc, &rcDesk);
|
|
if (!IsRectEmpty(&rc)) {
|
|
/*
|
|
* Realloc array as needed.
|
|
*/
|
|
if (cHwnds >= cHwndsAlloc) {
|
|
cHwndsAlloc += 10;
|
|
paWinfoNew = LocalReAlloc(paWinfo, cHwndsAlloc * sizeof(WINFO), LMEM_MOVEABLE);
|
|
if (paWinfo == NULL) {
|
|
LocalFree(paWinfo);
|
|
return;
|
|
}
|
|
paWinfo = paWinfoNew;
|
|
}
|
|
/*
|
|
* store info
|
|
*/
|
|
paWinfo[cHwnds].hwnd = hwnd;
|
|
GetWindowRect(hwnd, &(paWinfo[cHwnds].rc));
|
|
paWinfo[cHwnds].Depth = Depth;
|
|
|
|
/*
|
|
* Calculate its depth - If all windows at the same depth do
|
|
* not intersect it, it gets the same depth. If any intersect,
|
|
* it goes one level lower.
|
|
*/
|
|
for (i = cHwnds - 1; i >= 0; i--) {
|
|
if (paWinfo[i].Depth != Depth)
|
|
break;
|
|
|
|
if (IntersectRect(&rc, &paWinfo[i].rc, &paWinfo[cHwnds].rc)) {
|
|
Depth++;
|
|
paWinfo[cHwnds].Depth = Depth;
|
|
break;
|
|
}
|
|
}
|
|
|
|
cHwnds++;
|
|
}
|
|
}
|
|
hwnd = GetWindow(hwnd, GW_HWNDNEXT);
|
|
}
|
|
|
|
/*
|
|
* LATER: recalculate depths so as to minimize the number of depths.
|
|
* Thus if one window happens to intersect a window below it, this
|
|
* doesn't mean that all windows above it need be at its level. This
|
|
* will prevent icon titles from forming two or more levels just
|
|
* because a couple of them overlapped.
|
|
*/
|
|
|
|
/*
|
|
* Add the desktop. Realloc array as needed to make room.
|
|
*/
|
|
if (cHwnds >= cHwndsAlloc) {
|
|
cHwndsAlloc += 1;
|
|
paWinfoNew = LocalReAlloc(paWinfo, cHwndsAlloc * sizeof(WINFO), LMEM_MOVEABLE);
|
|
if (paWinfoNew == NULL) {
|
|
LocalFree(paWinfo);
|
|
return;
|
|
}
|
|
paWinfo = paWinfoNew;
|
|
}
|
|
|
|
/*
|
|
* The last entry is for the desktop. (last is on the bottom)
|
|
*/
|
|
paWinfo[cHwnds].hwnd = GetDesktopWindow();
|
|
CopyRect(&paWinfo[cHwnds].rc, &rcDesk);
|
|
paWinfo[cHwnds].Depth = ++Depth;
|
|
cHwnds++;
|
|
|
|
/*
|
|
* Place the topmost window out a little further so it stands out.
|
|
*/
|
|
paWinfo[0].Depth = 0;
|
|
|
|
cLastHwnds = cHwnds; // addaptive allocations - COOL!
|
|
|
|
/*
|
|
* Now before we do costly region calculations, find out if we need to.
|
|
* if *paWinfoLast == *paWinfo, we are done! (The only case where this
|
|
* isn't true would be for dynamically changing regional windows. Rects
|
|
* don't change but regions do.)
|
|
*/
|
|
if (!fForceRecalc &&
|
|
paWinfoLast != NULL &&
|
|
cHwnds == cHwndInfoLast &&
|
|
!memcmp(paWinfo, paWinfoLast, cHwnds * sizeof(WINFO))) {
|
|
LocalFree(paWinfo);
|
|
return;
|
|
}
|
|
|
|
if (fGlint) {
|
|
/*
|
|
* Now reallocate the regional array. This tells us which windows
|
|
* are reginal and is used for glinting effects. (we don't glint
|
|
* regional windows because painting is too hard.) We put this into
|
|
* a separate array so the quick memcmp check above can be done.
|
|
*/
|
|
if (aRegional != NULL) {
|
|
LocalFree(aRegional);
|
|
}
|
|
aRegional = LocalAlloc(LPTR, cHwnds * sizeof(BOOL));
|
|
if (aRegional == NULL) {
|
|
LocalFree(paWinfo);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Reallocate the glint region array. The glint region array is used
|
|
* to build up the glint region layer by layer so that only shadows
|
|
* cast on that layer are removed from the glint region.
|
|
*/
|
|
if (aGlintHrgn == NULL) {
|
|
LocalFree(aGlintHrgn);
|
|
}
|
|
|
|
aGlintHrgn = LocalAlloc(LPTR, Depth * sizeof(HRGN));
|
|
if (aGlintHrgn == NULL) {
|
|
LocalFree(aRegional);
|
|
LocalFree(paWinfo);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Initialize the glint regions to empty.
|
|
*/
|
|
for (i = 0; i < Depth; i++) {
|
|
aGlintHrgn[i] = CreateRectRgn(0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Go from the bottom up to generate the shadow region. Skip the desktop
|
|
* since it doesn't cast a shadow.
|
|
*/
|
|
hrgnShadow = CreateRectRgn(0, 0, 0, 0);
|
|
for (iHwnd = cHwnds - 2; iHwnd >= 0; iHwnd--) {
|
|
HRGN hrgnWindow; // the original region of the shadow castor.
|
|
|
|
hrgnWindow = CreateWindowRgn(iHwnd);
|
|
|
|
if (fGlint && !aRegional[iHwnd]) {
|
|
/*
|
|
* add this window's glint rectangle to the glint region for the
|
|
* appropriate level. Since no windows intersect on a
|
|
* single level we don't need to worry about it. Also,
|
|
* no shadows will be cast on this glint region until
|
|
* after all glint rectangles have been set up.
|
|
*/
|
|
RECT rc;
|
|
HRGN hrgnGlintOuter;
|
|
HRGN hrgnGlintLevel;
|
|
|
|
hrgnGlintLevel = aGlintHrgn[paWinfo[iHwnd].Depth];
|
|
CopyRect(&rc, &paWinfo[iHwnd].rc);
|
|
InflateRect(&rc, 1, 1);
|
|
hrgnGlintOuter = CreateRectRgnIndirect(&rc);
|
|
CombineRgn(hrgnGlintLevel, hrgnGlintLevel, hrgnGlintOuter, RGN_OR);
|
|
DeleteObject(hrgnGlintOuter);
|
|
}
|
|
|
|
/*
|
|
* For each window below iHwnd (including the desktop) figure out
|
|
* what parts of the target window is visible and cast the shadow
|
|
* of iHwnd onto it.
|
|
*/
|
|
for (iCastTarget = cHwnds - 1; iCastTarget > iHwnd; iCastTarget--) {
|
|
HRGN hrgnCastTarget;
|
|
HRGN hrgnCastShadow;
|
|
BOOL fNullTarget;
|
|
int dDepth;
|
|
|
|
/*
|
|
* Create the CastTarget region.
|
|
*/
|
|
hrgnCastTarget = CreateWindowRgn(iCastTarget);
|
|
fNullTarget = FALSE;
|
|
for (i = iCastTarget - 1; i >= 0 && !fNullTarget; i--) {
|
|
/*
|
|
* Remove from the CastTarget region the regions of all
|
|
* windows on top of and intersecting it.
|
|
*/
|
|
if (IntersectRect(&rc, &paWinfo[iCastTarget].rc, &paWinfo[i].rc)) {
|
|
HRGN hrgnBlock;
|
|
|
|
hrgnBlock = CreateWindowRgn(i);
|
|
if (CombineRgn(hrgnCastTarget, hrgnCastTarget, hrgnBlock, RGN_DIFF)
|
|
== NULLREGION) {
|
|
/*
|
|
* The cast target is empty - no point in continuing.
|
|
*/
|
|
fNullTarget = TRUE;
|
|
}
|
|
DeleteObject(hrgnBlock);
|
|
}
|
|
}
|
|
if (fNullTarget) {
|
|
DeleteObject(hrgnCastTarget);
|
|
continue;
|
|
}
|
|
/*
|
|
* Create the region of the shadow of iHwnd cast onto
|
|
* iCastTarget. (hrgnCastShadow)
|
|
*/
|
|
hrgnCastShadow = CreateRectRgn(0, 0, 0, 0);
|
|
CombineRgn(hrgnCastShadow, hrgnWindow, NULL, RGN_COPY);
|
|
dDepth = (paWinfo[iCastTarget].Depth - paWinfo[iHwnd].Depth);
|
|
OffsetRgn(hrgnCastShadow, cxShift * dDepth, cyShift * dDepth);
|
|
|
|
if (fGlint) {
|
|
/*
|
|
* Remove the cast shadow from the glint region for the target
|
|
* target level. (Shaded areas don't have glints.)
|
|
*/
|
|
CombineRgn(aGlintHrgn[paWinfo[iCastTarget].Depth],
|
|
aGlintHrgn[paWinfo[iCastTarget].Depth],
|
|
hrgnCastShadow, RGN_DIFF);
|
|
}
|
|
|
|
/*
|
|
* remove the original window from its cast
|
|
*/
|
|
CombineRgn(hrgnCastShadow, hrgnCastShadow, hrgnWindow, RGN_DIFF);
|
|
/*
|
|
* restrict the cast shadow to the cast target area.
|
|
*/
|
|
CombineRgn(hrgnCastShadow, hrgnCastShadow, hrgnCastTarget, RGN_AND);
|
|
/*
|
|
* Add the cast shadow into the overall shadow area.
|
|
*/
|
|
CombineRgn(hrgnShadow, hrgnShadow, hrgnCastShadow, RGN_OR);
|
|
|
|
DeleteObject(hrgnCastShadow);
|
|
DeleteObject(hrgnCastTarget);
|
|
}
|
|
|
|
DeleteObject(hrgnWindow);
|
|
}
|
|
|
|
if (fGlint) {
|
|
/*
|
|
* Combine together all the glint regions
|
|
*/
|
|
if (hrgnGlintMask) {
|
|
DeleteObject(hrgnGlintMask);
|
|
}
|
|
hrgnGlintMask = CreateRectRgn(0, 0, 0, 0);
|
|
for (i = Depth - 1; i >= 0; i--) {
|
|
int j;
|
|
|
|
CombineRgn(hrgnGlintMask, hrgnGlintMask, aGlintHrgn[i], RGN_OR);
|
|
DeleteObject(aGlintHrgn[i]);
|
|
|
|
/*
|
|
* remove from the glint region the window areas of the windows
|
|
* on this level, making the glint regions frames. This also
|
|
* has the effect of removing glint regions below this level
|
|
* that would be covered by other windows.
|
|
*/
|
|
for (j = cHwnds - 2; j >= 0; j--) {
|
|
if (paWinfo[j].Depth == i) {
|
|
HRGN hrgnWindow;
|
|
|
|
hrgnWindow = CreateRectRgnIndirect(&paWinfo[j].rc);
|
|
CombineRgn(hrgnGlintMask, hrgnGlintMask, hrgnWindow, RGN_DIFF);
|
|
DeleteObject(hrgnWindow);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* AND in the appropriate mask region to make the shadows transparant.
|
|
*/
|
|
if (fVMask && fHMask) {
|
|
/*
|
|
* We don't create this massive mask until we need it.
|
|
*/
|
|
if (hrgnCheckers == NULL) {
|
|
hrgnCheckers = CreateRectRgnIndirect(&rcDesk);
|
|
CombineRgn(hrgnCheckers, hrgnVMask, NULL, RGN_COPY);
|
|
CombineRgn(hrgnCheckers, hrgnHMask, hrgnCheckers, RGN_XOR);
|
|
}
|
|
CombineRgn(hrgnShadow, hrgnCheckers, hrgnShadow, RGN_AND);
|
|
} else if (fVMask) {
|
|
CombineRgn(hrgnShadow, hrgnVMask, hrgnShadow, RGN_AND);
|
|
} else if (fHMask) {
|
|
CombineRgn(hrgnShadow, hrgnHMask, hrgnShadow, RGN_AND);
|
|
}
|
|
|
|
if (fGlint) {
|
|
/*
|
|
* Or in the glint region which would not be transparent.
|
|
*/
|
|
CombineRgn(hrgnShadow, hrgnShadow, hrgnGlintMask, RGN_OR);
|
|
}
|
|
|
|
SetWindowRgn(hwndMrShadow, hrgnShadow, TRUE); // gives hrgnShadow to system.
|
|
InvalidateRect(hwndMrShadow, NULL, TRUE);
|
|
|
|
/*
|
|
* Remember paWinfo for next time.
|
|
*/
|
|
if (paWinfoLast) {
|
|
LocalFree(paWinfoLast);
|
|
}
|
|
paWinfoLast = paWinfo;
|
|
cHwndInfoLast = cHwnds;
|
|
}
|
|
|
|
|
|
//
|
|
// File IO - make that registry IO!
|
|
//
|
|
|
|
|
|
BOOL MyQueryProfileSize(
|
|
LPTSTR szFname,
|
|
INT *pSize)
|
|
{
|
|
DWORD type;
|
|
|
|
*pSize = 0;
|
|
if (hKeyMrShadow == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(RegQueryValueEx(hKeyMrShadow, szFname, 0, &type, NULL, (LPDWORD)pSize)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
BOOL MyQueryProfileData(
|
|
LPTSTR szFname,
|
|
VOID *lpBuf,
|
|
INT Size)
|
|
{
|
|
DWORD type = REG_BINARY;
|
|
|
|
if (hKeyMrShadow == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(RegQueryValueEx(hKeyMrShadow, szFname, NULL, &type, lpBuf, (LPDWORD)&Size)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
UINT MyWriteProfileData(
|
|
LPTSTR szFname,
|
|
VOID *lpBuf,
|
|
UINT cb)
|
|
{
|
|
if (hKeyMrShadow == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(RegSetValueEx(hKeyMrShadow, szFname, 0, REG_BINARY, lpBuf, (DWORD)cb)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CommandMsg(WORD cmd)
|
|
{
|
|
FARPROC lpfp;
|
|
|
|
switch (cmd) {
|
|
case CMD_HELP:
|
|
// WinHelp(hwndMrShadow, pszHelpFileName, HELP_INDEX, 0L);
|
|
break;
|
|
|
|
case CMD_EXIT:
|
|
// WinHelp(hwndMrShadow, pszHelpFileName, HELP_QUIT, 0);
|
|
PostMessage(hwndMrShadow, WM_CLOSE, 0, 0L);
|
|
break;
|
|
|
|
case CMD_ABOUT:
|
|
// lpfp = MakeProcInstance((FARPROC)AboutDlgProc, hInst);
|
|
// DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hwndMrShadow, (DLGPROC)lpfp);
|
|
// FreeProcInstance(lpfp);
|
|
break;
|
|
|
|
default:
|
|
return(FALSE);
|
|
break;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
VOID DrawGlintRect(
|
|
HDC hdc,
|
|
RECT *prc,
|
|
int cxShift,
|
|
int cyShift)
|
|
{
|
|
RECT rcLeft, rcTop, rcBottom, rcRight;
|
|
|
|
SetRect(&rcLeft,
|
|
prc->left,
|
|
prc->top,
|
|
prc->left + 1,
|
|
prc->bottom);
|
|
SetRect(&rcRight,
|
|
prc->right - 1,
|
|
prc->top,
|
|
prc->right,
|
|
prc->bottom);
|
|
SetRect(&rcTop,
|
|
prc->left,
|
|
prc->top,
|
|
prc->right,
|
|
prc->top + 1);
|
|
SetRect(&rcBottom,
|
|
prc->left,
|
|
prc->bottom - 1,
|
|
prc->right,
|
|
prc->bottom);
|
|
|
|
if (cxShift > GLINTSENSITIVITY) {
|
|
/*
|
|
* Paint left side white, right side black
|
|
*/
|
|
FillRect(hdc, &rcLeft, GetStockObject(WHITE_BRUSH));
|
|
FillRect(hdc, &rcRight, GetStockObject(BLACK_BRUSH));
|
|
} else if (cxShift < -GLINTSENSITIVITY) {
|
|
/*
|
|
* Paint left side black, right side white
|
|
*/
|
|
FillRect(hdc, &rcLeft, GetStockObject(BLACK_BRUSH));
|
|
FillRect(hdc, &rcRight, GetStockObject(WHITE_BRUSH));
|
|
} else {
|
|
/*
|
|
* Paint both sides gray
|
|
*/
|
|
FillRect(hdc, &rcLeft, GetStockObject(GRAY_BRUSH));
|
|
FillRect(hdc, &rcRight, GetStockObject(GRAY_BRUSH));
|
|
}
|
|
if (cyShift > GLINTSENSITIVITY) {
|
|
/*
|
|
* Paint top side white, bottom side black
|
|
*/
|
|
FillRect(hdc, &rcTop, GetStockObject(WHITE_BRUSH));
|
|
FillRect(hdc, &rcBottom, GetStockObject(BLACK_BRUSH));
|
|
} else if (cyShift < -GLINTSENSITIVITY) {
|
|
/*
|
|
* Paint top side black, bottom side white
|
|
*/
|
|
FillRect(hdc, &rcTop, GetStockObject(BLACK_BRUSH));
|
|
FillRect(hdc, &rcBottom, GetStockObject(WHITE_BRUSH));
|
|
} else {
|
|
/*
|
|
* Paint both sides gray
|
|
*/
|
|
FillRect(hdc, &rcTop, GetStockObject(GRAY_BRUSH));
|
|
FillRect(hdc, &rcBottom, GetStockObject(GRAY_BRUSH));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/********** MrShadow Window Procedure **************/
|
|
|
|
LONG APIENTRY MrShadowWndProc(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
INT iReal;
|
|
RECT rc;
|
|
HMENU hMenu;
|
|
HWND hwndTop;
|
|
|
|
if (msg == wmRefreshMsg) {
|
|
CalculateRegion(FALSE);
|
|
return(0L);
|
|
}
|
|
|
|
switch (msg) {
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_NCHITTEST:
|
|
return(HTTRANSPARENT);
|
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
{
|
|
LPWINDOWPOS pwp = (LPWINDOWPOS)lParam;
|
|
|
|
pwp->hwndInsertAfter = HWND_TOP;
|
|
pwp->x = 0;
|
|
pwp->y = 0;
|
|
pwp->cx = rcDesk.right;
|
|
pwp->cy = rcDesk.bottom;
|
|
return(0);
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
CalculateRegion(FALSE); // To catch cmd windows
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
{
|
|
HDC hdc = (HDC)wParam;
|
|
RECT rc;
|
|
HBRUSH hbr;
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
hbr = CreateSolidBrush(RGB(bShadowColor, bShadowColor, bShadowColor));
|
|
FillRect(hdc, &rc, hbr);
|
|
DeleteObject(hbr);
|
|
return(1);
|
|
}
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
if (fGlint) {
|
|
PAINTSTRUCT ps;
|
|
int i;
|
|
RECT rcLeft, rcRight, rcTop, rcBottom, rc;
|
|
HRGN hrgnSave;
|
|
|
|
BeginPaint(hwnd, &ps);
|
|
|
|
/*
|
|
* Draw Glint Rects
|
|
*/
|
|
hrgnSave = CreateRectRgnIndirect(&rcDesk);
|
|
GetClipRgn(ps.hdc, hrgnSave);
|
|
if (hrgnGlintMask) {
|
|
SelectClipRgn(ps.hdc, hrgnGlintMask);
|
|
}
|
|
for (i = cHwnds - 2; i >= 0; i--) {
|
|
if (!aRegional[i]) {
|
|
CopyRect(&rc, &paWinfo[i].rc);
|
|
InflateRect(&rc, 1, 1);
|
|
DrawGlintRect(ps.hdc, &rc, cxShift, cyShift);
|
|
}
|
|
}
|
|
SelectClipRgn(ps.hdc, hrgnSave);
|
|
DeleteObject(hrgnSave);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
break;
|
|
}
|
|
goto DoDWP;
|
|
|
|
case WM_COMMAND:
|
|
if (!CommandMsg(GET_WM_COMMAND_ID(wParam, lParam)))
|
|
goto DoDWP;
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
CommandMsg(GET_WM_COMMAND_ID(wParam, lParam));
|
|
goto DoDWP;
|
|
|
|
default:
|
|
DoDWP:
|
|
return(DefWindowProc(hwnd, msg, wParam, lParam));
|
|
break;
|
|
}
|
|
return(0L);
|
|
}
|
|
|
|
|
|
|
|
|
|
HBRUSH MyCreateHatchBrush(
|
|
UINT style,
|
|
DWORD color)
|
|
{
|
|
HBRUSH hbrHatch;
|
|
HBITMAP hbm, hbmSave;
|
|
HDC hdcMem, hdc;
|
|
|
|
hdc = GetDC(hwndMrShadow);
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
ReleaseDC(hwndMrShadow, hdc);
|
|
|
|
hbm = CreateBitmap(2, 2, 1, 1, NULL);
|
|
hbmSave = SelectObject(hdcMem, hbm);
|
|
|
|
switch (style) {
|
|
case HS_CROSS:
|
|
SetPixel(hdcMem, 0, 0, color);
|
|
SetPixel(hdcMem, 0, 1, BACKCOLOR);
|
|
SetPixel(hdcMem, 1, 0, BACKCOLOR);
|
|
SetPixel(hdcMem, 1, 1, color);
|
|
break;
|
|
|
|
case HS_VERTICAL:
|
|
SetPixel(hdcMem, 0, 0, color);
|
|
SetPixel(hdcMem, 0, 1, color);
|
|
SetPixel(hdcMem, 1, 0, BACKCOLOR);
|
|
SetPixel(hdcMem, 1, 1, BACKCOLOR);
|
|
break;
|
|
|
|
case HS_HORIZONTAL:
|
|
SetPixel(hdcMem, 0, 0, color);
|
|
SetPixel(hdcMem, 0, 1, BACKCOLOR);
|
|
SetPixel(hdcMem, 1, 0, color);
|
|
SetPixel(hdcMem, 1, 1, BACKCOLOR);
|
|
break;
|
|
}
|
|
|
|
SelectObject(hdcMem, hbmSave);
|
|
DeleteDC(hdcMem);
|
|
|
|
hbrHatch = CreatePatternBrush(hbm);
|
|
DeleteObject(hbm);
|
|
|
|
return(hbrHatch);
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG APIENTRY MrShadowUIWndProc(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
static BOOL fOnSpot = FALSE;
|
|
static BOOL fDragSpot = FALSE;
|
|
static BOOL fOnBar = FALSE;
|
|
static BOOL fDragBar = FALSE;
|
|
static int cxShiftNext, cyShiftNext;
|
|
static BYTE bShadowColorNext;
|
|
RECT rc;
|
|
|
|
switch (msg) {
|
|
case WM_CREATE:
|
|
cxShiftNext = cxShift;
|
|
cyShiftNext = cyShift;
|
|
bShadowColorNext = bShadowColor;
|
|
break;
|
|
|
|
case WM_ENDSESSION:
|
|
case WM_CLOSE:
|
|
DestroyWindow(hwndMrShadow);
|
|
DestroyWindow(hwnd);
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
GetClientRect(hwnd, &rc);
|
|
if (fDragSpot) {
|
|
|
|
SetCursor(hCurCross);
|
|
cxShiftNext = rc.right / 2 - LOWORD(lParam);
|
|
cyShiftNext = rc.bottom / 2 - HIWORD(lParam);
|
|
InflateRect(&rc, -CXCOLORBAR, 0);
|
|
InvalidateRect(hwnd, &rc, TRUE);
|
|
UpdateWindow(hwnd);
|
|
} else if (fDragBar) {
|
|
|
|
SetCursor(hCurUpDown);
|
|
bShadowColorNext = (BYTE)(HIWORD(lParam) * 255 / rc.bottom);
|
|
rc.left = rc.right - CXCOLORBAR;
|
|
InvalidateRect(hwnd, &rc, TRUE);
|
|
UpdateWindow(hwnd);
|
|
} else {
|
|
POINT pt;
|
|
|
|
pt.x = (int)LOWORD(lParam);
|
|
pt.y = (int)HIWORD(lParam);
|
|
InflateRect(&rc,
|
|
-(rc.right / 2 - RHITCIRCLE),
|
|
-(rc.bottom / 2 - RHITCIRCLE));
|
|
OffsetRect(&rc, -cxShiftNext, -cyShiftNext);
|
|
if (PtInRect(&rc, pt)) {
|
|
SetCursor(hCurCross);
|
|
fOnSpot = TRUE;
|
|
} else {
|
|
GetClientRect(hwnd, &rc);
|
|
if (LOWORD(lParam) >= (rc.right - CXCOLORBAR)) {
|
|
SetCursor(hCurUpDown);
|
|
fOnBar = TRUE;
|
|
} else {
|
|
SetCursor(hCurArrow);
|
|
fOnSpot = FALSE;
|
|
fOnBar = FALSE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
SendMessage(hwnd, WM_MOUSEMOVE, 0, lParam);
|
|
if (fOnSpot) {
|
|
fDragSpot = TRUE;
|
|
} else if (fOnBar) {
|
|
fDragBar = TRUE;
|
|
} else if (LOWORD(lParam) < CXCOLORBAR) {
|
|
GetClientRect(hwnd, &rc);
|
|
if (HIWORD(lParam) < rc.bottom / 4) {
|
|
fHMask = fVMask = FALSE;
|
|
} else if (HIWORD(lParam) < rc.bottom / 2) {
|
|
fVMask = TRUE;
|
|
fHMask = FALSE;
|
|
} else if (HIWORD(lParam) < rc.bottom * 3 / 4) {
|
|
fVMask = FALSE;
|
|
fHMask = TRUE;
|
|
} else {
|
|
fVMask = TRUE;
|
|
fHMask = TRUE;
|
|
}
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
CalculateRegion(TRUE);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
SendMessage(hwnd, WM_MOUSEMOVE, 0, lParam);
|
|
if (fDragSpot) {
|
|
|
|
fDragSpot = FALSE;
|
|
GetClientRect(hwnd, &rc);
|
|
cxShift = cxShiftNext = rc.right / 2 - LOWORD(lParam);
|
|
cyShift = cyShiftNext = rc.bottom / 2 - HIWORD(lParam);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
CalculateRegion(TRUE);
|
|
UpdateWindow(hwnd);
|
|
} else if (fDragBar) {
|
|
|
|
fDragBar = FALSE;
|
|
GetClientRect(hwnd, &rc);
|
|
bShadowColor = bShadowColorNext = (BYTE)(HIWORD(lParam) * 255 / rc.bottom);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
CalculateRegion(TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rcDraw;
|
|
int y;
|
|
HBRUSH hbr, hbrRed;
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
BeginPaint(hwnd, &ps);
|
|
/*
|
|
* Draw shadow angle circles
|
|
*/
|
|
hbr = CreateSolidBrush(RGB(bShadowColorNext, bShadowColorNext, bShadowColorNext));
|
|
SelectObject(ps.hdc, hbr);
|
|
Ellipse(ps.hdc,
|
|
rc.right / 2 - RSHADOWCIRCLE + cxShiftNext,
|
|
rc.bottom / 2 - RSHADOWCIRCLE + cyShiftNext,
|
|
rc.right / 2 + RSHADOWCIRCLE + cxShiftNext,
|
|
rc.bottom / 2 + RSHADOWCIRCLE + cyShiftNext);
|
|
SelectObject(ps.hdc, GetStockObject(LTGRAY_BRUSH));
|
|
DeleteObject(hbr);
|
|
Ellipse(ps.hdc,
|
|
rc.right / 2 - RSHADOWCIRCLE,
|
|
rc.bottom / 2 - RSHADOWCIRCLE,
|
|
rc.right / 2 + RSHADOWCIRCLE,
|
|
rc.bottom / 2 + RSHADOWCIRCLE);
|
|
SelectObject(ps.hdc, GetStockObject(WHITE_BRUSH));
|
|
Ellipse(ps.hdc,
|
|
rc.right / 2 - RHITCIRCLE - cxShiftNext,
|
|
rc.bottom / 2 - RHITCIRCLE - cyShiftNext,
|
|
rc.right / 2 + RHITCIRCLE - cxShiftNext,
|
|
rc.bottom / 2 + RHITCIRCLE - cyShiftNext);
|
|
|
|
/*
|
|
* Draw shade bar
|
|
*/
|
|
SetRect(&rcDraw, rc.right - CXCOLORBAR, 0, rc.right, 1);
|
|
for (y = 0; y < rc.bottom; y++) {
|
|
BYTE bColor;
|
|
|
|
bColor = (BYTE)(255 * y / rc.bottom);
|
|
hbr = CreateSolidBrush(RGB(bColor, bColor, bColor));
|
|
FillRect(ps.hdc, &rcDraw, hbr);
|
|
DeleteObject(hbr);
|
|
OffsetRect(&rcDraw, 0, 1);
|
|
}
|
|
|
|
/*
|
|
* Draw shade bar pointer
|
|
*/
|
|
y = bShadowColorNext * rc.bottom / 255;
|
|
SetRect(&rcDraw, rc.right - CXCOLORBAR, y - 1,
|
|
rc.right, y + 1);
|
|
hbrRed = CreateSolidBrush(RGB(255, 0, 0));
|
|
FillRect(ps.hdc, &rcDraw, hbr);
|
|
|
|
/*
|
|
* Draw shade mask buttons
|
|
*/
|
|
SetRect(&rcDraw, 0, 0, CXCOLORBAR, rc.bottom >> 2);
|
|
|
|
hbr = CreateSolidBrush(
|
|
RGB(bShadowColorNext, bShadowColorNext, bShadowColorNext));
|
|
FillRect(ps.hdc, &rcDraw, hbr);
|
|
DeleteObject(hbr);
|
|
if (!fHMask && !fVMask) {
|
|
FrameRect(ps.hdc, &rcDraw, hbrRed);
|
|
} else {
|
|
DrawGlintRect(ps.hdc, &rcDraw, cxShiftNext, cyShiftNext);
|
|
}
|
|
OffsetRect(&rcDraw, 0, rc.bottom >> 2);
|
|
|
|
hbr = MyCreateHatchBrush(HS_VERTICAL,
|
|
RGB(bShadowColorNext, bShadowColorNext, bShadowColorNext));
|
|
FillRect(ps.hdc, &rcDraw, hbr);
|
|
DeleteObject(hbr);
|
|
if (fVMask && !fHMask) {
|
|
FrameRect(ps.hdc, &rcDraw, hbrRed);
|
|
} else {
|
|
DrawGlintRect(ps.hdc, &rcDraw, cxShiftNext, cyShiftNext);
|
|
}
|
|
OffsetRect(&rcDraw, 0, rc.bottom >> 2);
|
|
|
|
hbr = MyCreateHatchBrush(HS_HORIZONTAL,
|
|
RGB(bShadowColorNext, bShadowColorNext, bShadowColorNext));
|
|
FillRect(ps.hdc, &rcDraw, hbr);
|
|
DeleteObject(hbr);
|
|
if (!fVMask && fHMask) {
|
|
FrameRect(ps.hdc, &rcDraw, hbrRed);
|
|
} else {
|
|
DrawGlintRect(ps.hdc, &rcDraw, cxShiftNext, cyShiftNext);
|
|
}
|
|
OffsetRect(&rcDraw, 0, rc.bottom >> 2);
|
|
|
|
hbr = MyCreateHatchBrush(HS_CROSS,
|
|
RGB(bShadowColorNext, bShadowColorNext, bShadowColorNext));
|
|
FillRect(ps.hdc, &rcDraw, hbr);
|
|
DeleteObject(hbr);
|
|
if (fVMask && fHMask) {
|
|
FrameRect(ps.hdc, &rcDraw, hbrRed);
|
|
} else {
|
|
DrawGlintRect(ps.hdc, &rcDraw, cxShiftNext, cyShiftNext);
|
|
}
|
|
OffsetRect(&rcDraw, 0, rc.bottom >> 2);
|
|
DeleteObject(hbrRed);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return(ibDefWindowProc(hwnd, msg, wParam, lParam));
|
|
}
|
|
|
|
|
|
|
|
BOOL InitApplication(
|
|
HANDLE hInst)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
wmRefreshMsg = RegisterWindowMessage(TEXT(szMYWM_REFRESH));
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = MrShadowWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInst;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = pszTitle2;
|
|
|
|
if (!RegisterClass(&wc)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
wc.lpfnWndProc = MrShadowUIWndProc;
|
|
wc.hbrBackground = CreateSolidBrush(BACKCOLOR);
|
|
wc.lpszClassName = pszTitle;
|
|
wc.hCursor = NULL;
|
|
|
|
return(RegisterClass(&wc));
|
|
}
|
|
|
|
|
|
|
|
int WINAPI WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
|
|
lpCmdLine;
|
|
nCmdShow;
|
|
|
|
hInst = hInstance;
|
|
|
|
if (!InitApplication(hInstance)) {
|
|
return (FALSE);
|
|
}
|
|
|
|
hCurCross = LoadCursor(NULL, IDC_CROSS);
|
|
hCurArrow = LoadCursor(NULL, IDC_ARROW);
|
|
hCurUpDown = LoadCursor(NULL, IDC_SIZENS);
|
|
|
|
hwndMrShadow = CreateWindowEx(
|
|
WS_EX_TOPMOST,
|
|
pszTitle2,
|
|
TEXT(""),
|
|
WS_POPUP,
|
|
0, 0, 0, 0, NULL, NULL, hInst, NULL);
|
|
|
|
if (!hwndMrShadow) {
|
|
return(0);
|
|
}
|
|
|
|
if (!SetMrShadowHooks(hwndMrShadow)) {
|
|
MessageBeep(0);
|
|
return(0);
|
|
}
|
|
|
|
rcDesk.left = 0;
|
|
rcDesk.right = GetSystemMetrics(SM_CXSCREEN);
|
|
rcDesk.top = 0;
|
|
rcDesk.bottom = GetSystemMetrics(SM_CYSCREEN),
|
|
|
|
InitBigRegions();
|
|
CalculateRegion(TRUE);
|
|
|
|
SetWindowPos(hwndMrShadow, HWND_TOP,
|
|
0,
|
|
0,
|
|
rcDesk.right,
|
|
rcDesk.bottom,
|
|
SWP_SHOWWINDOW);
|
|
|
|
SetActiveWindow(hwndMrShadow);
|
|
|
|
SetTimer(hwndMrShadow, 1, 1000, NULL); // To catch cmd windows
|
|
|
|
CreateWindowEx(0, pszTitle, pszTitle,
|
|
WS_POPUP | IBS_HORZCAPTION | WS_VISIBLE | WS_BORDER | WS_SYSMENU,
|
|
rcDesk.right - 64,
|
|
rcDesk.bottom - 64,
|
|
64,
|
|
64,
|
|
NULL, NULL, hInst, NULL);
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
KillTimer(hwndMrShadow, 1);
|
|
if (paWinfoLast) {
|
|
LocalFree(paWinfoLast);
|
|
}
|
|
DeleteObject(hrgnVMask);
|
|
DeleteObject(hrgnHMask);
|
|
if (hrgnCheckers) {
|
|
DeleteObject(hrgnCheckers);
|
|
}
|
|
if (hrgnGlintMask) {
|
|
DeleteObject(hrgnGlintMask);
|
|
}
|
|
if (aRegional) {
|
|
LocalFree(aRegional);
|
|
}
|
|
ClearMrShadowHooks(hwndMrShadow);
|
|
return(0);
|
|
}
|