Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You can create another window, completely black, on top of the window you want to dim, and set the black window's opacity with <a href="http://msdn.microsoft.com/en-us/library/ms633540%28VS.85%29.aspx" rel="noreferrer">SetLayeredWindowAttributes</a>. It doesn't have to be black, of course, but I guess that's the best dimming color. </p> <p>EDIT: I hacked together an example - but note that I am not an MFC developer, I usually use the Windows API directly. It seems to work okay, though. <a href="http://pastebin.com/NNqnNSLQ" rel="noreferrer">Here</a> is a pastebin. Feel free to add fade-ins etc. yourself. Also note that this dims the entire screen, you'll have to resize my dimming-window if you don't want this behaviour. See code comments.</p> <pre><code>/********************************************************************************************** MFC screen dim test :: oystein :: November 2010 Creates a simple window - click it to toggle whether a translucent black "dimmer" window is shown. The dimmer-window covers the entire screen, but the taskbar ("superbar" in Windows 7) will jump on top of it if clicked - it seems. Simple suggestions to fix that are welcome. Should work on Windows 2000 and later. Disclaimer: This is my first MFC program ever, so if anything seems wrong, it probably is. I have previously only coded with pure Win32 API, and hacked this together using online tutorials. Code provided "as-is" with no guarantees - I can not be held responsible for anything bad that happens if you run this program. ***********************************************************************************************/ #include "stdafx.h" #undef WINVER #define WINVER 0x500 // Windows 2000 &amp; above, because of layered windows // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Black window used to dim everything else // class CDimWnd : public CFrameWnd { public: CDimWnd() { // Get screen res into rect RECT rc; GetDesktopWindow()-&gt;GetWindowRect(&amp;rc); CreateEx(WS_EX_LAYERED | // Layered window for translucency WS_EX_TRANSPARENT | // Click through WS_EX_TOPMOST | // Always on top WS_EX_TOOLWINDOW, // Do not appear in taskbar &amp; similar NULL, TEXT(""), WS_POPUP, // No frame/borders - though there is // still some border left - we'll remove // it with regions 0, 0, rc.right + 10, rc.bottom + 10, // Make the window 10px larger // than screen resolution in both // directions - it is still positioned // at 0,0 NULL, NULL); // Grab a part of the window the size of the desktop - but 5px into it // Because the window is larger than the desktop res, the borders are removed CRgn rgn; rgn.CreateRectRgn(rc.left + 5, rc.top + 5, rc.right + 5, rc.bottom + 5); SetWindowRgn((HRGN)rgn, FALSE); rgn.Detach(); // We have to reposition window - (0,0) of window has not changed SetWindowPos(NULL, -5, -5, 0, 0, SWP_NOSIZE | SWP_NOZORDER); // This is where we set the opacity of the window: 0-255 SetLayeredWindowAttributes(RGB(0,0,0), 150, LWA_ALPHA); } void Close() { CFrameWnd::OnClose(); } BOOL CDimWnd::OnEraseBkgnd(CDC* pDC); // Set BKG color DECLARE_MESSAGE_MAP() }; BOOL CDimWnd::OnEraseBkgnd(CDC* pDC) { // Set brush to desired background color CBrush backBrush(RGB(0, 0, 0)); // Save old brush CBrush* pOldBrush = pDC-&gt;SelectObject(&amp;backBrush); CRect rect; pDC-&gt;GetClipBox(&amp;rect); // Erase the area needed pDC-&gt;PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC-&gt;SelectObject(pOldBrush); return TRUE; } BEGIN_MESSAGE_MAP(CDimWnd, CFrameWnd) ON_WM_ERASEBKGND() END_MESSAGE_MAP() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Global variable - is screen dimmed? bool g_bIsDimmed = false; // The main window class CMainWnd : public CFrameWnd { // Contains a CDimWnd - I'm not sure if this is the "MFC way" of doing things CDimWnd dimmer; public: CMainWnd() { Create(NULL, TEXT("Screen dimmer - Press left mouse button on window to toggle"), WS_OVERLAPPEDWINDOW, CRect(50, 50, 400, 250)); } // Left mouse button toggles dimming afx_msg void OnLButtonDown(UINT Flags, CPoint Point) { if(!g_bIsDimmed) { dimmer.ShowWindow(SW_SHOW); dimmer.BringWindowToTop(); g_bIsDimmed = true; } else { dimmer.ShowWindow(SW_HIDE); g_bIsDimmed = false; } } DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd) ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() // The app class CApp : public CWinApp { public: virtual BOOL InitInstance(); }; BOOL CApp::InitInstance() { m_pMainWnd = new CMainWnd(); m_pMainWnd-&gt;ShowWindow(m_nCmdShow); m_pMainWnd-&gt;UpdateWindow(); return TRUE; } CApp HelloApp; </code></pre> <hr /> <p><strong>UPDATE:</strong></p> <p>I hacked together some more code for you, to handle the fading. I'm still no MFC dev, and I left the code in a "rough" state (little error handling, not very robust) to give you something to do too. :) Anyway, here's one way to do it, that I think is fairly clean:</p> <p>To use it, make your main window contain a dimmer window </p> <pre><code>class CMainFrm : public CFrameWnd { CDimWnd* dimmer; public: CMainFrm() { // constructor code here ... dimmer = new CDimWnd(); } // rest of class ... }; </code></pre> <p>It can then be used e.g. like this:</p> <pre><code>dimmer-&gt;Show(); MessageBox(TEXT("Hello world")); dimmer-&gt;Hide(); </code></pre> <p>Alternatively I guess you could put this code (<code>Show()</code>/<code>Hide()</code> calls) in the constructor and destructor of the modal dialog, if you want to keep the code there. If you want a "scope"-dim, like in the example you posted, this code would have to go in the constructor &amp; destructor of the CDimWnd class, and you would need something like a static member variable to ensure that only one dimmer is running at a time (unless you want to use a global variable).</p> <p>For the dimmer window - I did this:</p> <p><strong>CDimWnd.h</strong></p> <pre><code>#define TARGET_OPACITY 70 // Target opacity 0-255 for dimmed window #define FADE_TIME 20 // Time between each fade step in milliseconds #define FADE_STEP 5 // How much to add to/remove from opacity each fade step #define ID_FADE_TIMER 1 // Call Show() and Hide() to fade in/fade out dimmer. // Creates the dimmer window in constructor. class CDimWnd : public CFrameWnd { bool m_isDimming; public: CDimWnd(); void Show(); void Hide(); protected: BOOL OnEraseBkgnd(CDC* pDC); void OnTimer(UINT_PTR nIDEvent); DECLARE_MESSAGE_MAP() }; </code></pre> <p><strong>CDimWnd.cpp</strong></p> <pre><code>#include "stdafx.h" #include "CDimWnd.h" #include "MainFrm.h" BEGIN_MESSAGE_MAP(CDimWnd, CFrameWnd) ON_WM_ERASEBKGND() END_MESSAGE_MAP() CDimWnd::CDimWnd() { // Get the main frame of the application which we want to dim. CMainFrame* pParent = theApp.pMainFrame; // Don't do anything if the main frame doesn't appear to be there if (pParent != NULL) { // Get the client area of the window to dim. CRect rc; pParent-&gt;GetClientRect(&amp;rc); pParent-&gt;ClientToScreen(&amp;rc); // convert to screen coordinates // Do some fudging to fit the client area exactly. // Other applications may not need this if the above client area fits already. rc.top += GetSystemMetrics(SM_CYFRAME); rc.top += GetSystemMetrics(SM_CYCAPTION); // MFC feature pack seems to include caption in client area rc.left -= GetSystemMetrics(SM_CXBORDER); rc.right += GetSystemMetrics(SM_CXBORDER) + 1; rc.bottom += GetSystemMetrics(SM_CYBORDER) + 1; // Create a layered window for transparency, with no caption/border. CreateEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, NULL, TEXT(""), WS_POPUP, rc.left, rc.top, rc.Width(), rc.Height(), pParent-&gt;GetSafeHwnd(), NULL); } } void CDimWnd::Show() { // If we are not already dimming, go for it if(!m_isDimming) { // Bring in front of main window. BringWindowToTop(); // Set opacity to 0 SetLayeredWindowAttributes(RGB(0,0,0), 0, LWA_ALPHA); // Show the dimmer window ShowWindow(SW_SHOW); // Create timer - the rest is handled in OnTimer() function SetTimer(ID_FADE_TIMER, FADE_TIME, NULL); } } void CDimWnd::Hide() { // If we are dimming, go for it if(m_isDimming) { // Create timer - the rest is handled in OnTimer() function SetTimer(ID_FADE_TIMER, FADE_TIME, NULL); } } void CDimWnd::OnTimer(UINT_PTR nIDEvent) { static int fade = 0; if(nIDEvent == ID_FADE_TIMER) { // We are dimming =&gt; we want to fade out if(m_isDimming) { if(fade &lt; 0) { // Fading finished - hide window completely, update status &amp; destroy timer fade = 0; ShowWindow(SW_HIDE); KillTimer(nIDEvent); m_isDimming = false; } else { // Set window opacity &amp; update fade counter SetLayeredWindowAttributes(RGB(0,0,0), fade, LWA_ALPHA); fade -= FADE_STEP; } } else // fade in { if(fade &gt; TARGET_OPACITY) { // Fading finished - destroy timer &amp; update status fade = TARGET_OPACITY; // but first, let's be accurate. SetLayeredWindowAttributes(RGB(0,0,0), fade, LWA_ALPHA); KillTimer(nIDEvent); m_isDimming = true; } else { // Set window opacity &amp; update fade counter SetLayeredWindowAttributes(RGB(0,0,0), fade, LWA_ALPHA); fade += FADE_STEP; } } } } BOOL CDimWnd::OnEraseBkgnd(CDC* pDC) { // Fill with black CBrush backBrush(RGB(0, 0, 0)); CBrush* pOldBrush = pDC-&gt;SelectObject(&amp;backBrush); CRect rect; pDC-&gt;GetClipBox(&amp;rect); // Erase the area needed pDC-&gt;PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC-&gt;SelectObject(pOldBrush); return TRUE; } </code></pre> <p>Okay. As I said, this was thrown together fairly quickly and is in a rough state, but it should give you some code to work from, and a general idea of how (I think) timers are used in MFC. I am definitely not the right person to think anything about that, though :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload