Пример #1
0
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;
}
Пример #2
0
void CFrameHolder::InitFrameHolder()
{
	mb_Initialized = TRUE;
	RecalculateFrameSizes();
}
Пример #3
0
LRESULT CFrameHolder::OnPaint(HWND hWnd, HDC hdc, UINT uMsg)
{
	if (hdc == NULL)
	{
		LRESULT lRc = 0;
		PAINTSTRUCT ps = {0};
		hdc = BeginPaint(hWnd, &ps);

		if (hdc != NULL)
		{
			lRc = OnPaint(hWnd, hdc, uMsg);

			EndPaint(hWnd, &ps);
		}
		else
		{
			_ASSERTE(hdc != NULL);
		}

		return lRc;
	}

	#ifdef _DEBUG
	RECT rcClientReal = {}; GetClientRect(hWnd, &rcClientReal);
	MapWindowPoints(hWnd, NULL, (LPPOINT)&rcClientReal, 2);
	#endif

	// Если "завис" PostUpdate
	if (gpConEmu->mp_TabBar->NeedPostUpdate())
		gpConEmu->mp_TabBar->Update();

	// Go

	RECT wr, cr;

	RecalculateFrameSizes();

	wr = gpConEmu->GetGuiClientRect();

	#ifdef _DEBUG
	wchar_t szPaint[140];
	_wsprintf(szPaint, SKIPCOUNT(szPaint) L"MainClient %s at {%i,%i}-{%i,%i} screen coords, size (%ix%i) calc (%ix%i)",
		(uMsg == WM_PAINT) ? L"WM_PAINT" : (uMsg == WM_PRINTCLIENT) ? L"WM_PRINTCLIENT" : L"UnknownMsg",
		LOGRECTCOORDS(rcClientReal), LOGRECTSIZE(rcClientReal), LOGRECTSIZE(wr));
	DEBUGSTRPAINT(szPaint);
	#endif

#if defined(CONEMU_TABBAR_EX)
#ifdef RED_CLIENT_FILL
	HBRUSH h = CreateSolidBrush(RGB(255,0,0));
	FillRect(hdc, &wr, h);
	DeleteObject(h);
	return 0;
#endif
#endif

	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;

	DEBUGTEST(FrameDrawStyle dt = gpConEmu->DrawType());


#if defined(CONEMU_TABBAR_EX)
	RECT tr = {};

	if (!gpSet->isTabsInCaption)
	{
		_ASSERTE(gpConEmu->GetDwmClientRectTopOffset() == 0); // CheckIt, must be zero

		if (gpSet->isTabs)
		{
			RECT captrect = gpConEmu->CalcRect(CER_TAB, wr, CER_MAINCLIENT);
			//CalculateCaptionPosition(cr, &captrect);
			CalculateTabPosition(cr, captrect, &tr);

			PaintDC dc = {false};
			RECT pr = {captrect.left, 0, captrect.right, captrect.bottom};
			gpConEmu->BeginBufferedPaint(hdc, pr, dc);

			gpConEmu->mp_TabBar->PaintTabs(dc, captrect, tr);

			gpConEmu->EndBufferedPaint(dc, TRUE);
		}

	}
	else if (dt == fdt_Aero || dt == fdt_Win8)
	{
		_ASSERTE(gpSet->isTabsInCaption);

		int nOffset = gpConEmu->GetDwmClientRectTopOffset();
		// "Рамка" расширена на клиентскую область, поэтому
		// нужно зарисовать заголовок черной кистью, иначе идет
		// искажение цвета для кнопок Min/Max/Close

		if (gpSet->isTabs)
		{
			RECT captrect = gpConEmu->CalcRect(CER_TAB, wr, CER_MAINCLIENT);
			//CalculateCaptionPosition(cr, &captrect);
			CalculateTabPosition(cr, captrect, &tr);

			PaintDC dc = {false};
			RECT pr = {captrect.left, 0, captrect.right, captrect.bottom};
			gpConEmu->BeginBufferedPaint(hdc, pr, dc);

			gpConEmu->mp_TabBar->PaintTabs(dc, captrect, tr);

			gpConEmu->EndBufferedPaint(dc, TRUE);

			// There is no "Glass" in Win8
			mb_WasGlassDraw = IsWindows7 && !IsWindows8;
		}

		cr.top += nOffset;
	}
#endif

	#ifdef _DEBUG
	int nWidth = (cr.right-cr.left);
	int nHeight = (cr.bottom-cr.top);
	#endif

	WARNING("Пока табы рисуем не сами и ExtendDWM отсутствует - дополнительные изыски с временным DC не нужны");
#if 0
	if (!gpSet->isTabsInCaption)
	{
		//OnPaintClient(hdc/*, nWidth, nHeight*/);
	}
	else
	// Создадим временный DC, для удобства отрисовки в Glass-режиме и для фикса глюка DWM(?) см.ниже
	// В принципе, для режима Win2k/XP временный DC можно не создавать, если это будет тормозить
	{
		//_ASSERTE(FALSE && "Need to be rewritten");

		HDC hdcPaint = CreateCompatibleDC(hdc);
		HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight);
		HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcPaint, hbmp);

		//OnPaintClient(hdcPaint/*, nWidth, nHeight*/);

		if ((dt == 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);
	}
