[C++] Transparente Bilder im Bildschirmschoner zeichnen

Jellysheep

Erfahrenes Mitglied
Hi,
ich wollte grade einen Bildschirmschoner programmieren, der den normalen Desktop zeigt und drüber ein transparentes Bild hin- und herfährt. Normale Bitmaps zu zeichnen schaff ich schon, nur bei Bildern mit Transparenz scheitere ich... Wie mache ich das am Besten?
 
Laut dem hier kann man ein PNG in ein CImage laden, aber dafür braucht man ATL und das habe ich bei meiner Express Edition von Visual C++ nicht dabei...

Ich hab gesehen, dass man mit GDI+ PNG-Grafiken laden kann.
Kann jemand dazu einen Beispielcode posten?
 
Ich mach jetzt das Ganze mit CxImage, das kann PNGs...
Aber ich hab zwei Probleme:
1. Ich male erst den Screenshot und dann ein PNG drüber, aber das flackert. Jetzt wollte ich ein Zwischenbild erstellen, da den Screenshot und das PNG reinmalen und das Ganze dann in den Screensaver malen. Code:
Code:
HDC tmp = CreateCompatibleDC(dc);
img2.Draw2(tmp, R2);
img.Draw2(tmp, R);
BitBlt(dc, 0, 0, 1024, 768, tmp, 0, 0, SRCCOPY);
Aber das macht nur einen schwarzen Hintergrund... Woran liegt das?

2. Das PNG erscheint in einem schrecklichen Zustand (siehe Screenshot) Muss ich da noch Transparenz aktivieren oder so?
Code dazu ist:
Code:
CxImage img;
img.Load(path, 0);
R = RECT();
R.bottom = 667;
R.left = 0;
R.right = 667;
R.top = 0;
img.Draw2(dc, R);
 

Anhänge

  • Screenshot.jpg
    Screenshot.jpg
    96,8 KB · Aufrufe: 60
Kann man denn nicht irgendwie zwei HDCs in eins malen und das gemeinsame dann auf den Bildschirm bringen?
 
Wäre denn folgender Code richtig (dc ist der Gerätekontext des Screensavers):
Code:
HDC tmp = CreateCompatibleDC(dc);
HBITMAP hbm = (HBITMAP)LoadImage(NULL,"C:\\Bitmaps\\Screenshot.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
HDC hdcBitmap = CreateCompatibleDC( tmp );
HBITMAP hbmOld = (HBITMAP)SelectObject( hdcBitmap, hbm );
BitBlt(tmp, 0, 0, 1024, 768, hdcBitmap, 0, 0, SRCCOPY);
BitBlt(dc, 0, 0, 1024, 768, tmp, 0, 0, SRCCOPY);
SelectObject( hdcBitmap, hbmOld );
DeleteDC( hdcBitmap );
DeleteDC(tmp);
 
Wie würde man denn normalerweise zwei HDCs (zwei Bilder) in einem dritten zwischenspeichern und gemeinsam auf einen vierten(Bildschirm) blitten?
 
Ich speichere zurzeit den Screenshot in einem Bitmap auf der Festplatte und lade ihn dann wieder rein.
Kann ich auch ein HBITMAP oder ein HDC des Screenshots erstellen?
 
Problem gelöst - ich habe vor dem ersten BitBlt ein SelectObject mit den zwei zuvor definierten Variablen eingefügt.
 
Jetzt habe ich noch eine Frage, aber nur noch eine.. oder zwei? ;)
Mit CxImage war das Ganze recht langsam, und ich hab jetzt die Möglichkeit, CImage zu verwenden und wollte das ausprobieren, aber das malt nicht ganz mit Transparenz (im Anhang).
Wie bekommt man das besser hin?

Dann wollte ich mal schauen, wie schnell der ohne Seifenblase zeichnen ist (hab einen leeren DC zeichnen lassen), und der war relativ langsam und hat nach ca. 500-mal (unterschiedlich) aufgehört, das nächste schwarze Quadrat zu zeigen, die CPU-Auslastung war aber normal, woran liegt das? :confused:
Die Bildschirmschoner von Microsoft zum Beispiel sind viel schneller in der Aktualisierung des Bildes...
 

Anhänge

  • Seifenblase.bmp
    104,2 KB · Aufrufe: 62
Weiß niemand Antworten auf meine Fragen oder einen anderen Lösungsansatz meines Problems?

Ich poste mal meinen bisherigen Code, vielleicht hilft das weiter:
Code:
struct SCREEN{
public:
	HBITMAP hbmp;
	HDC hdc;
};

SCREEN getScreen(HDC src){
	HDC hdcTemp = CreateCompatibleDC(src);
	HBITMAP hbmpTemp = CreateCompatibleBitmap(src, 1024, 768);
	SelectObject(hdcTemp, hbmpTemp);
	BitBlt(hdcTemp, 0, 0, 1024, 768, src, 0, 0, SRCCOPY);
	SCREEN scr;
	scr.hbmp = hbmpTemp;
	scr.hdc = hdcTemp;
	return scr;
};

CImage img;
char *path = "C:\\seifenblase.png";
bool flag = true;
SCREEN screen;
int X = 0;
int Y = 0;
int stepX = 5;
int stepY = 5;

long WINAPI ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam,LPARAM lParam)
{
	HDC dc = GetDC(hWnd);
	HDC tmp = CreateCompatibleDC(dc);
	HBITMAP hbm = CreateCompatibleBitmap(dc, 1024, 768);
	SelectObject(tmp, hbm);
	switch(message)
	{
		case WM_CREATE:
			UINT timer_id;
			SetTimer(hWnd,timer_id,100,NULL);
			screen = getScreen(dc);
			img.Load(path);
			break;

		case WM_TIMER:
			{
			

			// alles in HDC tmp schreiben

			if(flag == true){
				BitBlt(dc, 0, 0, 1024, 768, screen.hdc, 0, 0, SRCCOPY);
				flag = false;
			}

			X += stepX;
			Y += stepY;

			BitBlt(tmp, 0, 0, 200+stepX, 200+stepY, screen.hdc, X-stepX, Y-stepY, SRCCOPY);

			img.Draw(tmp, 0, 0, 200, 200);

			// tmp in dc kopieren

			BitBlt(dc, X-stepX, Y-stepY, 200+stepX, 200+stepY, tmp, 0, 0, SRCCOPY);

			break;
			}
		case WM_DESTROY:
			PostQuitMessage(WM_QUIT);
			break;
	}
	return DefScreenSaverProc(hWnd,message,wParam,lParam);
}
 
Zurück