Как сделать CRichEditCtrl на CDC с прозрачным backgorund? (МФЦ)
Мне нужна помощь с рендерингом контента 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 уже нарисованы вещи. Я пытался найти в Интернете какую-либо помощь о метафайлах и прозрачности, но не нашел ничего адекватного. Я буду благодарен за любую помощь.
2 ответа
Я не очень уверен насчет MetaFiles, но я сделал нечто подобное с EMF с прямым WinAPI, который работает - звоните 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 и 8 было разное поведение - после этого все работает нормально. Спасибо за помощь. С наилучшими пожеланиями.