2016-09-27 11 views
5

मुझे शीर्षक पट्टी के बिना एक विंडो चाहिए, लेकिन आकार बदलने योग्य फ्रेम और छाया के साथ। यह आसानी से WS_CAPTION को हटाकर और WS_THICKFRAME जोड़कर हासिल किया जा सकता है, हालांकि, विंडोज 10 के बाद, एक 6 पीएक्स सफेद गैर-क्लाइंट क्षेत्र है।रेजिज़ेबल सीमा के बिना टाइटलबार के बिना विंडो बनाएं और 6px सफेद पट्टी के बिना

निम्नलिखित कोड के साथ मैं एक खिड़की बना देता हूं और काले रंग के साथ सभी क्लाइंट क्षेत्र को पेंट करता हूं, खिड़की एक बाएं, दाएं और नीचे 6 पीएक्स पारदर्शी मार्जिन पाती है, हालांकि शीर्ष मार्जिन सफेद है।

#ifndef UNICODE 
#define UNICODE 
#endif 

#include <windows.h> 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) 
{ 
    // Register the window class. 
    const wchar_t CLASS_NAME[] = L"Sample Window Class"; 

    WNDCLASS wc = { }; 

    wc.lpfnWndProc = WindowProc; 
    wc.hInstance  = hInstance; 
    wc.lpszClassName = CLASS_NAME; 

    RegisterClass(&wc); 

    // Create the window. 

    HWND hwnd = CreateWindowEx(
     0,        // Optional window styles. 
     CLASS_NAME,      // Window class 
     L"", // Window text 
       0, 
     // Size and position 
     CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
     NULL,  // Parent window  
     NULL,  // Menu 
     hInstance, // Instance handle 
     NULL  // Additional application data 
     ); 

    ShowWindow(hwnd, nCmdShow); 

    LONG lStyle = GetWindowLong(hwnd, GWL_STYLE); 
    lStyle |= WS_THICKFRAME; 
    lStyle = lStyle & ~WS_CAPTION; 
    SetWindowLong(hwnd, GWL_STYLE, lStyle); 
    SetWindowPos(hwnd, NULL, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); 

    // Run the message loop. 

    MSG msg = { }; 
    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 0; 
} 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 

    case WM_PAINT: 
     { 
      PAINTSTRUCT ps; 
      HDC hdc = BeginPaint(hwnd, &ps); 


      // Paint everything black 
      FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOWTEXT)); 
      EndPaint(hwnd, &ps); 
     } 
     return 0; 

    } 
    return DefWindowProc(hwnd, uMsg, wParam, lParam); 
} 

रेंडर: image showing the problem

मैं सफेद धारी कैसे निकाल सकते हैं? मुझे यह संबंधित क्यूटी बग रिपोर्ट QTBUG-47543 भी मिली जो कि क्यूटी समस्या नहीं होने के कारण बंद कर दिया गया था, क्योंकि इसे win32 api के साथ पुन: उत्पन्न किया जा सकता है।

उत्तर

4

यह एक बग नहीं है। विंडोज 10 में बाएं/दाएं/नीचे की सीमाएं पारदर्शी हैं। शीर्ष सीमा पारदर्शी नहीं है। आपको इसे छोड़ देना चाहिए। शायद कोई शिकायत नहीं करेगा।

इसे बदलने के लिए, आपको गैर-क्लाइंट क्षेत्र को संशोधित करना होगा। विंडोज विस्टा और उससे ऊपर में यह मुश्किल है। संदर्भ के लिए Custom Window Frame Using DWM देखें।

  • ढूँढें सीमा मोटाई

  • उपयोग DwmExtendFrameIntoClientArea गैर ग्राहक क्षेत्र में अपारदर्शी रंग आकर्षित करने के लिए गैर-क्लाइंट क्षेत्र

  • उपयोग BeginBufferedPaint तक पहुँच प्राप्त करने

Windows 10 उदाहरण:

enter image description here

//requires Dwmapi.lib and UxTheme.lib 
#include <Windows.h> 
#include <Dwmapi.h> 

void my_paint(HDC hdc, RECT rc) 
{ 
    HBRUSH brush = CreateSolidBrush(RGB(0, 128, 0)); 
    FillRect(hdc, &rc, brush); 
    DeleteObject(brush); 
} 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    static RECT border_thickness; 

    switch (uMsg) 
    { 
    case WM_CREATE: 
    { 
     //find border thickness 
     SetRectEmpty(&border_thickness); 
     if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_THICKFRAME) 
     { 
      AdjustWindowRectEx(&border_thickness, GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL); 
      border_thickness.left *= -1; 
      border_thickness.top *= -1; 
     } 
     else if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_BORDER) 
     { 
      SetRect(&border_thickness, 1, 1, 1, 1); 
     } 

     MARGINS margins = { 0 }; 
     DwmExtendFrameIntoClientArea(hwnd, &margins); 
     SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); 
     break; 
    } 

    case WM_PAINT: 
    { 
     PAINTSTRUCT ps; 
     HDC hdc = BeginPaint(hwnd, &ps); 

     RECT rc = ps.rcPaint; 
     BP_PAINTPARAMS params = { sizeof(params), BPPF_NOCLIP | BPPF_ERASE }; 
     HDC memdc; 
     HPAINTBUFFER hbuffer = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, &params, &memdc); 

     my_paint(memdc, rc); 

     BufferedPaintSetAlpha(hbuffer, &rc, 255); 
     EndBufferedPaint(hbuffer, TRUE); 

     EndPaint(hwnd, &ps); 
     return 0; 
    } 

    case WM_NCACTIVATE: 
     return 0; 

    case WM_NCCALCSIZE: 
     if (lParam) 
     { 
      NCCALCSIZE_PARAMS* sz = (NCCALCSIZE_PARAMS*)lParam; 
      sz->rgrc[0].left += border_thickness.left; 
      sz->rgrc[0].right -= border_thickness.right; 
      sz->rgrc[0].bottom -= border_thickness.bottom; 
      return 0; 
     } 
     break; 

    case WM_NCHITTEST: 
    { 
     //do default processing, but allow resizing from top-border 
     LRESULT result = DefWindowProc(hwnd, uMsg, wParam, lParam); 
     if (result == HTCLIENT) 
     { 
      POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 
      ScreenToClient(hwnd, &pt); 
      if (pt.y < border_thickness.top) return HTTOP; 
     } 
     return result; 
    } 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 

    } 
    return DefWindowProc(hwnd, uMsg, wParam, lParam); 
} 

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int) 
{ 
    const wchar_t CLASS_NAME[] = L"Sample Window Class"; 

    WNDCLASS wc = {}; 
    wc.lpfnWndProc = WindowProc; 
    wc.hInstance = hInstance; 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.lpszClassName = CLASS_NAME; 
    RegisterClass(&wc); 

    CreateWindowEx(0, CLASS_NAME, NULL, 
     WS_VISIBLE | WS_THICKFRAME | WS_POPUP, 
     10, 10, 600, 400, NULL, NULL, hInstance, NULL); 

    MSG msg = {}; 
    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 0; 
} 

Windows Vista/7/8 उपयोग इस प्रक्रिया के बजाय साथ संगतता के लिए (विंडोज विस्टा, 7, 8 साथ संगतता के लिए अगले उदाहरण देखें)। यह बाएं/ऊपर/नीचे सीमाओं के साथ-साथ शीर्ष सीमा पर पेंट करेगा। इस विंडो का आकार सीमाओं के साथ, एक सरल आयत के रूप में दिखाई देगा:

enter image description here

//for Windows Vista, 7, 8, 10 
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    static RECT border_thickness; 

    switch (uMsg) 
    { 
    case WM_CREATE: 
    { 
     //find border thickness 
     SetRectEmpty(&border_thickness); 
     if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_THICKFRAME) 
     { 
      AdjustWindowRectEx(&border_thickness, GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL); 
      border_thickness.left *= -1; 
      border_thickness.top *= -1; 
     } 
     else if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_BORDER) 
     { 
      SetRect(&border_thickness, 1, 1, 1, 1); 
     } 

     MARGINS margins = { 0 }; 
     DwmExtendFrameIntoClientArea(hwnd, &margins); 
     SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); 
     break; 
    } 

    case WM_PAINT: 
    { 
     PAINTSTRUCT ps; 
     HDC hdc = BeginPaint(hwnd, &ps); 

     RECT rc = ps.rcPaint; 
     BP_PAINTPARAMS params = { sizeof(params), BPPF_NOCLIP | BPPF_ERASE }; 
     HDC memdc; 
     HPAINTBUFFER hbuffer = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, &params, &memdc); 

     my_paint(memdc, rc); 

     BufferedPaintSetAlpha(hbuffer, &rc, 255); 
     EndBufferedPaint(hbuffer, TRUE); 

     EndPaint(hwnd, &ps); 
     return 0; 
    } 

    case WM_NCACTIVATE: 
     return 0; 

    case WM_NCCALCSIZE: 
     if (lParam) 
      return 0; 

    case WM_NCHITTEST: 
    { 
     POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 
     ScreenToClient(hwnd, &pt); 
     RECT rc; 
     GetClientRect(hwnd, &rc); 
     enum {left=1, top=2, right=4, bottom=8}; 
     int hit = 0; 
     if (pt.x < border_thickness.left) hit |= left; 
     if (pt.x > rc.right - border_thickness.right) hit |= right; 
     if (pt.y < border_thickness.top) hit |= top; 
     if (pt.y > rc.bottom - border_thickness.bottom) hit |= bottom; 

     if (hit & top && hit & left) return HTTOPLEFT; 
     if (hit & top && hit & right) return HTTOPRIGHT; 
     if (hit & bottom && hit & left) return HTBOTTOMLEFT; 
     if (hit & bottom && hit & right) return HTBOTTOMRIGHT; 
     if (hit & left) return HTLEFT; 
     if (hit & top) return HTTOP; 
     if (hit & right) return HTRIGHT; 
     if (hit & bottom) return HTBOTTOM; 

     return HTCLIENT; 
    } 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 

    } 
    return DefWindowProc(hwnd, uMsg, wParam, lParam); 
} 
+0

आपके Win7 compat उदाहरण में फ्रेम के चारों ओर छाया नहीं है, किसी को पाने के लिए कोई तरीका नहीं है? –

+1

आप 'WNDCLASS' पंजीकरण के लिए' wc.style = CS_DROPSHADOW; 'जोड़ सकते हैं। यह दाएं तरफ और नीचे की तरफ छाया को छोड़ देता है। उदाहरण के लिए जीडीआई + के साथ, इसके चारों ओर छाया जोड़ने के लिए मैन्युअल रूप से किया जाना है। –

+0

कभी-कभी मुझे अभी भी सफेद पट्टी दिखाई देती है। WM_NCACTIVATE को पकड़ने से अधिकांश घटनाएं ठीक हो जाती हैं, लेकिन कभी-कभी खिड़की को वास्तव में तेज़ी से ले जाने पर यह सफेद पट्टी हो जाती है। मुझे कोई अन्य विंडोज़ ईवेंट ब्लॉक करना चाहिए? –

0

बस इस एक छोटे से पर विस्तार करने के लिए; सफेद पट्टी को हटाने के लिए किसी को केवल NCCALCSIZE में पहले संदर्भ से संबंधित मान को हटाना होगा। pywin32 कोड होगा:

if msg == WM_NCCALCSIZE: 
     if wParam: 
      res = CallWindowProc(
       wndProc, hWnd, msg, wParam, lParam 
      ) 
      sz = NCCALCSIZE_PARAMS.from_address(lParam) 
      sz.rgrc[0].top -= 6 # remove 6px top border! 
      return res 
संबंधित मुद्दे