Heim  >  Artikel  >  Backend-Entwicklung  >  C# GDI+ Programmierung (5)

C# GDI+ Programmierung (5)

高洛峰
高洛峰Original
2016-12-17 10:09:471401Durchsuche

Rufen Sie die API-Funktion auf, um im Nicht-Client-Bereich des Fensters zu zeichnen.

In der Graphics-Klasse von GDI+ gibt es eine FromHdc-Funktion. Diese Funktion kann ein Grafikobjekt basierend auf dem Fenstergerät erstellen Kontext (DC). In vc++ ist das Zeichnen des Fenster-Client-Bereichs mit dem Nicht-Client-Bereich nichts anderes als unterschiedliche Aufrufe der Funktionen GetWindowDC und GetDC. Ersteres erhält den gesamten Fenster-DC und letzteres den Fenster-Clientbereich-DC.

Dann können wir die GetWindowDC-Funktion in C# aufrufen, um den gesamten Fenster-DC abzurufen, und ihn dann über FromHdc laden, sodass wir für das gesamte Fenster zeichnen können.

Wie ruft C# die WINDOWS-API auf oder wie ruft man Funktionen in einer Dynamic Link Library (DLL) auf?

Ähnlich wie bei VC++ importieren Sie zuerst die Dynamic Link Library und deklarieren dann die API-Funktion wie folgt:

[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);

Natürlich ist das Obige das einfachste, es gibt noch einige Details, die nicht erwähnt werden, also machen wir es erst einmal, wir wissen nur, wie man es grundsätzlich verwendet. Diese Einzelheiten werden später im Detail erläutert.

In C# stellen wir fest, dass die Parametertypen von API-Funktionen unterschiedlich sind, z. B. behandelt HDC und HWND in VC++. Bei der Deklaration wurde stattdessen IntPtr verwendet. Dies ist nicht möglich, da C# nicht über das Konzept von Zeigern verfügt und wir bei der Überprüfung der HDC- und HWND-Typdefinitionen festgestellt haben, dass es sich bei beiden um Zeigertypen handelt.

In C# werden diese „Handle“-Typen also durch IntPtr ersetzt, einschließlich Bereichshandles HRGN, HICON-Symbole, HFONT-Schriftarthandles usw.

Sehen wir uns ein Beispiel an (Fortsetzung des vorherigen Kapitels)

