コード例 #1
0
ファイル: afxglobals.cpp プロジェクト: heksesang/mpc-hc
CMemDC::~CMemDC()
{
	if (m_hBufferedPaint != NULL)
	{
		m_dcMem.Detach();
		EndBufferedPaint(m_hBufferedPaint, TRUE);
	}
}
コード例 #2
0
LRESULT AeroControlBase::ProgressbarWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_ENABLE:
    case WM_STYLECHANGED:
        {
            LRESULT res = DefSubclassProc(hWnd, uMsg, wParam, lParam);
            InvalidateRgn(hWnd, NULL, FALSE);
            return res;
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            RECT rc;
            GetWindowRect(hWnd, &rc);
            MapWindowPoints(NULL, hWnd, (LPPOINT)&rc, 2);

            if (hdc)
            {
                PaintControl(hWnd, hdc, &ps.rcPaint, false);

                BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) };
                params.dwFlags = 0L;
                HDC hdcPaint = NULL;
                HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, &params, &hdcPaint);
                if (hdcPaint)
                {
                    COLORREF cr = RGB(0x00, 0x00, 0x00);
                    SetPixel(hdcPaint, 0, 0, cr);
                    SetPixel(hdcPaint, 0, RECTHEIGHT(rc) - 1, cr);
                    SetPixel(hdcPaint, RECTWIDTH(rc) - 1, 0, cr);
                    SetPixel(hdcPaint, RECTWIDTH(rc) - 1, RECTHEIGHT(rc) - 1, cr);

                    EndBufferedPaint(hBufferedPaint, TRUE);
                }
            }

            EndPaint(hWnd, &ps);
            return 0;
        }
        break;
    case WM_NCDESTROY:
    case WM_DESTROY:
        RemoveWindowSubclass(hWnd, SubclassProc, Static);
        subclassedControls.erase(hWnd);
        break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
コード例 #3
0
HBITMAP LiferayNativityContextMenus::_IconToBitmapPARGB32(HICON hIcon)
{
	if (!hIcon)
		return NULL;

	SIZE sizIcon;
	sizIcon.cx = GetSystemMetrics(SM_CXSMICON);
	sizIcon.cy = GetSystemMetrics(SM_CYSMICON);

	RECT rcIcon;
	SetRect(&rcIcon, 0, 0, sizIcon.cx, sizIcon.cy);
	HBITMAP hBmp = NULL;

	HDC hdcDest = CreateCompatibleDC(NULL);
	if (hdcDest)
	{
		if (SUCCEEDED(_Create32BitHBITMAP(hdcDest, &sizIcon, NULL, &hBmp)))
		{
			HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDest, hBmp);
			if (hbmpOld)
			{
				BLENDFUNCTION bfAlpha = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
				BP_PAINTPARAMS paintParams = { 0 };
				paintParams.cbSize = sizeof(paintParams);
				paintParams.dwFlags = BPPF_ERASE;
				paintParams.pBlendFunction = &bfAlpha;

				HDC hdcBuffer;
				HPAINTBUFFER hPaintBuffer = BeginBufferedPaint(hdcDest, &rcIcon, BPBF_DIB, &paintParams, &hdcBuffer);
				if (hPaintBuffer)
				{
					if (DrawIconEx(hdcBuffer, 0, 0, hIcon, sizIcon.cx, sizIcon.cy, 0, NULL, DI_NORMAL))
					{
						// If icon did not have an alpha channel we need to convert buffer to PARGB
						_ConvertBufferToPARGB32(hPaintBuffer, hdcDest, hIcon, sizIcon);
					}

					// This will write the buffer contents to the destination bitmap
					EndBufferedPaint(hPaintBuffer, TRUE);
				}

				SelectObject(hdcDest, hbmpOld);
			}
		}

		DeleteDC(hdcDest);
	}

	return hBmp;
}
コード例 #4
0
HBITMAP IconBitmapUtils::IconToBitmapPARGB32(HICON hIcon, int width, int height)
{
	if (!hIcon)
		return nullptr;

	SIZE sizIcon;
	sizIcon.cx = width;
	sizIcon.cy = height;

	RECT rcIcon;
	SetRect(&rcIcon, 0, 0, sizIcon.cx, sizIcon.cy);

	HDC hdcDest = CreateCompatibleDC(nullptr);
	if (!hdcDest)
		return nullptr;
	SCOPE_EXIT { DeleteDC(hdcDest); };

	HBITMAP hBmp = nullptr;
	if (FAILED(Create32BitHBITMAP(hdcDest, &sizIcon, nullptr, &hBmp)))
		return nullptr;

	auto hbmpOld = static_cast<HBITMAP>(SelectObject(hdcDest, hBmp));
	if (!hbmpOld)
		return hBmp;

	BLENDFUNCTION bfAlpha = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
	BP_PAINTPARAMS paintParams = { 0 };
	paintParams.cbSize = sizeof(paintParams);
	paintParams.dwFlags = BPPF_ERASE;
	paintParams.pBlendFunction = &bfAlpha;

	HDC hdcBuffer;
	HPAINTBUFFER hPaintBuffer = BeginBufferedPaint(hdcDest, &rcIcon, BPBF_DIB, &paintParams, &hdcBuffer);
	if (hPaintBuffer)
	{
		if (DrawIconEx(hdcBuffer, 0, 0, hIcon, sizIcon.cx, sizIcon.cy, 0, nullptr, DI_NORMAL))
		{
			// If icon did not have an alpha channel we need to convert buffer to PARGB
			ConvertBufferToPARGB32(hPaintBuffer, hdcDest, hIcon, sizIcon);
		}

		// This will write the buffer contents to the destination bitmap
		EndBufferedPaint(hPaintBuffer, TRUE);
	}

	SelectObject(hdcDest, hbmpOld);
	return hBmp;
}
コード例 #5
0
ファイル: menu.cpp プロジェクト: AlexRee/windows-setup
HBITMAP ComposerShellMenu::IconToBitmap(HICON hIcon)
{
    HBITMAP hBmp = NULL;
    HDC hdcDest = CreateCompatibleDC(NULL);

    if (hIcon && hdcDest)
    {
        long cx = GetSystemMetrics(SM_CXSMICON);
        long cy = GetSystemMetrics(SM_CYSMICON);
        RGBQUAD *bits = NULL;

        BITMAPINFO bmi = {0};
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biWidth = cx;
        bmi.bmiHeader.biHeight = cy;
        bmi.bmiHeader.biBitCount = 32;

        hBmp = CreateDIBSection(hdcDest, &bmi, DIB_RGB_COLORS, (VOID **)bits, NULL, 0);
        if (hBmp)
        { 
            SelectObject(hdcDest, hBmp);
            RECT rct;
            SetRect(&rct, 0, 0, cx, cy);

            BLENDFUNCTION bfAlpha = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
            BP_PAINTPARAMS paintParams = {0};
            paintParams.cbSize = sizeof(paintParams);
            paintParams.dwFlags = BPPF_ERASE;
            paintParams.pBlendFunction = &bfAlpha;

            HDC hdcBuffer;
            HPAINTBUFFER hPaintBuffer = BeginBufferedPaint(hdcDest, &rct, BPBF_DIB, &paintParams, &hdcBuffer);
            if (hPaintBuffer)
            {
                DrawIconEx(hdcBuffer, 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL);
                // Write the buffer contents to hdcDest
                EndBufferedPaint(hPaintBuffer, TRUE);
            }
        }

        DeleteDC(hdcDest);
    }

    return hBmp;
}
コード例 #6
0
void AeroControlBase::PaintControl(HWND hWnd, HDC hdc, RECT* prc, bool bDrawBorder)
{
    HDC hdcPaint = NULL;

    if(bDrawBorder)
        VERIFY(InflateRect(prc, 1, 1));
    HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, prc, BPBF_TOPDOWNDIB, NULL, &hdcPaint);
    if (hdcPaint)
    {
        RECT rc;
        VERIFY(GetWindowRect(hWnd, &rc));

        PatBlt(hdcPaint, 0, 0, RECTWIDTH(rc), RECTHEIGHT(rc), BLACKNESS);
        VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &rc, 0x00));

        ///
        /// first blit white so list ctrls don't look ugly:
        ///
        VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rc), RECTHEIGHT(rc), WHITENESS));

        if(bDrawBorder)
            VERIFY(InflateRect(prc, -1, -1));
        // Tell the control to paint itself in our memory buffer
        SendMessage(hWnd, WM_PRINTCLIENT, (WPARAM) hdcPaint, PRF_CLIENT|PRF_ERASEBKGND |PRF_NONCLIENT|PRF_CHECKVISIBLE);

        if(bDrawBorder)
        {
            VERIFY(InflateRect(prc, 1, 1));
            VERIFY(FrameRect(hdcPaint, prc, (HBRUSH)GetStockObject(BLACK_BRUSH)));
        }

        // don't make a possible border opaque, only the inner part of the control
        VERIFY(InflateRect(prc, -2, -2));
        // Make every pixel opaque
        VERIFY(S_OK == BufferedPaintSetAlpha(hBufferedPaint, prc, 255));
        VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE));
    }
}
コード例 #7
0
LRESULT AeroControlBase::ButtonWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_SETTEXT:
    case WM_ENABLE:
    case WM_STYLECHANGED:
        {
            LRESULT res = DefSubclassProc(hWnd, uMsg, wParam, lParam);
            InvalidateRgn(hWnd, NULL, FALSE);
            return res;
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            if(hdc)
            {
                LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
                LONG_PTR dwButtonStyle = LOWORD(dwStyle);
                LONG_PTR dwButtonType = dwButtonStyle&0xF;
                RECT rcClient;
                VERIFY(GetClientRect(hWnd, &rcClient));

                if((dwButtonType&BS_GROUPBOX)==BS_GROUPBOX)
                {
                    ///
                    /// it must be a group box
                    ///
                    HTHEME hTheme = OpenThemeData(hWnd, L"Button");
                    if(hTheme)
                    {
                        BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) };
                        params.dwFlags        = BPPF_ERASE;

                        RECT rcExclusion = rcClient;
                        params.prcExclude = &rcExclusion;

                        ///
                        /// We have to calculate the exclusion rect and therefore
                        /// calculate the font height. We select the control's font
                        /// into the DC and fake a drawing operation:
                        ///
                        HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL);
                        if(hFontOld)
                            hFontOld = (HFONT) SelectObject(hdc, hFontOld);

                        RECT rcDraw = rcClient;
                        DWORD dwFlags = DT_SINGLELINE;

                        ///
                        /// we use uppercase A to determine the height of text, so we
                        /// can draw the upper line of the groupbox:
                        ///
                        DrawTextW(hdc, L"A", -1,  &rcDraw, dwFlags|DT_CALCRECT);

                        if (hFontOld)
                        {
                            SelectObject(hdc, hFontOld);
                            hFontOld    = NULL;
                        }

                        VERIFY(InflateRect(&rcExclusion, -1, -1*RECTHEIGHT(rcDraw)));

                        HDC hdcPaint = NULL;
                        HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB,
                            &params, &hdcPaint);
                        if (hdcPaint)
                        {
                            ///
                            /// now we again retrieve the font, but this time we select it into
                            /// the buffered DC:
                            ///
                            hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL);
                            if(hFontOld)
                                hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld);


                            VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS));

                            VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00));
                            int iPartId = BP_GROUPBOX;

                            int iState = GetStateFromBtnState(dwStyle, FALSE, FALSE, 0L, iPartId, FALSE);

                            DTTOPTS DttOpts = {sizeof(DTTOPTS)};
                            DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
                            DttOpts.crText   = RGB(255, 255, 255);
                            DttOpts.iGlowSize = 12; // Default value

                            VERIFY(DetermineGlowSize(&DttOpts.iGlowSize));

                            COLORREF cr = RGB(0x00, 0x00, 0x00);
                            VERIFY(GetEditBorderColor(hWnd, &cr));
                            ///
                            /// add the alpha value:
                            ///
                            cr |= 0xff000000;

                            std::unique_ptr<Pen> myPen( new Pen(Color(cr), 1) );
                            std::unique_ptr<Graphics> myGraphics( new Graphics(hdcPaint) );
                            int iY = RECTHEIGHT(rcDraw)/2;
                            Rect rr = Rect(rcClient.left, rcClient.top+iY,
                                RECTWIDTH(rcClient), RECTHEIGHT(rcClient)-iY-1);
                            GraphicsPath path;
                            GetRoundRectPath(&path, rr, 10);
                            myGraphics->DrawPath(myPen.get(), &path);
                            //myGraphics->DrawRectangle(myPen, rcClient.left, rcClient.top + iY,
                            //  RECTWIDTH(rcClient)-1, RECTHEIGHT(rcClient) - iY-1);
                            myGraphics.reset();
                            myPen.reset();

                            int iLen = GetWindowTextLength(hWnd);

                            if(iLen)
                            {
                                iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING
                                LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen);
                                if(szText)
                                {
                                    iLen = GetWindowTextW(hWnd, szText, iLen);
                                    if(iLen)
                                    {
                                        int iX = RECTWIDTH(rcDraw);
                                        rcDraw = rcClient;
                                        rcDraw.left += iX;
                                        DrawTextW(hdcPaint, szText, -1,  &rcDraw, dwFlags|DT_CALCRECT);
                                        VERIFY(PatBlt(hdcPaint, rcDraw.left, rcDraw.top , RECTWIDTH(rcDraw) + 3, RECTHEIGHT(rcDraw), BLACKNESS));
                                        rcDraw.left++;
                                        rcDraw.right++;
                                        VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, iPartId, iState, szText, -1,
                                            dwFlags, &rcDraw, &DttOpts));

                                    }

                                    VERIFY(!LocalFree(szText));
                                }
                            }

                            if (hFontOld)
                            {
                                SelectObject(hdcPaint, hFontOld);
                                hFontOld    = NULL;
                            }

                            VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE));

                        }

                        VERIFY(S_OK==CloseThemeData(hTheme));
                    }
                }

                else if(dwButtonType==BS_CHECKBOX || dwButtonType==BS_AUTOCHECKBOX ||
                    dwButtonType==BS_3STATE || dwButtonType==BS_AUTO3STATE || dwButtonType==BS_RADIOBUTTON || dwButtonType==BS_AUTORADIOBUTTON)
                {
                    HTHEME hTheme = OpenThemeData(hWnd, L"Button");
                    if(hTheme)
                    {
                        HDC hdcPaint = NULL;
                        BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) };
                        params.dwFlags        = BPPF_ERASE;
                        HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, &params, &hdcPaint);
                        if (hdcPaint)
                        {
                            VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS));

                            VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00));

                            LRESULT dwCheckState = SendMessage(hWnd, BM_GETCHECK, 0, NULL);
                            POINT pt;
                            RECT rc;
                            GetWindowRect(hWnd, &rc);
                            GetCursorPos(&pt);
                            BOOL bHot = PtInRect(&rc, pt);
                            BOOL bFocus = GetFocus()==hWnd;

                            int iPartId = BP_CHECKBOX;
                            if(dwButtonType==BS_RADIOBUTTON || dwButtonType==BS_AUTORADIOBUTTON)
                                iPartId = BP_RADIOBUTTON;

                            int iState = GetStateFromBtnState(dwStyle, bHot, bFocus, dwCheckState, iPartId, FALSE);

                            int bmWidth = int(ceil(13.0 * GetDeviceCaps(hdcPaint, LOGPIXELSX) / 96.0));

                            UINT uiHalfWidth = (RECTWIDTH(rcClient) - bmWidth)/2;

                            ///
                            /// we have to use the whole client area, otherwise we get only partially
                            /// drawn areas:
                            ///
                            RECT rcPaint = rcClient;

                            if(dwButtonStyle & BS_LEFTTEXT)
                            {
                                rcPaint.left += uiHalfWidth;
                                rcPaint.right += uiHalfWidth;
                            }
                            else
                            {
                                rcPaint.left -= uiHalfWidth;
                                rcPaint.right -= uiHalfWidth;
                            }


                            ///
                            /// we assume that bmWidth is both the horizontal and the vertical
                            /// dimension of the control bitmap and that it is square. bm.bmHeight
                            /// seems to be the height of a striped bitmap because it is an absurdly
                            /// high dimension value
                            ///
                            if((dwButtonStyle&BS_VCENTER)==BS_VCENTER) /// BS_VCENTER is BS_TOP|BS_BOTTOM
                            {
                                int h = RECTHEIGHT(rcPaint);
                                rcPaint.top = (h - bmWidth) / 2;
                                rcPaint.bottom = rcPaint.top + bmWidth;
                            }
                            else if(dwButtonStyle&BS_TOP)
                            {
                                rcPaint.bottom = rcPaint.top + bmWidth;
                            }
                            else if(dwButtonStyle&BS_BOTTOM)
                            {
                                rcPaint.top =  rcPaint.bottom - bmWidth;
                            }
                            else // default: center the checkbox/radiobutton vertically
                            {
                                int h = RECTHEIGHT(rcPaint);
                                rcPaint.top = (h - bmWidth) / 2;
                                rcPaint.bottom = rcPaint.top + bmWidth;
                            }


                            VERIFY(S_OK==DrawThemeBackground(hTheme, hdcPaint, iPartId, iState, &rcPaint, NULL));
                            rcPaint = rcClient;


                            VERIFY(S_OK==GetThemeBackgroundContentRect(hTheme, hdcPaint, iPartId, iState, &rcPaint, &rc));

                            if(dwButtonStyle & BS_LEFTTEXT)
                                rc.right -= bmWidth + 2 * GetSystemMetrics(SM_CXEDGE);
                            else
                                rc.left += bmWidth + 2 * GetSystemMetrics(SM_CXEDGE);

                            DTTOPTS DttOpts = {sizeof(DTTOPTS)};
                            DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
                            DttOpts.crText   = RGB(255, 255, 255);
                            DttOpts.iGlowSize = 12; // Default value

                            VERIFY(DetermineGlowSize(&DttOpts.iGlowSize));


                            HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL);
                            if(hFontOld)
                                hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld);
                            int iLen = GetWindowTextLength(hWnd);

                            if(iLen)
                            {
                                iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING
                                LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen);
                                if(szText)
                                {
                                    iLen = GetWindowTextW(hWnd, szText, iLen);
                                    if(iLen)
                                    {
                                        DWORD dwFlags = DT_SINGLELINE /*|DT_VCENTER*/;
                                        if(dwButtonStyle&BS_MULTILINE)
                                        {
                                            dwFlags|=DT_WORDBREAK;
                                            dwFlags&= ~(DT_SINGLELINE |DT_VCENTER);
                                        }

                                        if((dwButtonStyle&BS_CENTER)==BS_CENTER) /// BS_CENTER is BS_LEFT|BS_RIGHT
                                            dwFlags|=DT_CENTER;
                                        else if(dwButtonStyle&BS_LEFT)
                                            dwFlags|=DT_LEFT;
                                        else if(dwButtonStyle&BS_RIGHT)
                                            dwFlags|=DT_RIGHT;


                                        if((dwButtonStyle&BS_VCENTER)==BS_VCENTER) /// BS_VCENTER is BS_TOP|BS_BOTTOM
                                            dwFlags|=DT_VCENTER;
                                        else if(dwButtonStyle&BS_TOP)
                                            dwFlags|=DT_TOP;
                                        else if(dwButtonStyle&BS_BOTTOM)
                                            dwFlags|=DT_BOTTOM;
                                        else
                                            dwFlags|=DT_VCENTER;

                                        VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, iPartId,
                                            iState, szText, -1, dwFlags, &rc, &DttOpts));

                                        ///
                                        /// if our control has the focus, we also have to draw the focus rectangle:
                                        ///
                                        if(bFocus)
                                        {
                                            ///
                                            /// now calculate the text size:
                                            ///
                                            RECT rcDraw = rc;

                                            ///
                                            /// we use GDI's good old DrawText, because it returns much more
                                            /// accurate data than DrawThemeTextEx, which takes the glow
                                            /// into account which we don't want:
                                            ///
                                            VERIFY(DrawTextW(hdcPaint, szText, -1,  &rcDraw, dwFlags|DT_CALCRECT));
                                            if(dwFlags&DT_SINGLELINE)
                                            {
                                                dwFlags &= ~DT_VCENTER;
                                                RECT rcDrawTop;
                                                DrawTextW(hdcPaint, szText, -1,  &rcDrawTop, dwFlags|DT_CALCRECT);
                                                rcDraw.top = rcDraw.bottom - RECTHEIGHT(rcDrawTop);
                                            }

                                            if(dwFlags & DT_RIGHT)
                                            {
                                                int iWidth = RECTWIDTH(rcDraw);
                                                rcDraw.right = rc.right;
                                                rcDraw.left = rcDraw.right - iWidth;
                                            }

                                            RECT rcFocus;
                                            VERIFY(IntersectRect(&rcFocus, &rc, &rcDraw));

                                            DrawFocusRect(&rcFocus, hdcPaint);
                                        }
                                    }

                                    VERIFY(!LocalFree(szText));
                                }
                            }

                            if (hFontOld)
                            {
                                SelectObject(hdcPaint, hFontOld);
                                hFontOld    = NULL;
                            }

                            VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE));
                        }
                        VERIFY(S_OK==CloseThemeData(hTheme));
                    }


                }
                else if(BS_PUSHBUTTON==dwButtonType || BS_DEFPUSHBUTTON==dwButtonType)
                {
                    ///
                    /// it is a push button
                    ///
                    HTHEME hTheme = OpenThemeData(hWnd, L"Button");
                    if(hTheme)
                    {
                        HDC hdcPaint = NULL;
                        BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) };
                        params.dwFlags        = BPPF_ERASE;
                        HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, &params, &hdcPaint);
                        if (hdcPaint)
                        {
                            VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS));

                            VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00));

                            LRESULT dwCheckState = SendMessage(hWnd, BM_GETCHECK, 0, NULL);
                            POINT pt;
                            RECT rc;
                            GetWindowRect(hWnd, &rc);
                            GetCursorPos(&pt);
                            BOOL bHot = PtInRect(&rc, pt);
                            BOOL bFocus = GetFocus()==hWnd;
                            int iPartId = BP_PUSHBUTTON;

                            if(dwButtonStyle==BS_RADIOBUTTON || dwButtonStyle==BS_AUTORADIOBUTTON)
                                iPartId = BP_RADIOBUTTON;


                            int iState = GetStateFromBtnState(dwStyle, bHot, bFocus, dwCheckState, iPartId, GetCapture()==hWnd);

                            ///
                            /// we have to use the whole client area, otherwise we get only partially
                            /// drawn areas:
                            ///
                            RECT rcPaint = rcClient;
                            VERIFY(S_OK==DrawThemeBackground(hTheme, hdcPaint, iPartId, iState, &rcPaint, NULL));


                            VERIFY(S_OK==GetThemeBackgroundContentRect(hTheme, hdcPaint, iPartId, iState, &rcPaint, &rc));


                            DTTOPTS DttOpts = {sizeof(DTTOPTS)};
                            DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
                            DttOpts.crText   = RGB(255, 255, 255);
                            DttOpts.iGlowSize = 12; // Default value

                            VERIFY(DetermineGlowSize(&DttOpts.iGlowSize));


                            HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL);
                            if(hFontOld)
                                hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld);
                            int iLen = GetWindowTextLength(hWnd);

                            if(iLen)
                            {
                                iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING
                                LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen);
                                if(szText)
                                {
                                    iLen = GetWindowTextW(hWnd, szText, iLen);
                                    if(iLen)
                                    {
                                        DWORD dwFlags = DT_SINGLELINE | DT_CENTER | DT_VCENTER;
                                        VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint,
                                            iPartId, iState, szText, -1, dwFlags, &rc, &DttOpts));

                                        ///
                                        /// if our control has the focus, we also have to draw the focus rectangle:
                                        ///
                                        if(bFocus)
                                        {
                                            RECT rcDraw = rcClient;
                                            VERIFY(InflateRect(&rcDraw, -3, -3));
                                            DrawFocusRect(&rcDraw, hdcPaint);
                                        }

                                    }

                                    VERIFY(!LocalFree(szText));
                                }
                            }

                            if (hFontOld)
                            {
                                SelectObject(hdcPaint, hFontOld);
                                hFontOld    = NULL;
                            }

                            VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE));
                        }
                        VERIFY(S_OK==CloseThemeData(hTheme));
                    }
                }
                else
                    //PaintControl(hWnd, hdc, &ps.rcPaint, (m_dwFlags & WD_DRAW_BORDER)!=0);
                    PaintControl(hWnd, hdc, &ps.rcPaint, false);
            }

            EndPaint(hWnd, &ps);
            return 0;
        }
        break;
    case WM_DESTROY:
    case WM_NCDESTROY:
        RemoveWindowSubclass(hWnd, SubclassProc, Button);
        subclassedControls.erase(hWnd);
        break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
