2009-07-18 11 views
10

पर WM_NCPAINT "ब्रेक" डीडब्लूएम ग्लास प्रतिपादन को संभालना मैं उपयोगकर्ता सेटिंग के आधार पर एरो/ग्लास और एक कस्टम रेंडर फ्रेम (WM_NCPAINT को संभालने) के बीच वैकल्पिक विंडो बनाने की कोशिश कर रहा हूं। (विंडोज विस्टा)।Vista/Aero

DwmComposition सक्षम है। मेरा ऐप ग्लास फ्रेम के साथ आता है, लेकिन जैसे ही मैं कस्टम WM_NCPAINT कोडपैथ ट्रिगर करने के लिए सेटिंग टॉगल करता हूं, तो DefWindowProc के WM_NCPAINT हैंडलिंग का उपयोग करने के लिए वापस टॉगल करें, मूल फ्रेम अब "Vista Basic" शैली में फंस गया है - यह है अब पारदर्शी नहीं है और कैप्शन बटन सामान्य एयरो/ग्लास वाले से अलग दिखते हैं।

मैंने विंडो शैली को बदलने के लिए विंडो को SWP_FRAMECHANGED भेजने से विंडो को पोक करने के हर तरीके की कोशिश की है, फिर इसे वापस बदलकर, इसे छुपाएं, आदि, लेकिन सभी को कोई फायदा नहीं हुआ। ऐसा लगता है जैसे मैं WM_NCPAINT को DefWindowProc को संदर्भित करने के बजाए ग्लास विंडो के लिए संभालता हूं, मेरी खिड़की हमेशा "टूटा" है।

मुझे एमएसडीएन (कोड डॉट एमएसडीएन डॉट माइक्रोसॉफ्ट डॉट कॉम स्लैश क्रोम) पर एक सी #/डब्ल्यूपीएफ उदाहरण मिला जो यह इंगित करता था कि WM_NCPAINT को संभालने से रोकने के लिए बस एक की आवश्यकता होती है और ग्लास वापस आ जाएगा, लेकिन ऐसा लगता है कि यह काम नहीं कर रहा है मेरा अपना ऐप

क्या इस राज्य को साफ-सुथरा करने का कोई तरीका है? मेरे कोड C++ है और यहाँ रहता है:

http://bengoodger.dreamhosters.com/software/chrome/dwm/

#include <windows.h> 
#include <dwmapi.h> 

static const wchar_t* kWindowClass = L"BrokenGlassWindow"; 
static const wchar_t* kWindowTitle = 
    L"BrokenGlass - Right click client area to toggle frame type."; 
static const int kGlassBorderSize = 50; 
static const int kNonGlassBorderSize = 40; 

static bool g_glass = true; 
bool IsGlass() { 
    BOOL composition_enabled = FALSE; 
    return DwmIsCompositionEnabled(&composition_enabled) == S_OK && 
     composition_enabled && g_glass; 
} 
void SetIsGlass(bool is_glass) { 
    g_glass = is_glass; 
} 

void ToggleGlass(HWND hwnd) { 
    SetWindowPos(hwnd, NULL, 0, 0, 0, 0, 
       SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); 
    RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 
} 

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM w_param, 
         LPARAM l_param) { 
    PAINTSTRUCT ps; 
    HDC hdc; 
    RECT wr; 
    HBRUSH br; 
    RECT* nccr = NULL; 
    RECT dirty; 
    RECT dirty_box; 
    MARGINS dwmm = {0}; 
    WINDOWPOS* wp = NULL; 

    switch (message) { 
    case WM_CREATE: 
     SetCursor(LoadCursor(NULL, IDC_ARROW)); 
     break; 
    case WM_ERASEBKGND: 
     return 1; 
    case WM_PAINT: 
     hdc = BeginPaint(hwnd, &ps); 
     GetClientRect(hwnd, &wr); 
     br = GetSysColorBrush(IsGlass() ? COLOR_APPWORKSPACE : COLOR_WINDOW); 
     FillRect(hdc, &wr, br); 
     EndPaint(hwnd, &ps); 
     break; 
    case WM_NCPAINT: 
     if (IsGlass()) 
     return DefWindowProc(hwnd, message, w_param, l_param); 
     GetWindowRect(hwnd, &wr); 
     if (!w_param|| w_param == 1) { 
     dirty = wr; 
     dirty.left = dirty.top = 0; 
     } else { 
     GetRgnBox(reinterpret_cast<HRGN>(w_param), &dirty_box); 
     if (!IntersectRect(&dirty, &dirty_box, &wr)) 
      return 0; 
     OffsetRect(&dirty, -wr.left, -wr.top); 
     } 
     hdc = GetWindowDC(hwnd); 
     br = CreateSolidBrush(RGB(255,0,0)); 
     FillRect(hdc, &dirty, br); 
     DeleteObject(br); 
     ReleaseDC(hwnd, hdc); 
     break; 
    case WM_NCACTIVATE: 
     // Force paint our non-client area otherwise Windows will paint its own. 
     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 
     break; 
    case WM_NCCALCSIZE: 
     nccr = w_param ? &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] 
        : reinterpret_cast<RECT*>(l_param); 
     nccr->bottom -= IsGlass() ? kGlassBorderSize : kNonGlassBorderSize; 
     nccr->right -= IsGlass() ? kGlassBorderSize : kNonGlassBorderSize; 
     nccr->left += IsGlass() ? kGlassBorderSize : kNonGlassBorderSize; 
     nccr->top += IsGlass() ? kGlassBorderSize : kNonGlassBorderSize; 
     return WVR_REDRAW; 
    case WM_RBUTTONDOWN: 
     SetIsGlass(!g_glass); 
     ToggleGlass(hwnd); 
     break; 
    case 0x31E: // WM_DWMCOMPOSITIONCHANGED: 
     ToggleGlass(hwnd); 
     break;  
    case 0xAE: // WM_NCUAHDRAWCAPTION: 
    case 0xAF: // WM_NCUAHDRAWFRAME: 
     return IsGlass() ? DefWindowProc(hwnd, message, w_param, l_param) : 0; 
    case WM_WINDOWPOSCHANGED: 
     dwmm.cxLeftWidth = kGlassBorderSize; 
     dwmm.cxRightWidth = kGlassBorderSize; 
     dwmm.cyTopHeight = kGlassBorderSize; 
     dwmm.cyBottomHeight = kGlassBorderSize; 
     DwmExtendFrameIntoClientArea(hwnd, &dwmm); 
     break; 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hwnd, message, w_param, l_param); 
    } 
    return 0; 
} 

ATOM RegisterClazz(HINSTANCE instance) { 
    WNDCLASSEX wcex = {0}; 
    wcex.cbSize = sizeof(wcex); 
    wcex.style = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = WndProc; 
    wcex.hInstance = instance; 
    wcex.lpszClassName = kWindowClass; 
    return RegisterClassEx(&wcex); 
} 

int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int show_command) { 
    RegisterClazz(instance); 
    HWND hwnd = CreateWindow(kWindowClass, kWindowTitle, WS_OVERLAPPEDWINDOW, 
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, 
          instance, NULL); 
    ShowWindow(hwnd, show_command); 

    MSG msg; 
    while (GetMessage(&msg, NULL, 0, 0)) { 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
    } 
    return static_cast<int>(msg.wParam); 
} 

उत्तर

14

जब एयरो/ग्लास और अपने कस्टम प्रदान की गई यह फ्रेम के बीच टॉगल आप स्पष्ट रूप से गैर-क्लाइंट क्षेत्र प्रतिपादन नीति को नियंत्रित करने के निम्न का उपयोग कर सकते हैं:

DWMNCRENDERINGPOLICY policy = DWMNCRP_ENABLED; // DWMNCRP_DISABLED to toggle back 
DwmSetWindowAttribute(hwnd, 
         DWMWA_NCRENDERING_POLICY, 
         (void*)&policy, 
         sizeof(DWMNCRENDERINGPOLICY)); 
+0

मीठे, यह काम किया। मैंने पहले यह कोशिश की थी, लेकिन पॉलिसी की भावना उलटी हुई थी। धन्यवाद! –