Puede crear otra ventana, completamente negra, en la parte superior de la ventana que desea atenuar, y establecer la opacidad de la ventana negra con SetLayeredWindowAttributes. No tiene que ser negro, por supuesto, pero supongo que es el mejor color de atenuación.
EDIT: hackeado un ejemplo - pero tenga en cuenta que no soy un desarrollador de MFC, que suelen utilizar la API de Windows directamente. Parece que funciona bien, sin embargo. Here es un pastebin. Siéntase libre de agregar fade-ins, etc. usted mismo. También tenga en cuenta que esto atenúa toda la pantalla, tendrá que cambiar el tamaño de mi ventana de regulación si no desea este comportamiento. Ver los comentarios del código.
/**********************************************************************************************
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 & 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()->GetWindowRect(&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 & 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->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect); // Erase the area needed
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->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->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
CApp HelloApp;
ACTUALIZACIÓN:
Pirateé juntos algo más de código para usted, para manejar el desvanecimiento. Todavía no soy un desarrollador de MFC, y dejé el código en un estado "rudo" (poco manejo de errores, no muy robusto) para darte algo que hacer también. :) De todos modos, aquí hay una manera de hacerlo, que creo que es bastante limpio:
Para usarlo, hacer que su ventana principal contiene una ventana regulador
class CMainFrm : public CFrameWnd
{
CDimWnd* dimmer;
public:
CMainFrm()
{
// constructor code here ...
dimmer = new CDimWnd();
}
// rest of class ...
};
A continuación, se puede utilizar, por ejemplo, de esta manera:
dimmer->Show();
MessageBox(TEXT("Hello world"));
dimmer->Hide();
Alternativamente Creo que se puede poner este código (Show()
/Hide()
llamadas) en el constructor y el destructor del diálogo modal, si se quiere mantener el código allí. Si desea un "scope" -dim, como en el ejemplo que publicó, este código debería ir en el constructor & destructor de la clase CDimWnd, y necesitaría algo así como una variable de miembro estática para asegurar que solo un dimmer es ejecutándose a la vez (a menos que quiera usar una variable global).
Por la ventana dimmer - Hice esto:
CDimWnd.h
#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()
};
CDimWnd.cpp
#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->GetClientRect(&rc);
pParent->ClientToScreen(&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->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 => we want to fade out
if(m_isDimming)
{
if(fade < 0)
{
// Fading finished - hide window completely, update status & destroy timer
fade = 0;
ShowWindow(SW_HIDE);
KillTimer(nIDEvent);
m_isDimming = false;
}
else
{
// Set window opacity & update fade counter
SetLayeredWindowAttributes(RGB(0,0,0), fade, LWA_ALPHA);
fade -= FADE_STEP;
}
}
else
// fade in
{
if(fade > TARGET_OPACITY)
{
// Fading finished - destroy timer & 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 & 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->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect); // Erase the area needed
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;
}
bien. Como dije, esto fue lanzado bastante rápido y está en un estado difícil, pero debería darle algún código para trabajar, y una idea general de cómo (creo) los temporizadores se usan en MFC. Definitivamente no soy la persona adecuada para pensar en eso, aunque :)
En un primer momento, lo que está atenuado? ¿Puedes proporcionar una captura de pantalla del comportamiento deseado? –
Encontré esto en Google Images, es una página web que oscurece el resto de la página alrededor de un diálogo: http://www.irritatedvowel.com/pub/blog/UsingBlurBehindDialogsinSilverlight3Beta_13306/image.png - así, pero oscureciendo la ventana principal de una aplicación mientras el diálogo está activo. – AshleysBrain