如何在带有透明背景的CDC上呈现CRichEditCtrl?(MFC)

如何在带有透明背景的CDC上呈现CRichEditCtrl?(MFC),mfc,transparency,gdi,metafile,cricheditctrl,Mfc,Transparency,Gdi,Metafile,Cricheditctrl,我需要在屏幕上显示并打印的图形上下文中使用透明背景渲染CRichEditCtrl内容的帮助。 现在我有以下代码,除了透明度问题外,这些代码运行良好: CRichEditCtrl ctrl; // my CRichEditCtrl CDC *dc; // - my graphical context dc->SetBkMode(TRANSPARENT); dc->DPtoHIMETRIC(&targetSize); CRect cHiMetricRect( 0, 0, ori

我需要在屏幕上显示并打印的图形上下文中使用透明背景渲染CRichEditCtrl内容的帮助。 现在我有以下代码,除了透明度问题外,这些代码运行良好:

CRichEditCtrl ctrl; // my CRichEditCtrl
CDC *dc; // - my graphical context

dc->SetBkMode(TRANSPARENT);
dc->DPtoHIMETRIC(&targetSize);
CRect cHiMetricRect( 0, 0, origSize.cx*factor,origSize.cy*factor);
CRect cTwipsRect( 0, 0, (TWIPS_INCH * targetSize.cx + HIMETRIC_INCH / 2) / HIMETRIC_INCH, (TWIPS_INCH * targetSize.cy + HIMETRIC_INCH / 2) / HIMETRIC_INCH);

CMetaFileDC metaFile;
metaFile.CreateEnhanced( dc, NULL, cHiMetricRect, NULL );
metaFile.SetBkMode(TRANSPARENT);
metaFile.SetAttribDC( dc->m_hDC );

FORMATRANGE stFR;
stFR.hdcTarget = stFR.hdc = metaFile.m_hDC; 
stFR.rcPage = stFR.rc = cTwipsRect;
stFR.chrg.cpMin = 0;
stFR.chrg.cpMax = -1;

ctrl.FormatRange( &stFR, TRUE);
ctrl.FormatRange( NULL, TRUE);

HENHMETAFILE hMetaFile = metaFile.CloseEnhanced();

dc->PlayMetaFile(hMetaFile,&cr);
DeleteEnhMetaFile(hMetaFile);
我需要以透明的方式呈现此文本,因为已经有东西绘制在我的DC上。
我试图在网上搜索有关图元文件和透明度的任何帮助,但没有找到足够的帮助。我将非常感谢您的帮助。

我对图元文件不是很确定,但我已经使用straight WinAPI对EMFs做了类似的事情,它确实有效——调用
EnumEnhMetaFile
而不是
PlayMetaFile
,例如:

BOOL bFirstTime = TRUE;
EnumEnhMetaFile(hDC, m_hEmf, (ENHMFENUMPROC)EmfEnumProc_Play_TranspBackground, &bFirstTime, &rc);
其中,EnumProc定义为

int CALLBACK EmfEnumProc_Play_TranspBackground(HDC hDC, LPHANDLETABLE lpHTable, LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData)
{   BOOL bOK;
    if (lpEMFR->iType == EMR_SETBKMODE)
    {   EMRSETBKMODE* lpEMRBkMode = (EMRSETBKMODE*) lpEMFR;

        if (lpEMRBkMode->iMode == OPAQUE)
        {   EMRSETBKMODE EmrBkMode;
            EmrBkMode.emr.iType = EMR_SETBKMODE;
            EmrBkMode.emr.nSize = (sizeof(EmrBkMode) % 4 == 0 ? sizeof(EmrBkMode) : (((sizeof(EmrBkMode) / 4) + 1) * 4));
            EmrBkMode.iMode = TRANSPARENT;
            bOK = PlayEnhMetaFileRecord(hDC, lpHTable, (LPENHMETARECORD)&EmrBkMode, (UINT)nObj);
            return bOK;
        }
    }

    bOK = PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj);

    if (lpEMFR->iType == EMR_HEADER)
    {   BOOL* pbFirstTime = (BOOL*)lpData;
        if (*pbFirstTime)
        {   EMRSETBKMODE EmrBkMode;
            EmrBkMode.emr.iType = EMR_SETBKMODE;
            EmrBkMode.emr.nSize = (sizeof(EmrBkMode) % 4 == 0 ? sizeof(EmrBkMode) : (((sizeof(EmrBkMode) / 4) + 1) * 4));
            EmrBkMode.iMode = TRANSPARENT;
            PlayEnhMetaFileRecord(hDC, lpHTable, (LPENHMETARECORD)&EmrBkMode, (UINT)nObj);

            *pbFirstTime = FALSE;
        }
    }

    return bOK;
}

我对图元文件不是很确定,但我已经使用straight WinAPI对EMFs做了类似的操作,它确实可以工作——调用
EnumEnhMetaFile
,而不是
PlayMetaFile
,例如:

BOOL bFirstTime = TRUE;
EnumEnhMetaFile(hDC, m_hEmf, (ENHMFENUMPROC)EmfEnumProc_Play_TranspBackground, &bFirstTime, &rc);
其中,EnumProc定义为

int CALLBACK EmfEnumProc_Play_TranspBackground(HDC hDC, LPHANDLETABLE lpHTable, LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData)
{   BOOL bOK;
    if (lpEMFR->iType == EMR_SETBKMODE)
    {   EMRSETBKMODE* lpEMRBkMode = (EMRSETBKMODE*) lpEMFR;

        if (lpEMRBkMode->iMode == OPAQUE)
        {   EMRSETBKMODE EmrBkMode;
            EmrBkMode.emr.iType = EMR_SETBKMODE;
            EmrBkMode.emr.nSize = (sizeof(EmrBkMode) % 4 == 0 ? sizeof(EmrBkMode) : (((sizeof(EmrBkMode) / 4) + 1) * 4));
            EmrBkMode.iMode = TRANSPARENT;
            bOK = PlayEnhMetaFileRecord(hDC, lpHTable, (LPENHMETARECORD)&EmrBkMode, (UINT)nObj);
            return bOK;
        }
    }

    bOK = PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj);

    if (lpEMFR->iType == EMR_HEADER)
    {   BOOL* pbFirstTime = (BOOL*)lpData;
        if (*pbFirstTime)
        {   EMRSETBKMODE EmrBkMode;
            EmrBkMode.emr.iType = EMR_SETBKMODE;
            EmrBkMode.emr.nSize = (sizeof(EmrBkMode) % 4 == 0 ? sizeof(EmrBkMode) : (((sizeof(EmrBkMode) / 4) + 1) * 4));
            EmrBkMode.iMode = TRANSPARENT;
            PlayEnhMetaFileRecord(hDC, lpHTable, (LPENHMETARECORD)&EmrBkMode, (UINT)nObj);

            *pbFirstTime = FALSE;
        }
    }

    return bOK;
}

我使用了EnumEnhMetaFile函数:

EnumEnhMetaFile(dc->m_hDC, hMetaFile, myMetafileProc, NULL, rect  );
然后我使用回调过程来检索图元文件的每条记录:

int metafileProc( HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData) {
if ( lpEMFR->iType == EMR_EXTTEXTOUTW ) {
        COLORREF_STRUCT *c = (COLORREF_STRUCT *)&(lastBgColor);
        EMR_EXTTEXTOUTW_STRUCT *s = (EMR_EXTTEXTOUTW_STRUCT *)lpEMFR;
        s->textStruct.options = 0x00;
        if ( bgColorFlag ) {
            bgColorFlag = false;
            renderRect( hDC, s->textStruct.rect, c );
        }
        PlayEnhMetaFileRecord( hDC, lpHTable, lpEMFR, nObj );
} else if ( lpEMFR->iType == EMR_SETBKCOLOR ) {
    BYTE *ptr = (BYTE*)lpEMFR;
    COLORREF temp = *((COLORREF*)(ptr+8));
    if ( temp != 0xFFFFFF ) {
        lastBgColor = temp;
        bgColorFlag = true;
    }
}
return 1;
}

其中renderRect(hDC,s->textStruct.rect,c)是一个用c颜色绘制透明背景的函数。我必须为文本设置零选项标志,因为在Windows XP、Windows 7和Windows 8中有不同的行为-之后一切正常。谢谢你的帮助。致以最诚挚的问候。

我使用了EnumenMetaFile函数:

EnumEnhMetaFile(dc->m_hDC, hMetaFile, myMetafileProc, NULL, rect  );
然后我使用回调过程来检索图元文件的每条记录:

int metafileProc( HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData) {
if ( lpEMFR->iType == EMR_EXTTEXTOUTW ) {
        COLORREF_STRUCT *c = (COLORREF_STRUCT *)&(lastBgColor);
        EMR_EXTTEXTOUTW_STRUCT *s = (EMR_EXTTEXTOUTW_STRUCT *)lpEMFR;
        s->textStruct.options = 0x00;
        if ( bgColorFlag ) {
            bgColorFlag = false;
            renderRect( hDC, s->textStruct.rect, c );
        }
        PlayEnhMetaFileRecord( hDC, lpHTable, lpEMFR, nObj );
} else if ( lpEMFR->iType == EMR_SETBKCOLOR ) {
    BYTE *ptr = (BYTE*)lpEMFR;
    COLORREF temp = *((COLORREF*)(ptr+8));
    if ( temp != 0xFFFFFF ) {
        lastBgColor = temp;
        bgColorFlag = true;
    }
}
return 1;
}
其中renderRect(hDC,s->textStruct.rect,c)是一个用c颜色绘制透明背景的函数。我必须为文本设置零选项标志,因为在Windows XP、Windows 7和Windows 8中有不同的行为-之后一切正常。谢谢你的帮助。致以最良好的祝愿