LRESULT CFrameHolder::OnNcPaint(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { RecalculateFrameSizes(); if (!gpSet->isTabsInCaption) { LRESULT lRc = DefWindowProc(hWnd, uMsg, wParam, lParam); return lRc; } FrameDrawStyle fdt = gpConEmu->DrawType(); if (fdt == fdt_Aero || fdt == fdt_Win8) { LRESULT lRc = DefWindowProc(hWnd, uMsg, wParam, lParam); //TODO: Может быть на "стекле" сразу рисовать, а не в WM_PAINT? return lRc; } if (!gpSet->isTabs) { return DefWindowProc(hWnd, uMsg, wParam, lParam); } RECT dirty_box, dirty, wr = {}, tr = {}, cr = {}, xorRect; BOOL fRegionOwner = FALSE; HDC hdc; HRGN hrgn = (HRGN)wParam; GetWindowRect(hWnd, &wr); CalculateCaptionPosition(wr, &cr); CalculateTabPosition(wr, cr, &tr); // --- Регион формируем всегда сами, иначе в некоторых случаях (XP+ Theming) // --- при выезжании окна из-за пределов экрана (обратно в видимую область) // --- сильно мелькает текст в заголовке //Create a region which covers the whole window. This //must be in screen coordinates //if(TRUE || hrgn == (HRGN)1 || hrgn == NULL) { hrgn = CreateRectRgnIndirect(&wr); dirty_box = wr; fRegionOwner = TRUE; //#ifdef _DEBUG // wchar_t szDbg[255]; // wsprintf(szDbg, L"CFrameHolder::OnNcPaint - New region({%ix%i}-{%ix%i})\n", wr.left,wr.top,wr.right,wr.bottom); // OutputDebugStringW(szDbg); //#endif } //else //{ // GetRgnBox((HRGN)wParam, &dirty_box); // #ifdef _DEBUG // wchar_t szDbg[255]; // wsprintf(szDbg, L"CFrameHolder::OnNcPaint - Existing region({%ix%i}-{%ix%i})\n", dirty_box.left,dirty_box.top,dirty_box.right,dirty_box.bottom); // OutputDebugStringW(szDbg); // #endif //} xorRect = tr; xorRect.top = cr.top; if (gpConEmu->DrawType() == fdt_Aero) { } else if (gpConEmu->DrawType() == fdt_Themed) { xorRect.left = cr.left; xorRect.right = cr.right; } else { xorRect.left = cr.left; //xorRect.right = cr.right; } OffsetRect(&xorRect, wr.left, wr.top); if (IntersectRect(&dirty, &dirty_box, &xorRect)) { // This must be in screen coordinates HRGN hrgn1 = CreateRectRgnIndirect(&xorRect); //Cut out a button-shaped hole CombineRgn(hrgn, hrgn, hrgn1, RGN_XOR); DeleteObject(hrgn1); } //#ifdef _DEBUG //else //{ // OutputDebugStringW(L"CFrameHolder::OnNcPaint --- IntersectRect failed\n"); //} //#endif //if (!mb_NcAnimate) DefWindowProc(hWnd, uMsg, (WPARAM)hrgn, lParam); //#ifdef _DEBUG // Sleep(150); //#endif // Собственно отрисовка табов hdc = GetWindowDC(hWnd); //HRGN hdcrgn = CreateRectRgn(cr.left, cr.top, cr.right, tr.bottom); //hdc = GetDCEx(hWnd, hdcrgn, DCX_INTERSECTRGN); PaintDC dc = {}; gpConEmu->BeginBufferedPaint(hdc, cr, dc); gpConEmu->mp_TabBar->PaintTabs(dc, cr, tr); gpConEmu->EndBufferedPaint(dc, TRUE); //if (mb_WasGlassDraw && gpConEmu->isZoomed()) //{ // //mb_WasGlassDraw = FALSE; // // Какой-то странный глюк DWM. При отключении Glass несколько верхних строк // // клиентской области оказываются "разрушенными" - у них остается атрибут "прозрачности" // // хотя прозрачность (Glass) уже отключена. В результате эти строки - белесые // BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER)}; // bi.biWidth = cr.right-cr.left+1; // bi.biHeight = GetFrameHeight()+1; // bi.biPlanes = 1; // bi.biBitCount = 32; // COLORREF *pPixels = NULL; // HDC hdcPaint = CreateCompatibleDC(hdc); // HBITMAP hbmp = CreateDIBSection(hdcPaint, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pPixels, NULL, 0); // HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcPaint, hbmp); // //memset(pPixels, 0xFF, bi.biWidth*bi.biHeight*4); // int i = 0; // for (int y = 0; y < bi.biHeight; y++) // { // for (int x = 0; x < bi.biWidth; x++) // { // pPixels[i++] = 0xFF000000; // } // } // BitBlt(hdc, cr.left, tr.bottom, bi.biWidth, bi.biHeight, hdcPaint, 0, 0, SRCCOPY); // SelectObject(hdcPaint, hOldBmp); // DeleteObject(hbmp); // DeleteDC(hdcPaint); //} ReleaseDC(hWnd, hdc); if(fRegionOwner) DeleteObject(hrgn); return 0; }
LRESULT CFrameHolder::OnPaint(HWND hWnd, BOOL abForceGetDc) { HDC hdc; PAINTSTRUCT ps = {0}; RECT wr, cr, tr; RecalculateFrameSizes(); hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &wr); if (gpSet->isStatusBarShow) { int nHeight = gpSet->StatusBarHeight(); if (nHeight < (wr.bottom - wr.top)) { RECT rcStatus = {wr.left, wr.bottom - nHeight, wr.right, wr.bottom}; gpConEmu->mp_Status->PaintStatus(hdc, rcStatus); wr.bottom = rcStatus.top; } } cr = wr; if (gpConEmu->DrawType() == fdt_Aero) { int nOffset = gpConEmu->GetDwmClientRectTopOffset(); // "Рамка" расширена на клиентскую область, поэтому // нужно зарисовать заголовок черной кистью, иначе идет // искажение цвета для кнопок Min/Max/Close if (gpSet->isTabs && gpSet->isTabsInCaption) { RECT captrect; CalculateCaptionPosition(cr, &captrect); CalculateTabPosition(cr, captrect, &tr); gpConEmu->mp_TabBar->PaintTabs(hdc, captrect, tr); mb_WasGlassDraw = TRUE; } cr.top += nOffset; } int nWidth = (cr.right-cr.left); int nHeight = (cr.bottom-cr.top); WARNING("Пока табы рисуем не сами и ExtendDWM отсутствует - дополнительные изыски с временным DC не нужны"); if (!gpSet->isTabsInCaption) { OnPaintClient(hdc, nWidth, nHeight); } else // Создадим временный DC, для удобства отрисовки в Glass-режиме и для фикса глюка DWM(?) см.ниже // В принципе, для режима Win2k/XP временный DC можно не создавать, если это будет тормозить { HDC hdcPaint = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight); HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcPaint, hbmp); OnPaintClient(hdcPaint, nWidth, nHeight); if ((gpConEmu->DrawType() == fdt_Aero) || !(mb_WasGlassDraw && gpConEmu->isZoomed())) { BitBlt(hdc, cr.left, cr.top, nWidth, nHeight, hdcPaint, 0, 0, SRCCOPY); } else { //mb_WasGlassDraw = FALSE; // Какой-то странный глюк DWM. При отключении Glass несколько верхних строк // клиентской области оказываются "разрушенными" - у них остается атрибут "прозрачности" // хотя прозрачность (Glass) уже отключена. В результате эти строки - белесые BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER)}; bi.biWidth = cr.right-cr.left+1; bi.biHeight = GetFrameHeight()+1; bi.biPlanes = 1; bi.biBitCount = 32; COLORREF *pPixels = NULL; HDC hdcTmp = CreateCompatibleDC(hdc); HBITMAP hTmp = CreateDIBSection(hdcTmp, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pPixels, NULL, 0); if (hTmp == NULL) { _ASSERTE(hTmp == NULL); BitBlt(hdc, cr.left, cr.top, nWidth, nHeight, hdcPaint, 0, 0, SRCCOPY); } else { HBITMAP hOldTmp = (HBITMAP)SelectObject(hdcTmp, hTmp); BitBlt(hdcTmp, 0, 0, bi.biWidth, bi.biHeight, hdcPaint, 0, 0, SRCCOPY); int i = 0; for (int y = 0; y < bi.biHeight; y++) { for (int x = 0; x < bi.biWidth; x++) { pPixels[i++] |= 0xFF000000; } } BitBlt(hdc, cr.left, cr.top, bi.biWidth, bi.biHeight, hdcTmp, 0, 0, SRCCOPY); if (nHeight > bi.biHeight) BitBlt(hdc, cr.left, cr.top+bi.biHeight, nWidth, nHeight-bi.biHeight, hdcPaint, 0, bi.biHeight, SRCCOPY); SelectObject(hdcTmp, hOldTmp); DeleteObject(hbmp); } DeleteDC(hdcTmp); } SelectObject(hdcPaint, hOldBmp); DeleteObject(hbmp); DeleteDC(hdcPaint); } EndPaint(hWnd, &ps); return 0; }