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
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.