2010-05-25 3 views
13

Ich möchte direkt auf dem Desktop in C# zeichnen. Bei der Suche habe ich ein Graphics-Objekt vom Desktop HDC (null) verwendet. Dann malte ich normal mit diesem Graphics-Objekt.Wie effektiv auf dem Desktop in C# zeichnen?

Das Problem ist, dass meine Formen verloren gehen, wenn ein Teil des Bildschirms neu gezeichnet wird. Ich habe versucht, eine While-Schleife, aber es tatsächlich Zeichnen so schnell wie die Anwendung kann, das ist nicht die Aktualisierungsrate des Desktops.

Normalerweise müsste ich meinen Zeichencode in ein "OnPaint" -Ereignis setzen, aber so etwas gibt es nicht für den Desktop.

Wie würde ich es tun?

Beispielcode: https://stackoverflow.com/questions/1536141/how-to-draw-directly-on-the-windows-desktop-c

+0

Welche Version von Windows? – SLaks

Antwort

8

Wenn Sie zu HDC (NULL) zeichnen, zeichnen Sie unmanaged auf den Bildschirm. Wie Sie festgestellt haben, werden Ihre Änderungen überschrieben, sobald Windows diesen Teil des Bildschirms aktualisiert.

Es gibt ein paar Optionen, je nachdem, was Sie erreichen wollen:

  1. einen rand erstellen, möglicherweise nicht rechteckige Fenster. (Verwenden Sie SetWindowRgn, um ein Fenster nicht rechteckig zu machen.) Sie können dies zu einem Kind des Desktop-Fensters machen.
  2. Unterklasse das Desktop-Fenster. Das ist nicht einfach und umfasst das Einführen einer DLL in dem Explorer.exe-Prozess.
1

Das ist schwer richtig zu tun.

Es wird viel einfacher und zuverlässiger sein, stattdessen Ihre eigene randlose Form zu erstellen.

3

Um eine OnPaint für den Desktop erhalten Sie die Desktop-Fenster benötigen würde und Logik verwenden, um Ihre Zeichnung zu Unterklasse, wenn er eine WM_PAINT/WM_ERASEBKGND Nachricht empfängt.

Wie der Thread, mit dem Sie verbunden sind, sagt, können Sie nur Nachrichten abfangen, die an ein Fenster eines externen Prozesses mit einem Haken (SetWindowsHookEx von einer DLL) gesendet werden.

Wie bereits erwähnt, ist ein transparentes Fenster eine andere Möglichkeit dies zu tun oder (abhängig von der Aktualisierungshäufigkeit) ein temporäres Hintergrundbild zu kopieren, zu zeichnen und einzustellen (wie bginfo).

15

I posted zwei Lösungen für eine ähnliche Anforderung here

Grundsätzlich haben Sie zwei Möglichkeiten.

1- Holen Sie ein Grafikobjekt für den Desktop und beginnen Sie mit dem Zeichnen. Das Problem ist, wenn Sie Löschen beginnen müssen, was Sie vorher erstellt haben usw.

Point pt = Cursor.Position; // Get the mouse cursor in screen coordinates 

using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) 
{   
    g.DrawEllipse(Pens.Black, pt.X - 10, pt.Y - 10, 20, 20); 
} 

2- Die zweite Option, die ich oben in der Verbindung zur Verfügung stellen ist ein transparentes obersten Fenster zu erstellen und alle Ihre Zeichnung zu tun in das Fenster. Dies bietet im Grunde eine transparente Überlagerung für den Desktop, auf dem Sie zeichnen können. Ein möglicher Nachteil, wie ich in der ursprünglichen Antwort erwähnt habe, ist, dass andere Fenster, die auch am höchsten sind und nach dem Start deiner App erstellt werden, dein oberstes Fenster verdecken. Dies kann jedoch gelöst werden, wenn es ein Problem ist.

Für Option 2 ist die Transparenz des Formulars so einfach wie die Verwendung eines Transparenzschlüssels, damit Mausklicks usw. auf den zugrunde liegenden Desktop fallen können.

BackColor = Color.LightGreen; 
TransparencyKey = Color.LightGreen; 
+0

Vermutlich würde das * nicht * für Vollbild-Anwendungen (Spiele, etc.) funktionieren? – acron

+2

Man sollte GetDesktopWindow() an Graphics.FromHwnd() übergeben, da IntPtr.Zero ein Implementierungsdetail ist, das sich ändern kann und sicherlich ** NICHT ** für Multi-Desktop- oder Multi-Session-Workstations funktionieren wird. –

Verwandte Themen