コード例 #8
0
LRESULT AeroControlBase::StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SETTEXT:
    case WM_ENABLE:
    case WM_STYLECHANGED:
        {
            LRESULT res = DefSubclassProc(hWnd, uMsg, wParam, lParam);
            InvalidateRgn(hWnd, NULL, FALSE);
            return res;
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

            if(hdc)
            {
                HDC hdcPaint = NULL;
                RECT rcClient;
                VERIFY(GetClientRect(hWnd, &rcClient));

                LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
                LONG_PTR dwStyleEx = GetWindowLongPtr(hWnd, GWL_EXSTYLE);

                HTHEME hTheme = OpenThemeData(NULL, L"ControlPanelStyle");
                if(hTheme)
                {
                    HPAINTBUFFER hBufferedPaint = NULL;
                    if (dwStyleEx & WS_EX_TRANSPARENT)
                    {
                        BP_PAINTPARAMS paintParams = {0};
                        paintParams.cbSize = sizeof(paintParams);
                        paintParams.dwFlags = BPPF_ERASE;
                        BLENDFUNCTION blendf = {0};
                        blendf.BlendOp = AC_SRC_OVER;
                        blendf.AlphaFormat = AC_SRC_ALPHA;
                        blendf.SourceConstantAlpha = 255;
                        paintParams.pBlendFunction = &blendf;
                        hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, &paintParams, &hdcPaint);
                    }
                    else
                        hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, NULL, &hdcPaint);

                    if (hdcPaint)
                    {
                        VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS));
                        VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00));
                        LONG_PTR dwStaticStyle = dwStyle&0x1F;


                        if(dwStaticStyle==SS_ICON || dwStaticStyle==SS_BITMAP)
                        {
                            bool bIcon = dwStaticStyle==SS_ICON;
                            HANDLE hBmpIco = (HANDLE)SendMessage(hWnd, STM_GETIMAGE, bIcon ? IMAGE_ICON:IMAGE_BITMAP, NULL);
                            if(hBmpIco)
                            {
                                std::unique_ptr<Bitmap> pBmp( bIcon ? new Bitmap((HICON)hBmpIco) : new Bitmap((HBITMAP)hBmpIco, NULL) );
                                std::unique_ptr<Graphics> myGraphics( new Graphics(hdcPaint) );
                                std::unique_ptr<CachedBitmap> pcbmp( new CachedBitmap(pBmp.get(), myGraphics.get()) );
                                VERIFY(Ok==myGraphics->DrawCachedBitmap(pcbmp.get(), 0,0));
                            }
                        }
                        else if(SS_BLACKRECT==dwStaticStyle || SS_GRAYRECT==dwStaticStyle || SS_WHITERECT==dwStaticStyle)
                        {
                            ARGB argb = 0L;
                            switch (dwStaticStyle)
                            {
                            case SS_BLACKRECT:
                                argb = 0xFF000000;
                                break;
                            case SS_GRAYRECT:
                                argb = 0xFF808080;
                                break;
                            case SS_WHITERECT:
                                argb = 0xFFFFFFFF;
                                break;
                            default:
                                ASSERT(0);
                                break;
                            }
                            Color clr(argb);

                            FillRect(&rcClient, hdcPaint, clr);
                        }
                        else if(SS_BLACKFRAME==dwStaticStyle || SS_GRAYFRAME==dwStaticStyle || SS_WHITEFRAME==dwStaticStyle)
                        {
                            ARGB argb = 0L;
                            switch (dwStaticStyle)
                            {
                            case SS_BLACKFRAME:
                                argb = 0xFF000000;
                                break;
                            case SS_GRAYFRAME:
                                argb = 0xFF808080;
                                break;
                            case SS_WHITEFRAME:
                                argb = 0xFFFFFFFF;
                                break;
                            }
                            Color clr(argb);

                            DrawRect(&rcClient, hdcPaint, DashStyleSolid, clr, 1.0);
                        }
                        else
                        {
                            DTTOPTS DttOpts = {sizeof(DTTOPTS)};
                            DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
                            DttOpts.crText   = RGB(255, 255, 255);
                            DttOpts.iGlowSize = 12; // Default value

                            VERIFY(DetermineGlowSize(&DttOpts.iGlowSize));

                            HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL);
                            if(hFontOld)
                                hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld);
                            int iLen = GetWindowTextLength(hWnd);

                            if(iLen)
                            {
                                iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING
                                LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen);
                                if(szText)
                                {
                                    iLen = GetWindowTextW(hWnd, szText, iLen);
                                    if(iLen)
                                    {
                                        DWORD dwFlags = DT_WORDBREAK;

                                        switch (dwStaticStyle)
                                        {
                                        case SS_CENTER:
                                            dwFlags |= DT_CENTER;
                                            break;
                                        case SS_RIGHT:
                                            dwFlags |= DT_RIGHT;
                                            break;
                                        case SS_LEFTNOWORDWRAP:
                                            dwFlags &= ~DT_WORDBREAK;
                                            break;
                                        }

                                        if(dwStyle & SS_CENTERIMAGE)
                                        {
                                            dwFlags |= DT_VCENTER;
                                            dwFlags &= ~DT_WORDBREAK;
                                        }

                                        if(dwStyle & SS_ENDELLIPSIS)
                                            dwFlags |= DT_END_ELLIPSIS|DT_MODIFYSTRING;
                                        else if(dwStyle & SS_PATHELLIPSIS)
                                            dwFlags |= DT_PATH_ELLIPSIS|DT_MODIFYSTRING;
                                        else if(dwStyle & SS_WORDELLIPSIS)
                                            dwFlags |= DT_WORD_ELLIPSIS|DT_MODIFYSTRING;

                                        if (dwStyleEx&WS_EX_RIGHT)
                                            dwFlags |= DT_RIGHT;

                                        if(dwStyle & SS_NOPREFIX)
                                            dwFlags |= DT_NOPREFIX;

                                        VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, 0, 0,
                                            szText, -1, dwFlags, &rcClient, &DttOpts));

                                        if(dwStyle&SS_SUNKEN || dwStyle&WS_BORDER)
                                            DrawRect(&rcClient, hdcPaint, DashStyleSolid, Color(0xFF, 0,0,0), 1.0);
                                    }
                                    VERIFY(!LocalFree(szText));
                                }
                            }

                            if (hFontOld)
                            {
                                SelectObject(hdcPaint, hFontOld);
                                hFontOld    = NULL;
                            }
                        }

                        VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE));
                    }

                    VERIFY(S_OK==CloseThemeData(hTheme));
                }
            }

            EndPaint(hWnd, &ps);
            return 0;
        }
        break;
    case WM_NCDESTROY:
    case WM_DESTROY:
        RemoveWindowSubclass(hWnd, SubclassProc, Static);
        subclassedControls.erase(hWnd);
        break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
