Click here to Skip to main content
Click here to Skip to main content

Security Blackout Window

, 20 Nov 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Richard MacCutchan
Retired
United Kingdom United Kingdom
I was a Software Support Engineer for many years using various legacy enterprise systems before learning UNIX and Windows programming - the latter largely in my own time. In my last few years of employment I spent more time in actual development.
 
Since retiring I have been learning some of the newer technologies (C#, .NET, WPF, LINQ, SQL ...) that I never used in my professional life, and am actually able to understand some of it.
 
One day I hope to become a real programmer.

Comments and Discussions

 
QuestionGreat article. PinprotectorPete O'Hanlon20-Nov-13 4:31 
AnswerRe: Great article. PinmvpRichard MacCutchan20-Nov-13 8:15 
QuestionGreat article PinmentorJonathan [Darka]20-Nov-13 3:03 
AnswerRe: Great article PinmvpRichard MacCutchan20-Nov-13 3:31 
GeneralRe: Great article PinmentorJonathan [Darka]20-Nov-13 4:43 
Perfect, thanks Richard!

Jonathan Wilkes
[DebugSPY]
 
[My Code Project Articles]

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 20 Nov 2013
Article Copyright 2013 by Richard MacCutchan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid