Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Security Blackout Window

0.00/5 (No votes)
20 Nov 2013 1  
Obscure a window or the screen and show a dialog.

Introduction

Someone posted a question in Q&A recently, asking how to create the semi-transparent "blackout" window on the screen in the same way that Windows does when it asks you whether to allow a program to proceed or not. I responded by saying that all you need is another window on top of the original, and a dialog box with the question. Having thought a bit more about the problem I wondered whether that would actually work or not. After some investigation I found the answer was actually fairly simple, once I had figured out how to create and manage the secondary window.

Using the code

The code below is fairly self-explanatory but a few notes may help:

  • First we need to register a new Windows class with the following attributes:
    • No special class styles, this window does nothing much.
    • Use DefWindowProc as its message handler, as our code will not deal with any messages.
    • Set the backgound colour to the system colour value COLOR_DESKTOP, which is black on my system.
  • Get the dimensions of the caller's window (see note below) and create a Window of our new class with the following attributes:
    • Extended style of WS_EX_LAYERED, this is a layered window with no frame borders.
    • Styles of WS_VISIBLE | WS_POPUP, this is a visible popup.
    • The same size and position as the caller's window.
    • Its parent must be the caller's Window, to make the parent inaccessible.
  • Next we call SetLayeredWindowAttributes to make the overlay completely obscure the parent window.
  • Sleep for half a second. Yes, this is fluff.
  • Call SetLayeredWindowAttributes again to make the overlay semi-transparent.
  • Show a dialog: I have used the system TaskDialog to display the user's message text.
  • When complete, destroy the window, unregister the class and return the response to the caller.

In my code, if the caller does not provide a Window handle then we get the handle of the Desktop Window and completely cover the screen.

#include <Windows.h>
#include <tchar.h>
#include <Commctrl.h>

/// <summary>
/// This function registers and creates a simple overlay Window
/// that is used to obscure the current window or the entire Desktop
/// until a dialog has been responded to.
/// </summary>
///
/// <param name="hParentWnd">Handle to the parent window to be obscured</param>
/// <param name="szTitle">optional title of the dialog box</param>
/// <param name="szMain">Main line of text</param>
/// <param name="szContent">supplementary dialog text</param>
///
/// <returns>TRUE or FALSE, depending on the user's response</returns>
///
BOOL StopDialog(HWND  hParentWnd,
                PTSTR  szTitle,
                PTSTR  szMain,
                PTSTR  szContent
                )
{
    WNDCLASSEX      wndClass;        // class structure to register the obscuring window
    HWND            hStopWnd;        // handle to the obscuring window
    RECT            rectParent;      // to get the dimensions of the parent window
    int             nButton = IDNO;  // default answer
    // Register the window class
    wndClass.cbSize        = sizeof wndClass;                   //
    wndClass.style         = 0;                                 // no  styles for this class
    wndClass.lpfnWndProc   = DefWindowProc;                     // we will not handle any messages
    wndClass.cbClsExtra    = 0;                                 // no extra space required
    wndClass.cbWndExtra    = 0;                                 //
    wndClass.hInstance     = GetModuleHandle(NULL);             // instance handle to the current process
    wndClass.hIcon         = NULL;                              // no icon
    wndClass.hCursor       = NULL;                              //    or cursor
    wndClass.hbrBackground = GetSysColorBrush(COLOR_DESKTOP);   // a black brush
    wndClass.lpszMenuName  = NULL;                              // no menu
    wndClass.lpszClassName = _T("Blackout");                    // our class name
    wndClass.hIconSm       = NULL;                              // no small icon
    if (RegisterClassEx(&wndClass))
    {
        if (hParentWnd == NULL)
        hParentWnd = GetDesktopWindow();                   // if no window given, then we will use the entire desktop
        GetWindowRect(hParentWnd, &rectParent);            // get the dimensions of the parent window
        int nWidth = rectParent.right - rectParent.left;
        int nHeight = rectParent.bottom - rectParent.top;
        // create the overlay window
        hStopWnd = CreateWindowEx(         // create a new window same size and position as the parent
            WS_EX_LAYERED,                 // this is a layered window
            wndClass.lpszClassName,        // registered class name
            NULL,                          // no title necessary
            WS_VISIBLE | WS_POPUP,         // it's a popup and always visible
            rectParent.left,               // horizontal position of window
            rectParent.top,                // vertical position of window
            nWidth,                        // window width
            nHeight,                       // window height
            hParentWnd,                    // handle to parent or owner window
            NULL,                          // no menu handle
            wndClass.hInstance,            // handle to application instance
            NULL                           // no create parameters
            );
        if (hStopWnd)
        {
            // we have our overlay window so set it to totally obscure its parent
            SetLayeredWindowAttributes(hStopWnd, 0, 255, ULW_ALPHA);
            // wait half a second
            Sleep(500);
            // now set it less opaque and show the response dialog
            SetLayeredWindowAttributes(hStopWnd, 0, 196, ULW_ALPHA);
            // We use a standard Windows TaskDialog control as it is far simpler
            // than creating a custom dialog box, although that is still an option.
            HRESULT hResult = TaskDialog(hStopWnd,
                NULL,                                // no hInstance as we use system icons and buttons
                szTitle,                             // title provided by the caller
                szMain,                              // main message ditto
                szContent,                           // secondary message ditto
                TDCBF_YES_BUTTON | TDCBF_NO_BUTTON,  // use the Yes and No buttons
                TD_SHIELD_ICON,                      // and system shield icon
                &nButton                             // response stored in here
                );
            if (hResult != S_OK)  // if the dialog fails for any reason, we answer No
                nButton = IDNO;
            DestroyWindow(hStopWnd); // finished with our obscuring window
        }
        UnregisterClass(wndClass.lpszClassName, wndClass.hInstance); // and finished with our class
    }
    return nButton == IDYES ? TRUE : FALSE;  // return TRUE if the user answers Yes, otherwis FALSE
} 

History

  • Initial post 27 October 2013
  • Cosmetic changes: 20 November 2013
  • Added sample image: 20 November 2013.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here