Thema: Delphi Handles

Einzelnen Beitrag anzeigen

Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

Handles die zweite

  Alt 9. Jun 2002, 16:56
Auch HDC's sind nur Handles

Dem ein oder anderen von euch ist bestimmt schon mal das Buchstabenkürzel DC oder HDC oder der Begriff Device Context untergekommen und hat sich dann gefragt, was es damit auf sich hat. Nun da das Hauptthema dieses Kurses Handels sind und wie man schon an der Überschrift erkennen kann, handlet es sich bei einem Device Context auch nur um einen Handle.

Was ist nun ein Device Context (DC)?
Na ja, da fragen wir doch mal die, die es wissen müßten oder sollten: die Leute von Microsoft:
Zitat:
Device Contexts
A device context is a structure that defines a set of graphic objects and their associated attributes, as well as the graphic modes that affect output. [...]
Aus dem PSDK

Also ein DC hat was mit zeichnen zu tun. Und was soll das Gefasel von einer Struktur? In dieser Struktur sind einfach die Eigenschaften von diversen Zeichenoperationen festgelegt. Die man ändern kann aber nicht muß, da die Struktur mit vordefinierten Weten besetzt wird. In den meisten Fällen wird man sie aber doch ändern, da die standard Werte meist unbrauchbar sind.

Und ich will noch mal das PSDK bemühen:
Zitat:
About Device Contexts
Device independence is one of the chief features of Microsoft® Windows®. Win32®-based applications can draw and print output on a variety of devices. The software that supports this device independence is contained in two dynamic-link libraries. The first, Gdi.dll, is referred to as the graphics device interface (GDI); the second is referred to as a device driver. The name of the second depends on the device where the application draws output. For example, if the application draws output in the client area of its window on a VGA display, this library is Vga.dll; if the application prints output on an Epson FX-80 printer, this library is Epson9.dll.
Kurz übersetzt und zusammen gefaßt, heißt das so viel wie:
"Ein Hauptmerkmal von Windows ist die Geräteunabhängigkeit. Windows-Anwendungen können ihre Ausgabe auf vielen verschiedenen Geräten stattfinden lassen. Die benötigten Funktionen werden von der GDI.dll (GDI: grafic device interface) bzw von speziellen Gerätetreibern, wie Druckertreiber dll's bereitgestellt."
Soll so viel heißen wie: Wenn ich mit Rectangle() ein Rechteck auf den Bildschirm zeichne, kann ich mit der selben Funktion auch das Rechteck auf den Drucker zeichnen oder sonst wohin schmieren.

Und noch mal das PSDK, weil es so schön funktioniert:
Zitat:
An application must inform GDI to load a particular device driver and, once the driver is loaded, to prepare the device for drawing operations (such as selecting a line color and width, a brush pattern and color, a font typeface, a clipping region, and so on). These tasks are accomplished by creating and maintaining a device context (DC).
So jetzt wären wir da wo wir hin wollen und worauf es mir hier ankommt. Man lasse sich mal den ersten Teil des ersten Satzen auf der Zuge zergehen: "An application must inform GDI to load a particular device driver and, [...]". Um es mal ganz platt zu sagen, man muß sich erst mal das Handle für ein Gerät holen. Wobei 'Gerät' nicht unbedingt was sein muß, was man im Computerladen für viel Geld kaufen kann. Gerät kann in diesem Fall auch das Fenster der eigenen Anwendung oder der Desktop sein.

Man merke sich:
Aus den ertenen Teil wissen wir, dass ein Handle nichts weiter als eine Kennziffer ist, die Windows intern als Querverweis auf Objekte benutzt. Ein Handle für einen Gerätekontext stellt so zusagen den Schlüssel eines Programmes für sämtliche GDI-Funktionen dar.

Wie funktioniert das nun mit den DC's?
Nun, wenn wir ein Handle zu einem entsprechenden Gerätekontext anfordern, reagiert Windows auf diese Anforderung mit der Initialisierung einer internen Datenstruktur, die erst mal mit standard Werten besetzt wird und einem Handle, welches den Zugriff auf diese Struktur für diese Gerät ermöglicht. Wichtig: An dieser Stelle sei noch angemerkt, dass wann immer man einen DC anfordert diesen auch wieder freizugeben hat, wenn man mit im fertig ist.

Die Praxis
Da ich ja weiß, was ihr hier für böse Buben und Mädels seit und nur blödsinn im Kopf habt ) gleich mal was, um euren Spieltrieb zu befriedigen und was, wo ihr so richtig böse sein könnt, denn was ich in dem folgenden kleinen Programm demonstriere macht man aus Höflichkeit normalerweise nicht - nämlich in fremden Fenster rumschmieren.
Normaler weise kommt man, wenn man mit der VCl programmiert recht gut ohne DC aus, wenn man auf dem eigenen Fenster rumpinseln will. Einfach
Code:
Form1.Canvas.Textout();
Den ganzen DC-Kram erledigt hier das Canvas-Objekt von der Form. Was aber nun wenn ich wo ganz anders rumschmieren will, als auf dem Fenster meiner Anwedung? Wenn wir so etwas links oder rechts an unserem Anwendungsfenster vorbei schielen, kann man doch ganz schnell auf dumme Gedanken kommen... Und man stellt sich die Frage: "Kann ich nicht irgend wie auf den Desktop malen?" Antwort: "Kann man. Und in genau diesem Fall braucht man den DC vom Desktop.
Das Beispiel-Programm besteht einfach nur aus zwei Buttons, die ich auch nicht umbannt habe. Hier nur der Implementaion-teil des Programmes:
Code:
procedure TForm1.Button1Click(Sender: TObject);
var
  DC: HDC; // Handle für Device Context
  Brush: HBRUSH; //  Handle für Brush
  Pen: HPEN; // Handle für Zeichenstift
  s: String; // variable für den Text
begin
  { Device Context holen, 0 für den De3sktop, Application.Handle für eigene Anwendung}
  DC := GetDC(0);
  { Frabe wählen }
  Brush := CreateSolidBrush(RGB(255,0,0));
  { in DC einsetzen }
  SelectObject(DC, Brush);
  { Zeichenstift erzeugen }
  Pen := CreatePen(PS_SOLID, 3, RGB(75,0,255));
  { in DC einsetzen }
  SelectObject(DC, Pen);
  { Rechteck zeichnen }
  Rectangle(DC, 10, 10, 375, 100);
  s := 'In fremden Fenstern rumschmieren macht man nicht.';
  { Hintergrundmodus auf transparent setzen, sonst hat der Text einen weißen Hintergrund }
  SetBkMode(DC, Transparent);
  { Text ausgeben }
  TextOut(DC, 20, 50, PChar(s), length(s));;
  { und aufräumen, DC wieder freigeben }
  ReleaseDC(0, DC);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  { Rechteck für ungültig erklären: 0 für Desktop, nil für gesamtes Fenster, TRUE um den Hintergrund neu zu zeichnen }
  InvalidateRect(0, nil, TRUE);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  InvalidateRect(0, nil, TRUE);
end;
Die GDI-Funktionen will ich hier jetzt nicht näher erläutern, die könnt ihr in der Windows SDK Hilfe von Delphi nachschlagen, es ging mir hier halt nur um den DC. Und die Kommentare sollten wieder für sich sprechen

So, ich hoffe, ich habe euch wieder mal etwas über die Interna von Windows aufklären können und euch die interne Funktionsweise von Windows etwas näher bringen können.

Viel Spaß mit den DC wünscht euch noch euer Luckie. Bis zum nächsten mal in diesen Lichtspieltheater.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat