Question

I am trying to work out how to fade out or dim the Windows Desktop and then display a rectangular portion of the desktop normally. This is for a screen area capture program. You can see the precise effect I am after in Jing Fading the background in a Web page is also commonly done. Any tips/pointers/C++ source much appreciated. Google has not helped so far.

Thanks, Neville

Was it helpful?

Solution

Use a layered window that covers the entire screen, but paint it with color key values such that the rectangular region of interest (the area that should be undarkened) is filled entirely with the color key. This region will then be completely transparent, and not darkened like the rest of the desktop. The rest of your layered window should be set to have a constant alpha value that is mostly transparent and filled with a dark color.

Here's a complete, working example:

#include "stdafx.h"
#include "ScreenCapper.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

const COLORREF transparentColor = RGB(255,0,0); // Pure red is the color key, or totally transparent color
const BYTE overallTranparencyAmount = 90; // Out of 255
int DesktopWidth,DesktopHeight;

int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    DesktopWidth = GetSystemMetrics(SM_CXSCREEN);
    DesktopHeight = GetSystemMetrics(SM_CYSCREEN);

    MSG msg;
    HACCEL hAccelTable;

    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_SCREENCAPPER, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SCREENCAPPER));

    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    memset(&wcex,0,sizeof(WNDCLASSEX));
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SCREENCAPPER));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    //wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SCREENCAPPER);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance;
    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle,WS_POPUP, 0, 0, DesktopWidth, DesktopHeight, NULL, NULL, hInstance, NULL);
    if (!hWnd)
        return FALSE;
    SetLayeredWindowAttributes(hWnd,transparentColor,32,LWA_COLORKEY | LWA_ALPHA);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    if (message == WM_COMMAND)
    {
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    else if (message == WM_PAINT)
    {
        hdc = BeginPaint(hWnd, &ps);

        HBRUSH hDarkBackgroundBrush = CreateSolidBrush(RGB(0,0,0));
        HBRUSH hRegionOfInterestBrush = CreateSolidBrush(transparentColor);

        RECT screenRect;
        screenRect.left = screenRect.top = 0;
        screenRect.right = DesktopWidth;
        screenRect.bottom = DesktopHeight;

        RECT interestRect;
        interestRect.left = interestRect.top = 300;
        interestRect.right = interestRect.bottom = 600;
        FillRect(hdc,&screenRect,hDarkBackgroundBrush);
        FillRect(hdc,&interestRect,hRegionOfInterestBrush);

        DeleteObject(hDarkBackgroundBrush);
        DeleteObject(hRegionOfInterestBrush);
        EndPaint(hWnd, &ps);
    }
    else if (message == WM_DESTROY)
    {
        PostQuitMessage(0);
    }
    else
        return DefWindowProc(hWnd, message, wParam, lParam);
    return 0;
}

OTHER TIPS

The official way is with FadeWindow() api : Windows does that on Display Control Panel

See the standard code in C

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top