用C++品嘗Vista美味[4]

字號(hào):

繪制文本
    在毛玻璃效果上繪制文本涉及以下步驟:
    ·創(chuàng)建一個(gè)用于雙緩沖繪制的內(nèi)存DC。
    ·創(chuàng)建一個(gè)32位色深的DIB,并選入DC。
    ·用DrawThemeTextEx()把文本繪制在內(nèi)存中的DIB上。
    ·用BitBit()把文本復(fù)制到屏幕。
    因?yàn)槲覀兊睦L制代碼將會(huì)因?yàn)閏omposition是否打開(kāi)而有所不同,所以需要在繪制期間檢查composition狀態(tài)。檢查狀態(tài)的API為DwmIsCompositionEnabled(),如果API執(zhí)行失敗,在返回值中就不會(huì)指示出打開(kāi)狀態(tài),但CMainFrame中有一個(gè)包裝好的函數(shù)IsCompositionEnabled(),非常易于使用:
    bool CMainFrame::IsCompositionEnabled() const
    {
    HRESULT hr;
    BOOL bEnabled;
    hr = DwmIsCompositionEnabled(&bEnabled);
    return SUCCEEDED(hr) && bEnabled;
    }
    現(xiàn)在,讓我們?cè)贆z查一遍OnEraseBkgnd(),看看每個(gè)步驟是否都完成了。這個(gè)程序是一個(gè)時(shí)鐘程序,所以先用GetTimeFormat()獲取當(dāng)前時(shí)間:
    BOOL CMainFrame::OnEraseBkgnd(HDC hdc)
    {
    CDCHandle dc = hdc;
    CRect rcClient, rcText;
    GetClientRect ( rcClient );
    dc.FillSolidRect ( rcClient, RGB(0,0,0) );
    rcText = rcClient;
    rcText.top = rcText.bottom - 100;
    //獲取當(dāng)前時(shí)間
    TCHAR szTime[64];
    GetTimeFormat(LOCALE_USER_DEFAULT,0,NULL,NULL,szTime,_countof(szTime));
    ……
    }
    如果composition打開(kāi),我們就進(jìn)行合成繪制步驟,先設(shè)置好一個(gè)內(nèi)存DC:
    if ( IsCompositionEnabled() )
    {
    //設(shè)置一個(gè)我們將繪制的內(nèi)存DC和位圖
    CDC dcMem;
    CBitmap bmp;
    BITMAPINFO dib = {0};
    dcMem.CreateCompatibleDC ( dc );
    接下來(lái),填充BITMAPINFO結(jié)構(gòu)以得到一個(gè)32位色深位圖,且與毛玻璃區(qū)域的高寬相同。此處需重點(diǎn)留意的是,位圖高度(即BITMAPINFOHEADER的biHeight成員)為負(fù)數(shù),這是因?yàn)橥ǔG闆r下BMP是按照從下至上的順序存儲(chǔ)在內(nèi)存中的,但DrawThemeTextEx()需要的位圖順序是從上至下,所以要把高度設(shè)為負(fù)數(shù)。
    dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    dib.bmiHeader.biWidth = rcText.Width();
    dib.bmiHeader.biHeight = -rcText.Height();
    dib.bmiHeader.biPlanes = 1;
    dib.bmiHeader.biBitCount = 32;
    dib.bmiHeader.biCompression = BI_RGB;
    bmp.CreateDIBSection (dc,&dib,DIB_RGB_COLORS,NULL,NULL,0);
    現(xiàn)在,我們的圖形對(duì)象就創(chuàng)建好了,可以開(kāi)始繪制文本了。
    //設(shè)置好DC
    dcMem.SelectBitmap ( bmp );
    dcMem.SelectFont ( m_font );
    //繪制文本
    DTTS dto = { sizeof(DTTS) };
    const UINT uFormat = DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_NOPREFIX;
    CRect rcText2 = rcText;
    dto.dwFlags = DTT_COMPOSITED|DTT_GLOWSIZE;
    dto.iGlowSize = 10;
    rcText2 -= rcText2.TopLeft(); //相同的rect,但左上角為(0,0)
    DrawThemeTextEx ( m_hTheme, dcMem, 0, 0, CT2CW(szTime), -1,
    uFormat, rcText2, &dto );
    DTTS結(jié)構(gòu)控制了文本怎樣被繪制,在標(biāo)志中我們指明了要繪制"合成文本",并讓文本有一個(gè)發(fā)光效果。最后,把內(nèi)存中的位圖貼到屏幕上:
    //將文本繪制到屏幕上。
    BitBlt ( dc, rcText.left, rcText.top, rcText.Width(), rcText.Height(), dcMem, 0, 0, SRCCOPY );
    } // end if (IsCompositionEnabled())