#endif

	return 0;
}
Пример #4
0
LRESULT CFrameHolder::OnNcCalcSize(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	RecalculateFrameSizes();

	LRESULT lRc = 0, lRcDef = 0;

	// В Aero (Glass) важно, чтобы клиенская область начиналась с верхнего края окна,
	// иначе не получится "рисовать по стеклу"
	FrameDrawStyle fdt = gpConEmu->DrawType();

	// Если nCaption == 0, то при fdt_Aero текст в заголовке окна не отрисовывается
	DEBUGTEST(int nCaption = GetCaptionHeight());

	bool bCallDefProc = true;

	#if defined(CONEMU_TABBAR_EX)
	// В режиме Aero/Glass (хоть он и почти выпилен в Win8)
	// мы расширяем клиентскую область на заголовок
	if (gpSet->isTabsInCaption && (fdt == fdt_Aero || fdt == fdt_Win8))
	{
		nCaption = 0;
		bCallDefProc = false;
		// Must be "glassed" or "themed", otherwise system will not draw window caption
		_ASSERTE(gpConEmu->IsGlass() || gpConEmu->IsThemed());
	}
	#endif

	if (wParam)
	{
		// lParam points to an NCCALCSIZE_PARAMS structure that contains information
		// an application can use to calculate the new size and position of the client rectangle.
		// The application should indicate which part of the client area contains valid information!
		NCCALCSIZE_PARAMS* pParm = wParam ? ((NCCALCSIZE_PARAMS*)lParam) : NULL;
		// r[0] contains the new coordinates of a window that has been moved or resized,
		//      that is, it is the proposed new window coordinates
		// r[1] contains the coordinates of the window before it was moved or resized
		// r[2] contains the coordinates of the window's client area before the window was moved or resized
		RECT r[3] = {pParm->rgrc[0], pParm->rgrc[1], pParm->rgrc[2]};
		bool bAllowPreserveClient = mb_AllowPreserveClient && (memcmp(r, r+1, sizeof(*r)) == 0);

		// We need to call this, otherwise some parts of window may be broken
		// If don't - system will not draw window caption when theming is off
		if (bCallDefProc)
		{
			lRcDef = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
		}

		//RECT rcWnd = {0,0, r[0].right-r[0].left, r[0].bottom-r[0].top};
		RECT rcClient; // = gpConEmu->CalcRect(CER_MAINCLIENT, rcWnd, CER_MAIN);
		//_ASSERTE(rcClient.left==0 && rcClient.top==0);
		RECT rcMargins = gpConEmu->CalcMargins(CEM_FRAMECAPTION);

		#if defined(CONEMU_TABBAR_EX)
		if (gpSet->isTabsInCaption)
		{
			_ASSERTE(nCaption==0);
			rcClient = MakeRect(r[0].left+rcMargins.left, r[0].top, r[0].right-rcMargins.right, r[0].bottom-rcMargins.bottom);
		}
		else
		#endif
		{
			// Need screen coordinates!
			rcClient = MakeRect(r[0].left+rcMargins.left, r[0].top+rcMargins.top, r[0].right-rcMargins.right, r[0].bottom-rcMargins.bottom);
			//int nDX = ((rcWnd.right - rcClient.right) >> 1);
			//int nDY = ((rcWnd.bottom - rcClient.bottom - nCaption) >> 1);
			//// Need screen coordinates!
			//OffsetRect(&rcClient, r[0].left + nDX, r[0].top + nDY + nCaption);
		}

		// pParm->rgrc[0] contains the coordinates of the new client rectangle resulting from the move or resize
		// pParm->rgrc[1] rectangle contains the valid destination rectangle
		// pParm->rgrc[2] rectangle contains the valid source rectangle
		pParm->rgrc[0] = rcClient;
		//TODO:
		#if 0
		if (!bAllowPreserveClient)
		{
			pParm->rgrc[1] = MakeRect(rcClient.left, rcClient.top, rcClient.left, rcClient.top);
			pParm->rgrc[2] = MakeRect(r[2].left, r[2].top, r[2].left, r[2].top);
		}
		else
		#endif
		{
			pParm->rgrc[1] = rcClient; // Mark as valid - only client area. Let system to redraw the frame and caption.
			pParm->rgrc[2] = r[2];
		}

		if (bAllowPreserveClient)
		{
			lRc = WVR_VALIDRECTS;
		}
		// При смене режимов (особенно при смене HideCaption/NotHideCaption)
		// требовать полную перерисовку клиентской области
		else if (mb_DontPreserveClient || (gpConEmu->GetChangeFromWindowMode() != wmNotChanging))
		{
			lRc = WVR_REDRAW;
		}
	}
	else
	{
		// lParam points to a RECT structure. On entry, the structure contains the proposed window
		// rectangle for the window. On exit, the structure should contain the screen coordinates
		// of the corresponding window client area.
		LPRECT nccr = (LPRECT)lParam;
		RECT rc = *nccr;
		//RECT rcWnd = {0,0, rc.right-rc.left, rc.bottom-rc.top};
		RECT rcClient; // = gpConEmu->CalcRect(CER_MAINCLIENT, rcWnd, CER_MAIN);
		//_ASSERTE(rcClient.left==0 && rcClient.top==0);
		RECT rcMargins = gpConEmu->CalcMargins(CEM_FRAMECAPTION);

		if (bCallDefProc)
		{
			// Call default function JIC
			lRcDef = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
		}

		#if defined(CONEMU_TABBAR_EX)
		if (gpSet->isTabsInCaption)
		{
			_ASSERTE(nCaption==0);
			rcClient = MakeRect(rc.left+rcMargins.left, rc.top, rc.right-rcMargins.right, rc.bottom-rcMargins.bottom);
			//int nDX = ((rcWnd.right - rcClient.right) >> 1);
			//int nDY = ((rcWnd.bottom - rcClient.bottom /*- nCaption*/) >> 1);
			//*nccr = MakeRect(rc.left+nDX, rc.top+nDY, rc.right-nDX, rc.bottom-nDY);
		}
		else
		#endif
		{
			// Need screen coordinates!
			rcClient = MakeRect(rc.left+rcMargins.left, rc.top+rcMargins.top, rc.right-rcMargins.right, rc.bottom-rcMargins.bottom);
			//int nDX = ((rcWnd.right - rcClient.right) >> 1);
			//int nDY = ((rcWnd.bottom - rcClient.bottom - nCaption) >> 1);
			//OffsetRect(&rcClient, rc.left + nDX, rc.top + nDY + nCaption);
		}

		*nccr = rcClient;
	}

	//if (!gpSet->isTabsInCaption)
	//{
	//	lRc = DefWindowProc(hWnd, uMsg, wParam, lParam);
	//}
	//else
	//{
	//	if (!gpSet->isTabs || !gpSet->isTabsInCaption)
	//	{
	//		lRc = DefWindowProc(hWnd, uMsg, wParam, lParam);
	//	}
	//	else
	//	{
	//		RECT r[3];
	//		r[0] = *nccr;
	//		if (wParam)
	//		{
	//			r[1] = pParm->rgrc[1];
	//			r[2] = pParm->rgrc[2];
	//		}
	//
	//		if (fdt == fdt_Aero)
	//		{
	//			// В Aero (Glass) важно, чтобы клиенская область начиналась с верхнего края окна,
	//			// иначе не получится "рисовать по стеклу"
	//			nccr->top = r->top; // нада !!!
	//			nccr->left = r->left + GetFrameWidth();
	//			nccr->right = r->right - GetFrameWidth();
	//			nccr->bottom = r->bottom - GetFrameHeight();
	//		}
	//		else
	//		{
	//			//TODO: Темы!!! В XP ширина/высота рамки может быть больше
	//			nccr->top = r->top + GetFrameHeight() + GetCaptionHeight();
	//			nccr->left = r->left + GetFrameWidth();
	//			nccr->right = r->right - GetFrameWidth();
	//			nccr->bottom = r->bottom - GetFrameHeight();
	//		}
	//	}

	//	// Наверное имеет смысл сбрасывать всегда, чтобы Win не пыталась
	//	// отрисовать невалидное содержимое консоли (она же размер меняет)
	//	if (wParam)
	//	{
	//		//pParm->rgrc[1] = *nccr;
	//		//pParm->rgrc[2] = r[2];
	//		memset(pParm->rgrc+1, 0, sizeof(RECT)*2);
	//	}
	//}

	UNREFERENCED_PARAMETER(lRcDef);
	UNREFERENCED_PARAMETER(fdt);
	return lRc;
}
Пример #5
0
LRESULT CFrameHolder::OnNcCalcSize(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	RecalculateFrameSizes();

	LRESULT lRc = 0;
	FrameDrawStyle fdt = gpConEmu->DrawType();
	NCCALCSIZE_PARAMS* pParm = wParam ? ((NCCALCSIZE_PARAMS*)lParam) : NULL;
	LPRECT nccr = wParam
			? pParm->rgrc
			: (RECT*)lParam;
			
	if (!gpSet->isTabsInCaption)
	{
		lRc = DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	else
	{
		if (!gpSet->isTabs || !gpSet->isTabsInCaption)
		{
			lRc = DefWindowProc(hWnd, uMsg, wParam, lParam);
		}
		else
		{
			RECT r[3];
			r[0] = *nccr;
			if (wParam)
			{
				r[1] = pParm->rgrc[1];
				r[2] = pParm->rgrc[2];
			}
				
			if (fdt == fdt_Aero)
			{
				// В Aero (Glass) важно, чтобы клиенская область начиналась с верхнего края окна,
				// иначе не получится "рисовать по стеклу"
				nccr->top = r->top; // нада !!!
				nccr->left = r->left + GetFrameWidth();
				nccr->right = r->right - GetFrameWidth();
				nccr->bottom = r->bottom - GetFrameHeight();
			}
			else
			{
				//TODO: Темы!!! В XP ширина/высота рамки может быть больше
				nccr->top = r->top + GetFrameHeight() + GetCaptionHeight();
				nccr->left = r->left + GetFrameWidth();
				nccr->right = r->right - GetFrameWidth();
				nccr->bottom = r->bottom - GetFrameHeight();
			}
		}

		// Наверное имеет смысл сбрасывать всегда, чтобы Win не пыталась
		// отрисовать невалидное содержимое консоли (она же размер меняет)
		if (wParam)
		{
			//pParm->rgrc[1] = *nccr;
			//pParm->rgrc[2] = r[2];
			memset(pParm->rgrc+1, 0, sizeof(RECT)*2);
		}
	}

	return lRc;
}
Пример #6
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;
}