2010-10-31 19 views
5

दिखाते समय मुख्य विंडो मंद करें मेरे पास एक मानक मानक एमएफसी एप्लिकेशन है जिसमें मुख्य विंडो होती है, और कभी-कभी मोडल डायलॉग लाती है। जैसा कि हम सभी जानते हैं कि इसे बंद होने तक एक मॉडल संवाद के बाहर कुछ भी नहीं किया जा सकता है।एमएफसी - मोडल डायलॉग

इसलिए, एक अच्छी यूआई सुविधा डायलॉग के पीछे की मुख्य विंडो को "मंद" करना है, यह देखने के लिए कि आप इसका उपयोग तब तक नहीं कर सकते जब तक आप मोडल संवाद के साथ नहीं कर लेते। कुछ वेब ऐप्स और जावा/मैक ऐप्स ऐसा करते हैं, लेकिन मैंने इसे पारंपरिक C++/MFC एप्लिकेशन में कभी नहीं देखा है। मैं इसे एक कोशिश देना चाहता हूं, भले ही यह मंच के लिए असामान्य है।

यह कैसे किया जा सकता है?

// pMainFrame is available as a pointer to the CWnd of the main window 
CMyDialog dialog; 
dialog.DoModal(); // invoke modal dialog; returns after dialog closed 

वहाँ एक आसान तरीका) खिड़की किसी भी DoModal (पहले मंद हो और बाद में पुनर्स्थापित करने के लिए है: मैं आवेदन में कई मोडल संवाद, इस पद्धति में प्रयोग किया जाता है? मैं विजुअल स्टूडियो 2010 का उपयोग कर रहा हूं यदि अद्यतन एमएफसी में ऐसी कोई विशेषताएं हैं जो मदद कर सकती हैं।

संपादित करें: मैंने ऑस्टीन के उत्तर के आधार पर एक समाधान पोस्ट किया है, लेकिन अगर कोई इसमें सुधार कर सकता है तो मैं एक उदारता शुरू कर रहा हूं - खासकर एक चिकनी फीका/फीका हुआ।

+0

सबसे पहले, क्या मंद हो जाता है? क्या आप वांछित व्यवहार का एक स्क्रीनशॉट आपूर्ति कर सकते हैं? –

+0

इसे Google छवियों से बाहर पाया गया, यह एक वेब पेज है जो एक संवाद के चारों ओर शेष पृष्ठ को मंद करता है: http://www.irritatedvowel.com/pub/blog/UsingBlurBehindDialogsinSilverlight3Beta_13306/image।पीएनजी - ऐसा ही है लेकिन एक संवाद के दौरान एक आवेदन की मुख्य खिड़की को कम कर रहा है। – AshleysBrain

उत्तर

14

आप खिड़की के शीर्ष पर एक और विंडो, पूरी तरह से काला बना सकते हैं, जिसे आप मंद करना चाहते हैं, और SetLayeredWindowAttributes के साथ ब्लैक विंडो की अस्पष्टता सेट करें। यह निश्चित रूप से काला नहीं होना चाहिए, लेकिन मुझे लगता है कि यह सबसे अच्छा धुंधला रंग है।

संपादित करें: मैंने एक उदाहरण को एक साथ हैक किया - लेकिन ध्यान दें कि मैं एक एमएफसी डेवलपर नहीं हूं, मैं आमतौर पर सीधे विंडोज एपीआई का उपयोग करता हूं। ऐसा लगता है कि ठीक है, यद्यपि। Here एक पेस्टबिन है। अपने आप को फीड-इन्स इत्यादि जोड़ने के लिए स्वतंत्र महसूस करें। यह भी ध्यान रखें कि यह पूरी स्क्रीन मंद हो जाती है, अगर आपको यह व्यवहार नहीं चाहिए तो आपको मेरी डमीिंग विंडो का आकार बदलना होगा। कोड टिप्पणियां देखें।

/********************************************************************************************** 

    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; 

अद्यतन:

मैं एक साथ आप के लिए कुछ और कोड को हैक कर लिया, लुप्त होती संभालने के लिए। मैं अभी भी कोई एमएफसी देव नहीं हूं, और मैंने कुछ भी करने के लिए आपको "मोटा" राज्य (थोड़ा त्रुटि प्रबंधन, बहुत मजबूत नहीं) में कोड छोड़ा। :) वैसे भी, यहाँ एक तरह से यह करने के लिए मुझे लगता है कि काफी साफ है,:

इसके इस्तेमाल के लिये अपने मुख्य विंडो अधिक धुंधला खिड़की

class CMainFrm : public CFrameWnd 
{  
    CDimWnd* dimmer; 

public: 
    CMainFrm() 
    { 
     // constructor code here ... 
     dimmer = new CDimWnd();   
    } 

// rest of class ... 

}; 

यह तो जैसे इस्तेमाल किया जा सकता शामिल कर इस तरह:

dimmer->Show(); 
MessageBox(TEXT("Hello world")); 
dimmer->Hide(); 

वैकल्पिक रूप से मैं तुम्हें तुम वहाँ कोड रखना चाहते हैं, निर्माता और मॉडल संवाद का नाशक में इस कोड (Show()/Hide() कॉल) डाल सकता है लगता है। यदि आप "स्कोप" -डिम चाहते हैं, जैसे आपके द्वारा पोस्ट किए गए उदाहरण में, इस कोड को सीडीआईएमडब्ल्यूडी कक्षा के निर्माता & विनाशक में जाना होगा, और आपको एक स्थिर सदस्य चर की तरह कुछ चाहिए ताकि यह सुनिश्चित किया जा सके कि केवल एक dimmer एक समय में चल रहा है (जब तक कि आप एक वैश्विक चर का उपयोग नहीं करना चाहते हैं)।

CDimWnd: -

मद्धम खिड़की के लिए मैं ऐसा किया।ज

#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; 
} 

ठीक है। जैसा कि मैंने कहा था, यह काफी तेजी से फेंक दिया गया था और किसी न किसी स्थिति में है, लेकिन इसे आपको काम करने के लिए कुछ कोड देना चाहिए, और एमएफसी में टाइम्स का उपयोग करने के बारे में एक सामान्य विचार है। मैं निश्चित रूप से उस बारे में कुछ भी सोचने का सही व्यक्ति नहीं हूं, हालांकि :)

+0

* मैं आमतौर पर सीधे विंडोज एपीआई का उपयोग करता हूं * - यह दिखाता है;) एमएफसी में, विंडो निर्माण कन्स्ट्रक्टर में नहीं जाता है लेकिन अलग है। वैसे भी, एक नमूना खांसी के लिए +1 jsut। – peterchen

+0

यह वास्तव में इस विशिष्ट मामले के लिए कन्स्ट्रक्टर में प्रारंभिकरण डालने के लिए उपयोगी है - फिर आपके पास 'स्कोप्ड विंडो डिमर' है जिसके लिए केवल एक पंक्ति की आवश्यकता होती है जिसे 'सीडीआईएमडब्ल्यूडी' को दायरे में मंद करने के लिए घोषित किया जाता है। – AshleysBrain

3

मैंने ऑस्टीन के जवाब को स्वीकार कर लिया है, क्योंकि इससे मुझे समाधान हुआ, लेकिन मैंने सोचा कि मैं अपने संशोधन पोस्ट करूंगा। मुझे इसे मेरे लिए काम करने के लिए थोड़ा सा संशोधित करना पड़ा, इसलिए यह किसी और के लिए उपयोगी हो सकता है।

रिकॉर्ड के लिए, डाimming अच्छी तरह से काम करता है, लेकिन यह अपेक्षाकृत प्राकृतिक नहीं दिखता है। एक ऐसे एप्लिकेशन में जो अक्सर संवाद लाता है, डाइमिंग मुख्य विंडो को चालू और बंद करने की नियमितता में विचलित हो जाती है। समझौता करने के लिए, मैंने डमीिंग को काफी सूक्ष्म (लगभग 25% अस्पष्टता) बना दिया है जो धीरे-धीरे सक्रिय संवाद को हाइलाइट करता है; तत्काल डाimming अभी भी थोड़ा विचलित है, लेकिन मुझे यकीन नहीं है कि इसे आसानी से कैसे फीका या फीका करना है, खासकर जब स्कॉप्ड किया जाए।

इसके अलावा, मैं यूआई विशेषज्ञ नहीं हूं, लेकिन डमीन ने मुझे एक तरह का इंप्रेशन दिया कि संवाद इसके पीछे की खिड़की सामग्री से कम था। इसने एप्लिकेशन में जो काम कर रहा था उससे थोड़ा अलग महसूस किया, भले ही संवाद सीधे उस सामग्री में हेरफेर कर रहे हों। यह एक और व्याकुलता हो सकती है।

यहाँ यह वैसे भी है: CDimWnd.cpp

CDimWnd.h

// Dim the application main window over a scope. Creates dimmer window in constructor. 
class CDimWnd : public CFrameWnd 
{    
public: 
    CDimWnd(); 
    BOOL OnEraseBkgnd(CDC* pDC); 

    ~CDimWnd(); 

protected: 
    DECLARE_MESSAGE_MAP() 
}; 

#include "stdafx.h" 
#include "CDimWnd.h" 
#include "MainFrm.h" 

BEGIN_MESSAGE_MAP(CDimWnd, CFrameWnd) 
    ON_WM_ERASEBKGND() 
END_MESSAGE_MAP() 

// For preventing two dimmer windows ever appearing 
bool is_dimmer_active = false; 

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, 
    // or if there is already dimming happening. 
    if (pParent != NULL && !is_dimmer_active) 
    { 
     // 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); 

     // Bring in front of main window. 
     BringWindowToTop(); 

     // Apply 25% opacity 
     SetLayeredWindowAttributes(RGB(0,0,0), 64, LWA_ALPHA); 

     // Show the dimmer window 
     ShowWindow(SW_SHOW); 

     is_dimmer_active = true; 
    } 
} 

CDimWnd::~CDimWnd() 
{ 
    is_dimmer_active = false; 
} 

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; 
} 

प्रयोग मृत सरल है: क्योंकि CDimWnd अपने निर्माता में ही बनाता है, आपको बस इतना करना हैजोड़ेंसंवाद वर्ग के सदस्य के रूप में, और यह मुख्य विंडो को स्वचालित रूप से मंद करता है, भले ही आप से संवाद कहां से कॉल करें।

तुम भी प्रणाली मोडल संवाद धुंधला करने के लिए एक दायरे के भीतर इसका इस्तेमाल कर सकते हैं:

{ 
    CDimWnd dimmer; 
    MessageBox(...); 
} 
+0

लुप्तप्राय के लिए, आप कन्स्ट्रक्टर/विनाशक में टाइमर बना सकते हैं जो धीरे-धीरे अस्पष्टता को बढ़ाता/घटाता है। जब तक आप इसे अलग करने के लिए एक अलग धागा नहीं चाहते हैं, तो फीका बहुत तेज़ होना होगा। – Oystein

+0

यही बात है, फीका संवाद की उपस्थिति में देरी नहीं करनी चाहिए। क्या यह एक ही समय हो सकता है क्योंकि मोडल संवाद अपने एरो फीड-इन संक्रमण के साथ प्रकट होता है? यदि एक मोडल संवाद चल रहा है तो क्या टाइमर अभी भी चलाएगा? – AshleysBrain

+0

अंतिम टिप्पणी को छोड़ दें। यदि आप एक विंडोज टाइमर पंजीकृत करते हैं, तो आपको एक टिक इवेंट प्राप्त होगा। यदि आप ईवेंट हैंडलर में लुप्तप्राय करते हैं, तो यह अन्य संवादों से स्वतंत्र हो जाएगा और कुछ भी निष्पादन में देरी नहीं करेगा। – Oystein

2

इसे करने में मुझे रोक नहीं सकता है।

यह जोड़ा गया टाइमर के साथ आपका कोड है और एक फीका/फीका आउट लागू किया गया है। इसके अलावा मैं अस्पष्ट ब्लॉक के लिए काले रंग की बजाय मध्य भूरे रंग का उपयोग करने के लिए बदल गया।

आप स्थिरांक को ट्विक कर सकते हैं जो अवधि को बढ़ाकर या दर में वृद्धि करके इसे आसान बनाने के लिए फीका को नियंत्रित कर सकते हैं। प्रयोग मुझे पता चलता है कि 10 हर्ट्ज की दर मेरे लिए चिकनी है, लेकिन YMMV

// DimWnd.h : header file 
#pragma once 

class CDimWnd : public CFrameWnd 
{ 
public: 
    CDimWnd(class CWnd * pParent); 
    virtual ~CDimWnd(); 
    BOOL OnEraseBkgnd(CDC* pDC); 
    int opacity, opacity_increment; 
protected: 
    DECLARE_MESSAGE_MAP() 

public: 
    afx_msg void OnTimer(UINT_PTR nIDEvent); 
    void fadeOut(); 
}; 

// DimWnd.cpp : implementation file 
// 

#include "stdafx.h" 
#include "dimmer.h" 
#include "DimWnd.h" 
#include "MainFrm.h" 
#include <math.h> 

const int TIMER_ID = 111; 

// For preventing two dimmer windows ever appearing 
bool is_dimmer_active = false; 

// constants to control the fade. 
int ticks_per_second = 1000; // ms 
int start_opacity  = 44; // 20% 
int max_opacity  = 220; // 0->255 
double fade_in_duration = 4; // seconds to fade in (appear) 
double fade_out_duration = 0.2; // seconds to fade out (disappear) 
int rate    = 100; // Timer rate (ms 


CDimWnd::CDimWnd(CWnd * pParent) 
{ 
    // Don't do anything if the main frame doesn't appear to be there, 
    // or if there is already dimming happening. 
    if (pParent != NULL && !is_dimmer_active) 
    { 
     // 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); 

     // Bring in front of main window. 
     BringWindowToTop(); 

     // Show the dimmer window 
     ShowWindow(SW_SHOW); 


     double increment_per_second = ((max_opacity - start_opacity)/fade_in_duration); 
     opacity_increment = ceil( increment_per_second/(ticks_per_second/rate)) ; 

     is_dimmer_active = true; 
     opacity = start_opacity; 

     SetLayeredWindowAttributes(RGB(0,0,0), opacity, LWA_ALPHA); 

     SetTimer(TIMER_ID, rate,NULL); 

    } 
} 

CDimWnd::~CDimWnd() 
{ 
    fadeOut(); // fade the window out rather than just disappearing. 
    is_dimmer_active = false; 
} 

void CDimWnd::fadeOut() 
{ 
    // can't use timers as may be in the process of being destroyed so make it quick.. 

    double increment_per_second = ((opacity - start_opacity)/fade_out_duration); 
    opacity_increment = ceil( increment_per_second/(ticks_per_second/rate)) ; 

    while(opacity > start_opacity) 
    { 
     opacity -= opacity_increment; 
     SetLayeredWindowAttributes(RGB(0,0,0), opacity, LWA_ALPHA); 
     Sleep(100); 
    } 
} 

BOOL CDimWnd::OnEraseBkgnd(CDC* pDC) 
{ 
    // Fill with midgray 
    CBrush backBrush(RGB(128,128,128)); 
    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() 
    ON_WM_TIMER() 
END_MESSAGE_MAP() 

void CDimWnd::OnTimer(UINT_PTR nIDEvent) 
{ 
    if (opacity >= max_opacity) 
    { 
     // stop the timer when fade in finished. 
     KillTimer(TIMER_ID); 
     return; 
    } 

    opacity += opacity_increment; 
    SetLayeredWindowAttributes(RGB(0,0,0), opacity, LWA_ALPHA); 

    CFrameWnd::OnTimer(nIDEvent); 
} 
+0

को पा सकते हैं ऐसा करने के लिए एक साफ तरीका लगता है जब तक आपको केवल स्कोप मॉडल की आवश्यकता होती है, और लंबे समय तक फीका नहीं होना चाहिए। यह निश्चित रूप से मेरे संस्करण से आसान है :) – Oystein

संबंधित मुद्दे