コード例 #9
0
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId;
    int wmEvent;
    
    switch (message) 
    {
        case WM_COMMAND:
            wmId    = LOWORD(wParam); 
            wmEvent = HIWORD(wParam); 
            // Parse the menu selections:
            switch (wmId)
            {
                case IDM_ABOUT:
                    DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;

        case WM_ERASEBKGND:
            return 1;

        case WM_PAINT:
            // Let's open some theme data, and using BufferedPainting draw different fonts on glass background
            {
                RECT rcClient;
                GetClientRect(hWnd, &rcClient);

                MARGINS marGlassInset = {-1, -1, -1, -1}; // -1 means the whole window
                DwmExtendFrameIntoClientArea(hWnd, &marGlassInset);

                PAINTSTRUCT ps;
                HDC    hdc    = BeginPaint(hWnd, &ps);
                // ControlPanelStyle is declared in AeroStyle.xml
                HTHEME hTheme = OpenThemeData(NULL, L"ControlPanelStyle"); 

                if (hTheme)
                {
                    HDC hdcPaint = NULL;

                    BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) };
                    params.dwFlags        = BPPF_ERASE;

                    HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, &params, &hdcPaint);
                    if (hdcPaint)
                    {
                        // Let's start with the simplest GDI default font
                        DTTOPTS DttOpts = {sizeof(DTTOPTS)};
                        DttOpts.dwFlags = DTT_COMPOSITED;
                        DrawText(hdcPaint, L"This is some GDI text in the default font", -1, &rcClient, 0);

                        // Let's look at the same text in the default theme
                        rcClient.top += RECT_INCREMENT;
                        DrawThemeTextEx(hTheme, hdcPaint, 0, 0, L"This is some text in the default font", -1, 0, &rcClient, &DttOpts);

                        // Let's add some text color to add to theming attributes and draw again
                        rcClient.top    += RECT_INCREMENT;
                        DttOpts.dwFlags |= DTT_TEXTCOLOR;
                        DttOpts.crText   = RGB(255, 255, 255);
                        // CPANEL_TASKLINK is declared in VSStyle.h
                        DrawThemeTextEx(hTheme, hdcPaint, CPANEL_TASKLINK, 0, L"This is some text in a themed font", -1, 0, &rcClient, &DttOpts);

                        // Draw text on glass in a selected font
                        DttOpts.dwFlags &= ~DTT_TEXTCOLOR;
                        LOGFONT lgFont;
                        HFONT hFontOld = NULL;
                        if (SUCCEEDED(GetThemeSysFont(hTheme, TMT_CAPTIONFONT, &lgFont)))
                        {
                            HFONT hFont = CreateFontIndirect(&lgFont);
                            hFontOld    = (HFONT) SelectObject(hdcPaint, hFont);
                        }

                        rcClient.top += RECT_INCREMENT;
                        DrawText(hdcPaint, L"This is some GDI text in the selected font", -1, &rcClient, 0);

                        // The same selected font in themed text
                        rcClient.top += RECT_INCREMENT;
                        DrawThemeTextEx(hTheme, hdcPaint, 0, 0, L"This is some text in the selected font", -1, 0, &rcClient, &DttOpts);

                        SelectObject(hdcPaint, hFontOld);
                        rcClient.top += RECT_INCREMENT;
                        DrawText(hdcPaint, L"This is some GDI text in the default font", -1, &rcClient, 0);

                        // Let's add glow to our text attributes
                        DttOpts.dwFlags |= DTT_GLOWSIZE;
                        DttOpts.iGlowSize = 12; // Default value
                        // CompositedWindow::Window is declared in AeroStyle.xml
                        HTHEME hThemeWindow = OpenThemeData(NULL, L"CompositedWindow::Window");
                        if (hThemeWindow != NULL)
                        {
                            GetThemeInt(hThemeWindow, 0, 0, TMT_TEXTGLOWSIZE, &DttOpts.iGlowSize);
                            CloseThemeData(hThemeWindow);
                        }

                        rcClient.top += RECT_INCREMENT;
                        DrawThemeTextEx(hTheme, hdcPaint, 0, 0, L"This is some text with glow in the default font", -1, 0, &rcClient, &DttOpts);

                        // Now some color(theme) and glow
                        DttOpts.dwFlags |= DTT_TEXTCOLOR;
                        DttOpts.crText   = RGB(255, 255, 255);

                        rcClient.top += RECT_INCREMENT;
                        // CPANEL_TASKLINK is declared in VSStyle.h
                        DrawThemeTextEx(hTheme, hdcPaint, CPANEL_TASKLINK, 0, L"This is some text with glow in a themed font", -1, 0, &rcClient, &DttOpts);

                        DttOpts.dwFlags &= ~DTT_TEXTCOLOR;

                        // Find a particular font and draw using this
                        if (SUCCEEDED(GetThemeSysFont(hTheme, TMT_CAPTIONFONT, &lgFont)))
                        {
                            HFONT hFont = CreateFontIndirect(&lgFont);
                            hFontOld    = (HFONT) SelectObject(hdcPaint, hFont);
                        }
                        
                        rcClient.top += RECT_INCREMENT;
                        DrawText(hdcPaint, L"This is some GDI text in the selected font", -1, &rcClient, 0);
                        
                        rcClient.top += RECT_INCREMENT;
                        DrawThemeTextEx(hTheme, hdcPaint, 0, 0, L"This is some text with glow in the selected font", -1, 0, &rcClient, &DttOpts);
                        
                        if (hFontOld)
                        {                        
                            SelectObject(hdcPaint, hFontOld);
                        }
                        EndBufferedPaint(hBufferedPaint, TRUE);
                    }
                    CloseThemeData(hTheme);
                }
                EndPaint(hWnd, &ps);
            }
            break;
        
        case WM_DESTROY:
            PostQuitMessage(0);
            BufferedPaintUnInit();
            break;
        
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
コード例 #10
0
LRESULT DeskBandWindow::OnPaint(const HDC hdcIn)
{
	if (mHwnd == NULL) return 0;
	HDC hdc = hdcIn;
	PAINTSTRUCT ps;

	if (!hdc)
	{
		hdc = BeginPaint(mHwnd, &ps);
	}

	if (hdc)
	{
		RECT rc;
		GetClientRect(mHwnd, &rc);

		if (m_fCompositionEnabled)
		{		
			HTHEME hTheme;
			if (ThemeReady)
			{
				ZeroMemory(CurrentTheme, sizeof(CurrentTheme));
				wcscat(CurrentTheme, Theme);
				wcscat(CurrentTheme, Toolbar);
				hTheme = OpenThemeData(mHwnd, CurrentTheme);
			}
			else
			{
				hTheme = OpenThemeData(mHwnd, L"TOOLBAR");
			}
			
			
			if (hTheme)
			{
				HDC hdcPaint = NULL;
				HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, NULL, &hdcPaint);
		
				DrawThemeParentBackground(mHwnd, hdcPaint, &rc);

				switch (Mouse)
				{
				case Entered:
					DrawThemeBackground(hTheme, hdcPaint, TP_BUTTON, TS_HOT, &rc, NULL);
					break;
				case ClickDown:
					DrawThemeBackground(hTheme, hdcPaint, TP_BUTTON, TS_PRESSED, &rc, NULL);
					break;
				case Left:
				case ClickUp:
					break;
				}

				HICON m_iconSafe = LoadIcon(g_hDllInst, MAKEINTRESOURCE(IDI_ICON1));
				DrawIconEx(hdcPaint, rc.left+(rc.right-rc.left-30)/2, rc.top+(rc.bottom-rc.top-24)/2, m_iconSafe, 30, 24, 0, NULL, DI_DEFAULTSIZE | DI_NORMAL);
		
				EndBufferedPaint(hBufferedPaint, TRUE);
		
				CloseThemeData(hTheme);
			}
		}
	}

	if (!hdcIn)
	{
		EndPaint(mHwnd, &ps);
	}

	return 0;
};
コード例 #11
0
// ----------------------------------------------------------------------
//  Windows proc for the one and only window in this app.
//
// ----------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HBRUSH   hbrLit = NULL;
    static HBRUSH   hbrUnlit = NULL;
    static HFONT    hFont = NULL;
    static UINT_PTR nTimerId = 101;

    switch (message)
    {
        case WM_CREATE:
        {
            // Make BLACK the transparency color
            SetLayeredWindowAttributes(hWnd, RGB(0,0,0), 0, LWA_COLORKEY);

            // Initialize the DPI scalar.
            InitializeDPIScale(hWnd);

            // Create brushes and font that will be used in WM_PAINT
            hbrLit = CreateSolidBrush(RGB(0,128,255));
            hbrUnlit = CreateSolidBrush(RGB(0,64,128));
            hFont = CreateFont(DPIScale(64), 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, 0, 0, 0, 0, 0, L"Segoe UI");

            // Position at the center of the primary monitor
            POINT const ptZeroZero = {};
            HMONITOR hMonitor = MonitorFromPoint(ptZeroZero, MONITOR_DEFAULTTOPRIMARY);
            MONITORINFO mi = {sizeof(mi)};
            GetMonitorInfo(hMonitor, &mi);

            SIZE const size = { g_currentVolume.cSteps * DPIScale(10), DPIScale(60) };

            POINT const pt = 
            {
                mi.rcMonitor.left + (mi.rcMonitor.left + mi.rcMonitor.right - size.cx) / 2, 
                mi.rcMonitor.top + (mi.rcMonitor.top + mi.rcMonitor.bottom - size.cy) / 2
            };

            SetWindowPos(hWnd, HWND_TOPMOST, pt.x, pt.y, size.cx, size.cy, SWP_SHOWWINDOW);

            break;
        }

        case WM_DESTROY:
        {
            DeleteObject(hbrLit);
            DeleteObject(hbrUnlit);
            DeleteObject(hFont);

            PostQuitMessage(0);
            return 0;
        }

        case WM_ERASEBKGND:
        {
            // Don't do any erasing here.  It's done in WM_PAINT to avoid flicker.
            return 1;
        }

        case WM_VOLUMECHANGE:
        {
            // get the new volume level
            g_pVolumeMonitor->GetLevelInfo(&g_currentVolume);

            // make window visible for 2 seconds
            ShowWindow(hWnd, SW_SHOW);
            InvalidateRect(hWnd, NULL, TRUE);

            nTimerId = SetTimer(hWnd, 101, 2000, NULL);

            return 0;
        }

        case WM_ENDPOINTCHANGE:
        {
            g_pVolumeMonitor->ChangeEndpoint();
            return 0;
        }

        case WM_TIMER:
        {
            // make the window go away
            ShowWindow(hWnd, SW_HIDE);
            KillTimer(hWnd, nTimerId);

            return 0;
        }

        case WM_PAINT:
        {
            PAINTSTRUCT     ps;
            HPAINTBUFFER    hBufferedPaint = NULL;
            RECT            rc;

            GetClientRect(hWnd, &rc);
            HDC hdc = BeginPaint(hWnd, &ps);

            if (g_bDblBuffered)
            {
                // Get doublebuffered DC
                HDC hdcMem;
                hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_COMPOSITED, NULL, &hdcMem);
                if (hBufferedPaint)
                {
                    hdc = hdcMem;
                }
            }

            // black background (transparency color)
            FillRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));

            // Draw LEDs
            for (UINT i = 0; i < (g_currentVolume.cSteps-1); i++)
            {
                RECT const rcLed = { DPIScale(i * 10), DPIScale(10), DPIScale(i * 10 + 8), rc.bottom-DPIScale(15) };

                if ((i < g_currentVolume.nStep) && (!g_currentVolume.bMuted))
                    FillRect(hdc, &rcLed, hbrLit);
                else
                    FillRect(hdc, &rcLed, hbrUnlit);
            }

            if (g_currentVolume.bMuted)
            {
                HGDIOBJ hof = SelectObject(hdc, hFont);
                SetBkMode(hdc, TRANSPARENT);
                SetTextColor(hdc, RGB(255, 64, 64));
                RECT rcText = rc;
                rcText.bottom -= DPIScale(11);
                DrawText(hdc, L"MUTED", -1, &rcText, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
                SelectObject(hdc, hof);
            }

            if (hBufferedPaint)
            {
                // end painting
                BufferedPaintMakeOpaque(hBufferedPaint, NULL);
                EndBufferedPaint(hBufferedPaint, TRUE);
            }

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

    return DefWindowProc(hWnd, message, wParam, lParam);
}