2016-10-09 6 views
2

ich einige Erweiterungen wie Umzug hinzufügen möchten, vergrößern, verkleinern, ... zu PictureBox, Label, Panel wie folgt aus:gleichen Erweiterungen mehrere Steuerelemente in WinForms

public class LiveControl: PictureBox 
{ 
    private Point cur = new Point(0, 0); 
    public LiveControl() 
    { 
     ResizeRedraw = true; 
     MouseDown += (s, e) => { cur = new Point(e.X, e.Y); }; 
     MouseMove += (s, e) => { 
      if (e.Button == MouseButtons.Left) 
      { 
       Control x = (Control)s; 
       x.SuspendLayout(); 
       x.Location = new Point(x.Left + e.X - cur.X, x.Top + e.Y - cur.Y); 
       x.ResumeLayout(); 
      } 
     }; 
    } 
    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     var rc = new Rectangle(this.ClientSize.Width - grab, this.ClientSize.Height - grab, grab, grab); 
     ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc); 
    } 
    protected override void WndProc(ref Message m) 
    { 
     base.WndProc(ref m); 
     if (m.Msg == 0x84) 
     { 
      var pos = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16)); 
      if (pos.X >= this.ClientSize.Width - grab && pos.Y >= this.ClientSize.Height - grab) 
       m.Result = new IntPtr(17); 
     } 
    } 
    private const int grab = 16; 
} 

Gibt es trotzdem, dass ich es wie ein schreiben Klasse und erben sie für alle, oder sollte ich 3 separate Klassen wie die schreiben, die ich für die PictureBox geschrieben habe?

+0

ich in der Regel eine Controller-Klasse schreiben, die die Steuerelemente registrieren können, um diese Dienste zu erhalten. Siehe [hier für ein Beispiel eines Drag & Drop-Controllers!] (Http://stackoverflow.com/questions/33284997/drag-and-drop-using-a-class-method/33288228?s=2|0.2710#33288228) – TaW

+0

@HansPassant Ich habe nicht verstanden, was du meinst –

+0

gut ein Teil davon ich von anderswo kopiert habe, ich brauche nicht Zeit zu verschwenden schreiben, was bereits geschrieben ist, und ich bin nicht dazu bestimmt zu verlangen, dass der Code ganz meins ist, Das war zum Beispiel, der Code ist viel größer. –

Antwort

0

Sie können die Logik in einer Hilfsklasse einkapseln, die von NativeWindow stammt. Auf diese Weise können Sie den Job ausführen, ohne eine abgeleitete Klasse für jedes Steuerelement zu erstellen, das Sie verschieben/skalieren möchten.

Sie können das Steuerelement übergeben, das Sie auf den Konstruktor der Hilfsklasse erweitern möchten, und Ihr Steuerelement dem nativen Fenster zuweisen. Dann wird das Überschreiben WndProc des systemeigenen Fensters Nachrichten des Steuerelements behandeln.

Auch andere Dinge wie die Handhabung des Ereignisses des Steuerelements sind einfach möglich, indem Sie einen Verweis auf das Steuerelement behalten, das Sie im Konstruktor übergeben und Ereignishandler zugewiesen haben.

Nach einer solchen nativen Fenster Helfer-Klasse erstellen die Verwendung wäre:

var h1 = new LiveControlHelper(this.pictureBox1); 
var h2 = new LiveControlHelper(this.button1); 

Oder Sie können in einer Schleife den Helfer für alle Bedienelemente eines Behälters verwenden.

Beispiel

Im folgenden Beispiel Refactoring ich den Code, die Sie auf dem Laufenden. Auf diese Weise können Sie den Code für alle Steuerelemente ohne Vererbung verwenden.

using System; 
using System.Drawing; 
using System.Windows.Forms; 
public class LiveControlHelper : NativeWindow 
{ 
    private Control control; 
    private Point cur = new Point(0, 0); 
    private const int grab = 16; 
    public LiveControlHelper(Control c) 
    { 
     control = c; 
     this.AssignHandle(c.Handle); 
     control.MouseDown += (s, e) => { cur = new Point(e.X, e.Y); }; 
     control.MouseMove += (s, e) => { 
      if (e.Button == MouseButtons.Left) { 
       Control x = (Control)s; 
       x.SuspendLayout(); 
       x.Location = new Point(x.Left + e.X - cur.X, x.Top + e.Y - cur.Y); 
       x.ResumeLayout(); 
      } 
     }; 
     control.Paint += (s, e) => { 
      var rc = new Rectangle(control.ClientSize.Width - grab, 
       control.ClientSize.Height - grab, grab, grab); 
      ControlPaint.DrawSizeGrip(e.Graphics, control.BackColor, rc); 
     }; 
     control.Resize += (s, e) => { control.Invalidate(); }; 
    } 
    protected override void WndProc(ref Message m) 
    { 
     base.WndProc(ref m); 
     if (m.Msg == 0x84) { 
      var pos = control.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, 
       m.LParam.ToInt32() >> 16)); 
      if (pos.X >= control.ClientSize.Width - grab && 
       pos.Y >= control.ClientSize.Height - grab) 
       m.Result = new IntPtr(17); 
     } 
    } 
} 

Hinweis

1- Um die Steuerung in dem normalen Zustand (nicht-veränderbare unbeweglichen) zurückzukehren es besser ist, unter Verwendung von Methoden Ereignisbehandlungsroutinen zuzuordnen und nicht mit Lambda. Sie müssen Ereignisbehandlungsroutinen revo- ren, um das Steuerelement in den normalen Status zurückzusetzen. Um dies zu tun, müssen Sie die Methode DestroyHanlde der Hilfsklasse aufrufen.

2- Ich habe den bereitgestellten Code einfach überarbeitet, damit er für Steuerelemente wiederverwendbar ist, ohne dass eine abgeleitete Version aller Steuerelemente implementiert werden muss. Aber Sie können den Code durch verbessern:

  • Aktivieren Sie die Kontrolle bewegen und Ändern der Größe Oberfläche verwenden, Kanten und Ecken der Kontrolle durch m.Result auf geeignete Werte einstellen.

  • Zieh Greifer Grenzen/Handler auf Kontrolle.

3- Wenn Sie SetStyle auf Kontrolle aufrufen müssen, können Sie einfach eine Erweiterungsmethode von this post verwenden und es so nennen:

control.SetStyle(ControlStyles.OptimizedDoubleBuffer | 
    ControlStyles.AllPaintingInWmPaint | 
    ControlStyles.ResizeRedraw, true); 
Verwandte Themen