Text direkt in Memory schreiben
-
Hallo,
ich hab da ein kleines Problem was ich optimieren möchte. Ich brauche eine art Textlayer in als Bitmap Array.
unsigned int TextArray[100*100*4]; z.B. das wird dynamisch angelegt
mit dem folgenden code sichere ich mir zur Laufzeit den Hintergrund vom Bildschirm, lösche die Fläche,schreibe den Text ganz normal da rein, kopiere mir den neuen Bildschirm in mein Memory Bereich und restauriere danach den zuvor gespeicherten Hintergrund. Alles über BitBlitting was recht schnell geht aber ich glaube der Weg ist etwas umständlich. Erstmal der Code.
void CCaptureZ_ButtonCtrl::GrabText(CDC *pDC,int sx,int sy,int nWidth,int nHeight) { CDC memDC; CBitmap memBmp; CBitmap *pOldmemDC; // copy background to memDC memDC.CreateCompatibleDC(pDC); memBmp.CreateCompatibleBitmap(pDC,nWidth,nHeight); pOldmemDC = memDC.SelectObject(&memBmp); BITMAPINFO bmi[1]; bmi[0].bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi[0].bmiHeader.biWidth = nWidth; bmi[0].bmiHeader.biHeight = nHeight; bmi[0].bmiHeader.biPlanes = 1; bmi[0].bmiHeader.biBitCount = 32; // 32 bmi[0].bmiHeader.biCompression = BI_RGB; bmi[0].bmiHeader.biSizeImage = 0; bmi[0].bmiHeader.biXPelsPerMeter = 75; bmi[0].bmiHeader.biYPelsPerMeter = 75; bmi[0].bmiHeader.biClrUsed = 0; bmi[0].bmiHeader.biClrImportant = 0; int srcX = 0; int srcY = 0; int dstX = 0; int dstY = 0; int dstW = nWidth; int dstH = nHeight; // nachdem der Background gesichert ist, löschen wir mal den Bereich kurz unsigned int FillColor = RGB_MAKE(0,0,0); for (int py=0;py< nHeight;py++) for (int px=0;px< nWidth;px++) mem_Text_Bitmap_Ptr[px+py*nWidth] = FillColor; CRect rect; rect.left = 0; rect.top = 0; rect.right = nWidth; rect.bottom = nHeight * 0.8f; // erstmal per BitBlitting löschen, da weiß ich das es weiß ist !!! // copy Image to memDC // das hier kopiert den hintergrund aus dem speicher in memDC SetDIBitsToDevice(memDC,dstX, dstY, dstW, dstH, srcX, srcY, 0, dstH, mem_Text_Bitmap_Ptr, bmi, DIB_RGB_COLORS); // draw memDC to screen // das hier malt das bild auf den bildschirm von memDC zu pCD pDC->BitBlt( sx, sy,nWidth,nHeight,&memDC,0,0,SRCCOPY); // Jetzt mal den Text auf den weißen Hintergrung DrawText(pDC,rect,ODS_SELECTED); // state = ODS_SELECTED // kopiert vom schirm in memcd memDC.BitBlt(0,0,nWidth,nHeight,pDC, sx, sy,SRCCOPY); // wandelt memdc in bitmap memory // in mem_Text_Bitmap_Ptr ist jetzt das Bitmap vom Text mit Weißem Hintergrund GetDIBits(memDC,memBmp,0,nHeight,mem_Text_Bitmap_Ptr,bmi,DIB_RGB_COLORS); if(Flag_Background_Saved) { // jetzt erstmal den Background drüber malen damit man während der Button berechnung nix sieht // copy Image to memDC // das hier kopiert den hintergrund aus dem speicher in memDC SetDIBitsToDevice(memDC,dstX, dstY, dstW, dstH, srcX, srcY, 0, dstH, mem_ButtonBackground_Ptr, bmi, DIB_RGB_COLORS); // draw memDC to screen // das hier malt das bild auf den bildschirm von memDC zu pCD pDC->BitBlt( sx, sy,nWidth,nHeight,&memDC,0,0,SRCCOPY); } }die Funktion DrawText(pDC,rect,ODS_SELECTED) schreibt den Text auf den Schirm, das geht auch gut, jezt hab ich mal probiert mit .TextOut() direkt in den Speicher zu schreiben aber der Text reagiert auf keine Formatierung wie Größe und Schriftart, hat da jemand ein Beispiel ?
hier noch die DrawText funktion
void CCaptureZ_ButtonCtrl::DrawText(CDC *pDC,CRect rect,UINT state) { if (!m_ButtonText.IsEmpty()) { CSize Extent = pDC->GetTextExtent(m_ButtonText/*strText*/); CPoint pt( rect.CenterPoint().x - Extent.cx/2 - 3, rect.CenterPoint().y - Extent.cy/2 - 2 ); if (state & ODS_SELECTED) pt.Offset(1,1); int nMode = pDC->SetBkMode(TRANSPARENT); CFont *pOldFont = SelectStockFont( pDC ); if (state & ODS_DISABLED) pDC->DrawState( pt,Extent,m_ButtonText,DSS_DISABLED,TRUE,0,(HBRUSH)NULL); else pDC->SetTextColor(RGB_MAKE(255,255,255)); pDC->TextOut(pt.x, pt.y, m_ButtonText); pDC->SelectObject(pOldFont); pDC->SetBkMode(nMode); } }thx
Micha
-
Und wie hast Du es versucht direkt über den memDC abzuwickeln?
Du musst nicht den realen DC sichern, dorthinein schreiben sichern und wieder den alten Inhalt zurückschaufeln. Es muss auch direkt über einen memDC gehen.
Wie hast Du es denn gemacht? Evtl. hast Du nur enmal den DC verwechselt beim SelectObject.
-
hier ist mal die alternative mit im code:
/* das alles kann wech... // erstmal per BitBlitting löschen, da weiß ich das es weiß ist !!! // copy Image to memDC // das hier kopiert den hintergrund aus dem speicher in memDC SetDIBitsToDevice(memDC,dstX, dstY, dstW, dstH, srcX, srcY, 0, dstH, mem_Text_Bitmap_Ptr, bmi, DIB_RGB_COLORS); // draw memDC to screen // das hier malt das bild auf den bildschirm von memDC zu pCD pDC->BitBlt( sx, sy,nWidth,nHeight,&memDC,0,0,SRCCOPY); // Jetzt mal den Text auf den weißen Hintergrung DrawText(pDC,rect,ODS_SELECTED); // state = ODS_SELECTED // kopiert vom schirm in memcd memDC.BitBlt(0,0,nWidth,nHeight,pDC, sx, sy,SRCCOPY); // wandelt memdc in bitmap memory // in mem_Text_Bitmap_Ptr ist jetzt das Bitmap vom Text mit Weißem Hintergrund GetDIBits(memDC,memBmp,0,nHeight,mem_Text_Bitmap_Ptr,bmi,DIB_RGB_COLORS); */ bis hierhin memDC.TextOut(10,10,"Hallo"); GetDIBits(memDC,memBmp,0,nHeight,mem_Text_Bitmap_Ptr,bmi,DIB_RGB_COLORS);der Text wird auch angezeigt, später wenn ich die Bitmap darstelle, auch an Position 10,10 px und da steht auch Hallo, das Problem ist, ich finde keine Funktion wie ich Textgröße oder Schriftart einstellen kann.
und in der DrawText wird es scheinbar so gesetzt:
int nMode = pDC->SetBkMode(TRANSPARENT); CFont *pOldFont = SelectStockFont( pDC ); if (state & ODS_DISABLED) pDC->DrawState( pt,Extent,m_ButtonText,DSS_DISABLED,TRUE,0,(HBRUSH)NULL); else pDC->SetTextColor(RGB_MAKE(255,255,255)); pDC->TextOut(pt.x, pt.y, m_ButtonText); pDC->SelectObject(pOldFont); pDC->SetBkMode(nMode);aber selbst wenn ich das vor mein TextOut setze reagiert das da nicht drauf.
Ich muß sagen mit diesen Select Object geschichten da steig ich nicht ganz durch...
-
Du musst einen entsprechenden Font erzeugen (CreateFontIndirect) und diesen selektieren (SelectObject), nicht vergessen vor zersören des DCs den alten Font (der durch SelectObject returniert wird) wieder zu selektieren.
-
CreateFont ja das hab ich auch mal gefunden, das Problem ist:
dadurch das ich im Eigenschaftsfenster das Stock Prop Objekt habe öffnet sich sobald ich die Eigenschaft ändere, bzw. ist schon von vorn herein im Eigenschaftsdialog ein eigener Reiter für Font und auf den hab ich nicht so eifach Zugriff. Ich müßte da also schauen was eingestellt ist und das dann wieder in das neue Übertragen.
Oder... ich überlege grad... kann ich nicht das StockFont einfach kopieren? Nur
wenn eine Kopie laufen würde, warum nicht gleich das alte? Irgendwo ist da noch der Wurm drin.Außerdem, der pDC ist doch der gleiche wenn ich in meine DrawText() springe , da weise ich dem pDC doch auch das StockFont zu und habe immer nur Arial Type
würde heißen:
pDC->TextOut(pt.x, pt.y, m_ButtonText);
geht weil vorher dem pDC
CFont *pOldFont = SelectStockFont( pDC );
der StockFont zugeteilt wird aber ich über
memDC.TextOut(10,10,"Hallo");
memDC das nicht weiß ?
und somit ein
CFont *pOldFont = SelectStockFont( memDC );
sollte das tun? bin ich da richtig ? na ich teste mal und gucke ob ich das jetzt verstanden habe...

Danke erstmal
-
vielleicht ist es zu spät aber alles was ich bis jetzt probiert hab ging noch nicht richtig...
das hier ist ggf. der Richtige Ansatz
// Stock Font für pDC wird so gesetzt // CFont *pOldFont = SelectStockFont( pDC ); // dann versuch ich mal den pDC StockFont zu kopieren ? // weil ich setzte den ja nicht selber, der wird per Dialog gesetzt LOGFONT myFont; // hier myFont. Variablen setzen pDC->GetFontData(0,0,&myFont,0); HFONT m_Font = CreateFontIndirect(&myFont); memDC.SelectObject(m_Font); // geht teilweise, Farbe usw aber Schriftart stimmt nicht memDC.SetTextColor(RGB_MAKE(255,255,255)); memDC.SetBkColor(RGB_MAKE(0,0,0)); memDC.TextOut(10,10, m_ButtonText); GetDIBits(memDC,memBmp,0,nHeight,mem_Text_Bitmap_Ptr,bmi,DIB_RGB_COLORS);es Erzeugt einen Font wie ich ihn noch nie gesehen habe
aber es ist auf keinen Fall eine Kopie des Richtigen aber Arial ist es nicht mehr also denke ich das geht den richtigen Weg...
-
Setze alle Werte der LOGFONT Struktur auf 0, dann fülle die Struktur aus, mit dem Font Namen und der Größe. Dann führe CreateFontIndirect aus.
-
Danke dir erstmal,
die Lösung ist viel einfacher

// hier da die Zeile : memDC.SelectObject(SelectStockFont( pDC )); memDC.SetTextColor(RGB_MAKE(255,255,255)); memDC.SetBkColor(RGB_MAKE(0,0,0)); memDC.TextOut(pt.x,pt.y, m_ButtonText); GetDIBits(memDC,memBmp,0,nHeight,mem_Text_Bitmap_Ptr,bmi,DIB_RGB_COLORS);