Click here to Skip to main content
15,884,099 members
Articles / Desktop Programming / MFC
Tip/Trick

Security Blackout Window

Rate me:
Please Sign up or sign in to vote.
4.98/5 (15 votes)
20 Nov 2013CPOL2 min read 26.7K   29   8
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.

Image 1

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.

C++
#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)


Written By
Retired
United Kingdom United Kingdom
I was a Software Engineer for 40+ years starting with mainframes, and moving down in scale through midi, UNIX and Windows PCs. I started as an operator in the 1960s, learning assembler programming, before switching to development and graduating to COBOL, Fortran and PLUS (a proprietary language for Univac systems). Later years were a mix of software support and development, using mainly C, C++ and Java on UNIX and Windows systems.

Since retiring I have been learning some of the newer (to me) technologies (C#, .NET, WPF, LINQ, SQL, Python ...) that I never used in my professional life, and am actually able to understand some of them.

I still hope one day to become a real programmer.

Comments and Discussions

 
NewsPorted to C# Pin
Brisingr Aerowing11-Dec-14 17:17
professionalBrisingr Aerowing11-Dec-14 17:17 
GeneralRe: Ported to C# Pin
Richard MacCutchan11-Dec-14 23:09
mveRichard MacCutchan11-Dec-14 23:09 
GeneralRe: Ported to C# Pin
Brisingr Aerowing12-Dec-14 3:14
professionalBrisingr Aerowing12-Dec-14 3:14 
QuestionGreat article. Pin
Pete O'Hanlon20-Nov-13 4:31
mvePete O'Hanlon20-Nov-13 4:31 
AnswerRe: Great article. Pin
Richard MacCutchan20-Nov-13 8:15
mveRichard MacCutchan20-Nov-13 8:15 
QuestionGreat article Pin
Jonathan [Darka]20-Nov-13 3:03
professionalJonathan [Darka]20-Nov-13 3:03 
Would be nice to have a screenshot of the Blackout Window in the article.

regards,

AnswerRe: Great article Pin
Richard MacCutchan20-Nov-13 3:31
mveRichard MacCutchan20-Nov-13 3:31 
GeneralRe: Great article Pin
Jonathan [Darka]20-Nov-13 4:43
professionalJonathan [Darka]20-Nov-13 4:43 

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

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