öffentliche Teilklasse Form1: Form
{
//Importieren Sie die dynamische Linkbibliothek und deklarieren Sie die Funktion. Diese Funktion wird in der Klasse Form1 deklariert.
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
//Pfad zum Speichern des nicht transparenten Teils des PNG
private GraphicsPath path = new GraphicsPath();
//PNG-Bild laden
Bitmap bmp = new Bitmap("d:\Image\win.png");
public Form1()
{
​​ InitializeComponent ();
//Beurteilen Sie den Farbwert jedes Pixels und erhalten Sie den Anzeigebereich des Bildes
for (int y = 0; y < bmp.Height; y++)
for (int x = 0; x < bmp.Width; x++)
{
Color cor = bmp.GetPixel(x, y);
int argb = cor .ToArgb (); GetBytes(argb);
//Pixelfarbwert ist nicht transparent
if (bargb[3] != 0)
                         //Diesen Pixelbereich zum Pfad hinzufügen
                path.AddRectangle(neues Rechteck (x, y, 1, 1));                                                                                                                                                            . Fensteranzeigebereich, Bereich erstellen durch Pfad
This.Region = new Region( path);
this.Paint += formPaint;

}
private void formPaint(object sender, PaintEventArgs e)
{
                                                                                                                >                 //Handle ist das Fensterhandle, es ist ein IntPtr-Typ
          IntPtr hdc = GetWindowDC(this.Handle); Graphics.FromHdc (hdc);
                                                                                                                                                                                                                                                          Seitprotected override void OnPaintBackground(PaintEventArgs e)
                                                                       void. es.Transparent , this.ClientRectangle) ;
                                                                                                                    Es wird einige Probleme oder eine Menge Ärger mit sich bringen. Es ist nur so, dass ich es nicht gelöst habe. Das Verschieben des Fensters oder das Maximieren des Fensters, ohne das gesamte Fenster vollständig zu aktualisieren, führt zu diesem Problem. Dieses Problem wird später gelöst.

Freunde, die Interesse haben, können dieses Problem auch lösen.

Außerdem habe ich nur den Client-Bereich des Fensters mit einem transparenten Pinsel gefüllt. Wenn ich das gesamte Fenster (einschließlich der Titelleiste) füllen möchte, ist die Methode dieselbe wie beim Zeichnen auf dem gesamten Fenster Fenster, holen Sie sich WindowDC und erstellen Sie dann

ein Grafikobjekt und zeichnen Sie den Fensterhintergrund.

(Exkurs: In vc++ haben der Client-Bereich und der Nicht-Client-Bereich unterschiedliche Neuzeichnungsnachrichten, WM_PAINT und WM_NCPAINT. Bitte beachten Sie dies. Wenn Sie den Nicht-Client-Bereich aktualisieren, zeichnen Sie den Client-Bereich nicht neu. , obwohl es keine Probleme geben wird, ist es immer schlecht, wenn es die Effizienz beeinträchtigt. Vermeiden Sie es, wenn Sie können)

Nicht-Client-Bereich des selbst gezeichneten Fensters (einschließlich Titelleiste, Maximum, Minimieren). , Schaltflächen schließen)

Schreiben Sie die Nachrichtenverarbeitungsfunktion WndProc neu

öffentliche Teilklasse Form1: Form

{

public Form1()

{

InitializeComponent();

       }

protected override void WndProc(ref Message m)

{
if (m.Msg == 0xA3)//WM_NCLBUTTONDBLCLK Doppelklicken Sie auf die Titelnachricht
MessageBox.Show(" You doppelklickte auf die Titelleiste");
                                           beschäftigen.

Um den der Nachricht entsprechenden Wert zu überprüfen, können Sie ihn im VC++-Compiler überprüfen. Markieren Sie beispielsweise WM_LBUTTONDOWN und klicken Sie mit der rechten Maustaste, wählen Sie „Zur Definition gehen“, um ihn anzuzeigen.

m.HWnd speichert das Fensterhandle m.LParam und m.WParam. Weitere Informationen finden Sie in der Erläuterung der Parameter WPARAM und LPARAM in der Funktion CreateWindow.



Der Arbeitsaufwand, den Nicht-Kundenbereich selbst zu zeichnen, ist wirklich zu groß. Hier werde ich nur eine allgemeine Vorstellung und Richtung geben, wenn ich Zeit habe Zukunft.

Die Voraussetzung besteht natürlich darin, verschiedene Daten zu berechnen, z. B. ob das Fenster Ränder hat. Wenn ja, ermitteln Sie die Randbreite und -höhe und berechnen Sie dann die rechteckige Fläche der vier Ränder.

Bestimmen Sie abschließend, ob das Fenster über die maximalen und minimalen Attribute verfügt, und ermitteln Sie dann den Bereich für die drei Schaltflächen.

Die SystemInformation-Klasse speichert diese Daten. Beispielsweise speichert SystemInformation.CaptionButtonSize die Größe der Titelleistenschaltfläche. Sobald die Größe ermittelt wurde, können Sie

den Bereich der Schaltfläche bestimmen , weil diese drei Die Schaltflächen befinden sich alle in der oberen rechten Ecke des Fensters, mit Ausnahme der Höhe und Breite des Rahmens.

SystemInformation.CaptionHeight speichert die Höhe der Titelleiste, und die Höhe und Breite des Rahmens werden in SystemInformation.BorderSize oder SystemInformation.Border3DSize gespeichert, die entsprechend dem FormBorderStyle des Fensters bestimmt werden. Sie können bestimmen, ob das Fenster durch MaximizeBox maximiert wird, was maximiert wird, wenn true.

Nach Erhalt der oben genannten Daten reagiert es auf verschiedene Nachrichten im Nicht-Client-Bereich, z. B. auf die Nachrichten mit der linken Maustaste WM_NCLBUTTONDOWN und WM_NCLBUTTONUP.

Die Maus verschiebt die Nachricht WM_NCMOUSEMOVE und dann beginnt die Selbstzeichnung.

Die Funktion „Contains“ in der Klasse „Rechteck“ kann bestimmen, ob sich ein Punkt innerhalb eines rechteckigen Bereichs befindet.

Weitere Artikel zum Thema C# GDI+-Programmierung (5) finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn