/****************************** 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);
}