CDialog, Bitmaps zur Runtime zeichnen

DannyP

Mitglied
Hallo,

ich hab ein MFC Programm, dass auf Dialogfeldern basiert. Ein Dialogfeld enthält schon verschiedene Controls. Auf dieses Formular müss zu Runtime Bitmaps aus einer Ressource Datei gezeichnet werden.

Derzeit benutze ich dafür folgenden Code in der OnPaint() Funktion der Dialogklassen:

Code:
CPaintDC dc(this);
  	
  CDC dcbuf;
  CBitmap *buf=new CBitmap;
  
  if( toPaint != -1 )
  {
  	MessageBox( "Zeichnen... ");
  	dcbuf.CreateCompatibleDC(&dc);
  	buf->LoadBitmap( toPaint );
  	dcbuf.SelectObject(buf);
  	dc.BitBlt( TISCH_LINKS+10,TISCH_OBEN+10,13,13, &dcbuf,0,0,SRCCOPY);
  
  }



Die Funktion wird auch korrekt aufgerufen (Zeichnen wird in einer MessageBox aufgerufen), aber er passsiert nichts. Erst nachdem ich das Fenster minimiert habe und wieder maximiert, wird das Bitmap angezeigt.

Kann mir jemand sagen, was ich falsche machen? Das Bitmap muss über andere Controls gezeichnet werden.


Danke im Voraus
Daniel

PS: Sory für erneutes Posting in diesem Forum, aber mein erster Beitrag hab ich aus versehen ins falsche Forum gestellt. Ich werde einen Mod bitten, diesen ersten zu löschen.
 
Der Code scheint soweit ok zu sein. Was ist denn "toPaint" für eine Variable (Typ, Scope) ?
DannyP hat gesagt.:
Das Bitmap muss über andere Controls gezeichnet werden.
Könnte ein Problem sein, da dein Bitmap evt. von den Zeichenroutinen der Controls überschrieben wird. Hast du mal versucht, an einer Position zu zeichnen, an der kein Control liegt?

Gruß
MCoder
 
Hallo,

danke für die Antwort :)

toPaint ist eine int Variable, die als private Membervariable definiert ist. Sie enthält die Resource ID des zu zeichnenden Bitmaps (bspw. IDB_BITMAP1 )

Ja, ich habe schon versucht, das Bitmap an eine Stelle zu zeichnen, an der kein Control liegt. Auch dann muss ich das Fenster erst minimieren und wieder maximieren, damit es erscheint.

Ich habe den Code in der If Anweisung mal durch folgenden ersetzt:
Code:
CStatic *stat = new CStatic();
stat->Create( NULL, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_CENTERIMAGE, CRect(10, 10, 23, 23), this );
CBitmap *b = new CBitmap;
b->LoadBitmap( IDB_CHIP1 );
stat->BringWindowToTop();
stat->SetBitmap((HBITMAP)*b);


Dann erscheint das Bitmap sofort, allerdings hinter anderen Controls, wenn welche an dieser Stelle liegen. Es ist aber zwingend erforderlich, dass es auf ein anderes gezeichnet wird (Auf ein anderes Picture Control, dass fest im Dialog eingebettet ist)

Weiß da vielleicht noch jemand weiter?

Danke schon mal ;)
Daniel
 
hallo,
hab ein ähnliches Problem ich wollt in einem Dialog eine BMP anzeigen lassen, aber ohne den Picture Control!
bloß wie mach ich das am dümmsten?
Code:
CBitmap *b = new CBitmap;
b->LoadBitmap("pic.bmp" );
zum anlegen und laden des Bildes aber wie kann ichs anzeigen lassen
die MSDN hat mich auch nich viel weiter gebracht!:mad:
 
Direktes Zeichnen erfolgt in der OnPaint()-Methode (Handler für WM_PAINT) des Dialogs, die ggf. mit Hilfe des KLassenassistenten noch angelegt werden muss.
Ansonsten erledigt man das Zeichnen von Bitmaps üblicherweise mit Hilfe eines Speicher Device-Contexts. Hier ein kurzes Beispiel:
Code:
CPaintDC dc;

// Speicher Device-Context erzeugen
CDC memDC;
memDC.CreateCompatibleDC(&dc);

// Bitmap laden
CBitmap bitmap;
bitmap.LoadBitmap( ... );

// Bitmap auswählen und vorherige Auswahl merken
CBitmap *pOldBitmap  = memDC.SelectObject(&bitmap);

// Bitmap zeichnen -> Es wird aus dem Speicher Device-Context an
// die entsprechende Position des Dialog Device-Context kopiert
dc.BitBlt( XPos_Dialog, YPos_Dialog, Breite, Hoehe, &memDC, 0, 0, SRCCOPY);

// Vorherige Einstellung wiederherstellen
memDC.SelectObject(pOldBitmap);

Gruß
MCoder
 
so hab ich mir das jetzt geadacht, dummer weise seh ich kein bild!
oben links is ja eigentlich x und y = 1 oder nich?
und was ich auch nich versteh wenn ich ein bild lade per LoadBitmap(...) wieso muss ich dann noch die Höhe und Breite angeben?
eigentlich müst doch die Classen Variablen diese haben oder?
Code:
void CDialog_testDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // Gerätekontext für Zeichnen

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Symbol in Client-Rechteck zentrieren
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Symbol zeichnen
		dc.DrawIcon(x, y, m_hIcon);


	int XPos_Dialog=1;
	int YPos_Dialog=1;
	int Hoehe=200;
	int Breite=412;
	// Speicher Device-Context erzeugen
	CDC memDC;
	memDC.CreateCompatibleDC(&dc);

	// Bitmap laden
	CBitmap bitmap;
	bitmap.LoadBitmap("pic.bmp");

	// Bitmap auswählen und vorherige Auswahl merken
	CBitmap *pOldBitmap  = memDC.SelectObject(&bitmap);

	// Bitmap zeichnen -> Es wird aus dem Speicher Device-Context an
	// die entsprechende Position des Dialog Device-Context kopiert
	dc.BitBlt( XPos_Dialog, YPos_Dialog, Breite, Hoehe, &memDC, 0, 0, SRCCOPY);

	// Vorherige Einstellung wiederherstellen
	memDC.SelectObject(pOldBitmap);


	}
	else
	{
		CDialog::OnPaint();
	}

}
 
Du musst den Code zum Zeichnen in den else-Zweig von "if (IsIconic())" schreiben, sonst er nur ausgeführt, wenn das Fenster minimiert ist. Wahrscheinlich etwas unpraktisch :)

Die Größe bekommt man mit etwas zusätzlicher Programmierung auch aus dem CBitmap-Objekt heraus:
Code:
BITMAP bm;
bitmap.GetBitmap(&bm);

int Hoehe  = bm.bmHeight;
int Breite = bm.bmWidth;


Gruß
MCoder
 
also ich weiß nich was ich hier falsch mache aber hier code:
Code:
void CTalsperreDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // Gerätekontext für Zeichnen
	
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Symbol in Client-Rechteck zentrieren
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Symbol zeichnen
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{

		CDialog::OnPaint();
		
		CPaintDC dc(this);
		int XPos_Dialog=1;
		int YPos_Dialog=1;
		int Hoehe=200;
		int Breite=412;
		// Speicher Device-Context erzeugen
		CDC memDC;
		memDC.CreateCompatibleDC(&dc);

		// Bitmap laden
		CBitmap bitmap;
		bitmap.LoadBitmap("pic.bmp");

		// Bitmap auswählen und vorherige Auswahl merken
		CBitmap *pOldBitmap  = memDC.SelectObject(&bitmap);

		// Bitmap zeichnen -> Es wird aus dem Speicher Device-Context an
		// die entsprechende Position des Dialog Device-Context kopiert
		dc.BitBlt( XPos_Dialog, YPos_Dialog, Breite, Hoehe, &memDC, 0, 0, SRCCOPY);

		// Vorherige Einstellung wiederherstellen
		memDC.SelectObject(pOldBitmap);
	}

}

und wenn ich das Programm starte dann passiert nichts, ich nichts ausser dem OK und dem Abbrechen Button :confused:
und die größe lass ich erstmal per Hand zugewiesen!

edit: wenn ich die Abmessung vom Objekt hole kommt nen Debug Fehler in der GetBitmap Funktion!
da fehlt sicher noch was ;-)
 
Zuletzt bearbeitet:
Hallo,
zwei Punkte:

1. CBitmap::LoadBitmap() lädt keine Bitmap-Dateien sondern nur Resourcen. Schaue dir dazu noch mal die Beschreibung in der MSDN an. Zum Laden von Dateien kannst du LoadImage() verwenden (siehe Beispiel).
Daher rührt übrigens auch der Absturz bei GetBitmap: Dein CBitmap-Objekt enthält keine gültigen Daten.

2. Die Zeile CDialog::OnPaint(); darf nicht am Anfang sondern muss am Ende deines Codes stehen.
Code:
// Speicher Device-Context erzeugen
CDC memDC;
memDC.CreateCompatibleDC(&dc);

// Bitmap laden
HBITMAP hbm = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
                                    _T("pic.bmp"),
                                    IMAGE_BITMAP,
                                    0,
                                    0,
                                    LR_LOADFROMFILE | LR_DEFAULTSIZE );

// Bitmap auswählen und vorherige Auswahl merken
CBitmap *pOldBitmap  = memDC.SelectObject(CBitmap::FromHandle(hbm));

// Abmessungen ermitteln und Bitmap zeichnen
BITMAP bm;
(CBitmap::FromHandle(hbm))->GetBitmap(&bm);

dc.BitBlt( 1, 1, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);

// Vorherige Einstellung wiederherstellen
memDC.SelectObject(pOldBitmap);

// HBITMAP freigeben
::DeleteObject(hbm);
Gruß
MCoder
 
gut jetzte gehts, ich bewuntere euch zwar immer wieder wo man sowas her weiß weil ohne Lehrer lernt man ja sowas nicht!
aber Danke
MFG Mario
 

Neue Beiträge

Zurück