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


  • Mod

    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...


  • Mod

    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...


  • Mod

    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);
    

Anmelden zum Antworten