Bildschirm verdunkeln
-
Hi,
wie kann ich wie bei "Start->Beenden" den Bildschirm verdunkeln? Gibbet da ne Funktion für?
-
Da müsste es, so glaube ich, schon eine Funktion geben, bei der man die Helligkeit des Bildschirm verändern kann. Denn immer wenn ich Army Operations spiele, das Game beenden, ist mein Windows so hell *pfui*. Ich schau mal nach :D.
cya
-
So, ich hab jetzt ein bisschen in der MSDN rumgestöbert, und hab schon einiges gefunden, weiß zwar nicht, ob du das brauchen kannst, aber na gut ;):
SetColorAdjustment: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/colors_5cs4.asp
SetSysColor: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/setsyscolors.asp
SelectPalette: http://msdn.microsoft.com/library/en-us/gdi/colors_4u79.asp?frame=true
Wahrscheinlich sind die meisten Links Mist, aber vielleicht findest du ja sogar was :D.
cya
EDIT: Ich hab jetzt gerade nicht posten können, was sollte das mit dem "Sie können keinen Beitrag erstellen, ihr Benutzername enthält das ungültige Zeichen | ." oder so?
-
Ich hab das auch mal gebrauch und mir was gebastelt!
Du musst einfach nur ein monochromes Bitmap erstellen und dann ein graues Recheck reinzeichnen! Dann blittest du dieses per AND-Verknüfung auf den Bildschirm!
-
Aha. Das werde ich mal ausprobieren, flenders. Danke schonmal.
-
Danke auch an MagiC, der sich für mich Mühe gegeben hat.
-
Ich hab doch so eh nix zu tun :D.
cya
-
Hmm... ich hab jetzt sowas hier gemacht:
Graphics::TBitmap* bmp = new Graphics::TBitmap; bmp->Width = Screen->Width; bmp->Height = Screen->Height; TRect rc = Rect(0, 0, Screen->Width, Screen->Height); bmp->Canvas->Brush->Color = clGray; bmp->Canvas->FillRect(rc); HDC hdc = GetWindowDC(GetDesktopWindow()); BitBlt(hdc, 0, 0, Screen->Width, Screen->Height, bmp->Canvas->Handle, 0, 0, SRCAND); ReleaseDC(GetDesktopWindow(), hdc); ShowMessage("NA, WIE IS?"); delete bmp;
Ist VCL, aber ihr werdet das schon verstehen. Sieht fast OK aus, nur, dass einige Buttons (z.B. der StartButton) nicht übergezeichnet werden. Alles andere schon. Was glaubt ihr, muss ich jetzt noch ändern?
-
Hab noch ne Funktion gefunden, ich glaub das funktioniert besser :):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/icm/icm_0yi8.asp
cya
-
Diese Buttons wurden dann wohl nach deinem Blit neu gezeichnet!
Du könntest dir aber einfach den Bildschirm kopieren, ausgrauen und als hintergrund für ein Fullscrenn-Window verwenden!@MagiC Creator: Deine Funktionen ändern vielleicht schon auch die Farbdarstellung aber bei Start->Beenden ist eine schwarze Punktmaske drübergelegt (die nicht schwarzen Punkte behalten ihre ganz normalen Farben)!
[ Dieser Beitrag wurde am 06.01.2003 um 19:41 Uhr von flenders editiert. ]
-
Diese Buttons wurden dann wohl nach deinem Blit neu gezeichnet!
Der StartButton schon - der andere, der auf meinem Formular liegt, nicht! Es ist auch so, dass, wenn ich eine Linie auf meinem Formular zeichne, die durch den Button geht, diese nicht auf dem Button gezeichnet wird. Sie geht also sozusagen "drunter durch", was natürlich nicht so ist. Ich hab mich schon immer gefragt, wieso das so ist.
Die Idee mit dem Fullscreen-Window halte ich nicht für so gut. Das macht MS sicher auch nicht. Wenn schon - dann auch ganz!
-
@flenders: Bei mir wird bei Start-Beenden nur alles Grau... hab WinXP
cya
-
Ich werd mal versuchen, alle Top-Level-Windows zu disablen, also auch die Taskleiste. Dann kann da nichts mehr neu gezeichnet werden.
@flenders: Du hattest doch recht: der Button wird neu gezeichnet.
-
So, ich hab das mal versucht. Mit der VCL hat's auch einigermaßen gut geklappt. Der Bildschirm sah so aus wie bei Start->Beenden, nur eben, dass der geklickte Button nicht eingedunkelt war. Ich denke, das liegt am Fokus. Nur in WinAPI bekomme ich das nicht so hin (GetDIBits und SetDIBits). Dazu weiter unten. Hier erstmal die Funktionen zum Disablen aller TopLevel-Windows:
BOOL CALLBACK EnumProc(HWND hWnd, LPARAM lParam) { LONG style = GetWindowLong(hWnd, GWL_STYLE); if(IsWindow(hWnd) && (style & WS_VISIBLE) && !(style & WS_MINIMIZE)) EnableWindow(hWnd, (BOOL)lParam); return true; } //--------------------------------------------------------------------------- VOID EnableTopLevelWindows(BOOL enable) { EnumWindows((WNDENUMPROC)EnumProc, (LPARAM)enable); } //---------------------------------------------------------------------------
Die verwende ich in der folgenden "VCL-Funktion":
typedef VOID CALLBACK (*DARKENSCREENPROC)(); VOID DarkenScreen(DARKENSCREENPROC dsProc) { Graphics::TBitmap* bmp = new Graphics::TBitmap; int width = Screen->Width; int height = Screen->Height; bmp->Width = width; bmp->Height = height; bmp->PixelFormat = pf32bit; // ScreenShot des Desktops machen in bmp HDC hdc = GetWindowDC(GetDesktopWindow()); BitBlt(bmp->Canvas->Handle, 0, 0, width, height, hdc, 0, 0, SRCCOPY); // Punkte druff int begin = 0; for(int i=0; i<height; ++i) { LONG* lBegin = (LONG*)bmp->ScanLine[i]; int j = begin; for(; j < width; j+=2) lBegin[j] = 0; if(j == width) begin = 1; else begin = 0; } // Auf Desktop malen BitBlt(hdc, 0, 0, width, height, bmp->Canvas->Handle, 0, 0, SRCCOPY); // ................. EnableTopLevelWindows(FALSE); dsProc(); EnableTopLevelWindows(TRUE); ReleaseDC(GetDesktopWindow(), hdc); delete bmp; }
Wie gesagt: funktioniert gut. So, jetzt wollte ich diese Funktion aber in purem C mit WinAPI haben. Dazu habe ich folgendes geschrieben:
VOID DarkenScreenApi(DARKENSCREENPROC dsProc) { HBITMAP hBitmap; HDC hMemDC; HDC hdc; int i, width, height; HGLOBAL hGlobal; LONG* bitarray; BITMAPINFO bi; // Vorbereitungen width = Screen->Width; height = Screen->Height; hdc = GetWindowDC(GetDesktopWindow()); hBitmap = CreateCompatibleBitmap(hdc, width, height); hMemDC = CreateCompatibleDC(hdc); SelectObject(hMemDC, hBitmap); // Screenshot des Desktops machen BitBlt(hMemDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY); // Das BitArray füllen SelectObject(hMemDC, NULL); // raus mit hBitmap hGlobal = GlobalAlloc(GMEM_FIXED, 4 * width * height); bitarray = (LONG*)GlobalLock(hGlobal); bi.bmiHeader.biSize = sizeof(BITMAPINFO); bi.bmiHeader.biWidth = width; bi.bmiHeader.biHeight = height; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; GetDIBits(hMemDC, hBitmap, 0, height, (void*)bitarray, &bi, DIB_RGB_COLORS); // Punkte ins Bitmap malen for(i=0; i<height*width; i+=2) bitarray[i] = 0; //schwarz SetDIBits(hMemDC, hBitmap, 0, height, (void*)bitarray, &bi, DIB_RGB_COLORS); SelectObject(hMemDC, hBitmap); // wieda rin! // Auf Desktop malen BitBlt(hdc, 0, 0, width, height, hMemDC, 0, 0, SRCCOPY); // ................. EnableTopLevelWindows(FALSE); dsProc(); EnableTopLevelWindows(TRUE); DeleteObject(hBitmap); GlobalUnlock(hGlobal); GlobalFree(hGlobal); ReleaseDC(NULL, hMemDC); ReleaseDC(GetDesktopWindow(), hdc); }
Das macht mir zwar einen ScreenShot des Desktops - malt aber nicht die Punkte auf das Bitmap. Wieso nicht? Verwende ich Set/GetDIBits falsch? Ich frage mich auch, was der erste Parameter (also das DC) in den Funktionen soll, wenn der zweite Parameter (also das Bitmap) nicht in einen DC selektiert sein darf bei Aufruf der Funktion(en). Was mache ich falsch?
-
So, jetzt hab ich eine besser Idee gehabt, und es klappt auch, und sogar viel schneller: mit einem PatternBrush! Die Funktion ist folgende:
VOID DarkenScreenApi() { HBITMAP hBrushBmp; HDC hMemDC; HDC hdc; HBRUSH hBrush, hOrgBrush; int i, k, offset, width, height; // Vorbereitungen width = Screen->Width; height = Screen->Height; hdc = GetWindowDC(GetDesktopWindow()); hMemDC = CreateCompatibleDC(hdc); hBrushBmp = CreateCompatibleBitmap(hdc, 8, 8); SelectObject(hMemDC, hBrushBmp); // Das Brush-Bitmap erstellen im DC offset = 0; for(i=0; i<8; i=i+1) { for(k=0; k<8; k=k+1) if( ( (k + offset) % 2 ) == 0 ) SetPixel(hMemDC, k, i, RGB(0,0,0)); else SetPixel(hMemDC, k, i, RGB(255,255,255)); offset = offset + 1; } // Den Brush erstellen und ins Screen-DC hauen hBrush = CreatePatternBrush(hBrushBmp); hOrgBrush = (HBRUSH)SelectObject(hdc, hBrush); // Den Bildschirm verdunkeln PatBlt(hdc, 0, 0, width, height, 0xA000C9); // Den "Dialog" anzeigen EnableTopLevelWindows(FALSE); MessageBox(NULL, "We shadowed the screen", "HALLO", MB_OK); EnableTopLevelWindows(TRUE); // Aufräumen SelectObject(hdc, hOrgBrush); DeleteObject(hBrush); DeleteObject(hBrushBmp); ReleaseDC(NULL, hMemDC); ReleaseDC(GetDesktopWindow(), hdc); }
Das Dumme ist nur immernoch, dass der Tray und der StartButton neu gezeichnet werden - auch, wenn ich alles disable. Es bleiben 3 Fragen:
- Wie kann ich erreichen, dass Startbutton und Tray nicht mehr gemalt werden?
- Wie bekomme ich alles wieder auf den ursprünglichen Zustand?
- Warum geht das mit den Get/SetDIBits() da oben nicht?
-
Also ich hab bei mir erst CreateCompatibleDC gemacht und von diesem dann per CreateCompatibleBitmap ein Bitmap erzeugt! Dadurch erhältst du ein monochromes Bitmap! In dieses zeichnest du dann ein graues (128,128,128) Rechteck in Größe deines Bildschirms -> jetzt hast du eine Punktmaske in Größe deines Bildschirms!
Aber du kannst es auch mit dem PatternBrush machen wenn's funktioniert!Ich würde zuerst die TopLevelWindows deaktivieren und dann erst die Maske auf den Bildschirm blitten!
-
Original erstellt von flenders:
Ich würde zuerst die TopLevelWindows deaktivieren und dann erst die Maske auf den Bildschirm blitten!Wozu? Bringt nüscht!
Ich hab noch ne Frage: Wie kann man es erreichen, dass nichts mehr neu gezeichnet wird, außer auf meinem eigenen Fenster bzw. Dialog. Die, die Win98 haben, machen mal Start->Beenden und bringen dann den MouseCursor über das Schließen-Kreuz des Shutdown-Dialogs. Es erscheint der Tooltip "Schließen". Wenn man die Maus wieder wegbewegt, wird der Dialog neu gezeichnet, der restliche Teil aber nicht. Ein Teil des Tooltips bleibt, wo er war. D.h., auf allen anderen Fenster wird NICHTS mehr gezeichnet. Wie mache ich das?