全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1891
推到 Plurk!
推到 Facebook!

Cr�縱tion d'un contr�鏊e Winform avec Delphi 8 .NET

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-06-12 00:34:59 IP:61.64.xxx.xxx 未訂閱
Creation d'un controle Winform avec Delphi 8 .NET
http://nono40.developpez.com/delphi/delphi8/source0080/    Par Nono40 (nono40.developpez.com)
     Ce document presente la creation d'un controle WinForm personnalise.     La version telechargeable de ce document ( HTML ) est disponible ici : article0080d8.zip     Introduction 
I. Creation de l'assemblage 
II. Ajout de la propriete AiguilleSec 
III. Ajout du code de dessin 
IV. Surcharge de la taille par defaut 
V. Ajout d'un evenement 
VI. Utilisation du composant dans un projet Delphi .NET 
VII. Utilisation du composant dans un projet C# 
Conclusion         Introduction        Cet article va presenter la creation d'un composant WinForm personnalise derivant du type System.Windows.Forms.UserControl. Ce composant est une horloge analogique avec ou sans l'aiguille des secondes :         La methode proposee ici est l'adaptation a Delphi 8 de l'article de CGI : Creation d'un controle WinForm pour .Net         I. Creation de l'assemblage        La notion de paquet en tant que tel n'existe plus dans Delphi 8. Ceux-ci ont ete remplaces par la definition d'assemblage introduite par .NET. Pour creer un composant WinForm utilisable il faut creer un nouvel assemblage contenant ce composant.     Pour creer un nouvel assemblage pour le composant, utilisez Fichier->Nouveau->Paquet. Enregistrez le projet comme PHorloge.bdsprj.         Ensuite ajouter un controle Winform avec Fichier->Nouveau->Controle utilisateur. Enregistrer le code comme UHorloge.pas. Dans l'editeur de propriete qui vient de s'ouvrir renommez ( propriete Name ) le composant en THorloge.         Notez que Delphi fait alors directement deriver le composant de la classe System.Windows.Forms.UserControl et cree dans l'unite tout le code minimum de gestion du composant.     Le gestionnaire de projet doit alors vous donner les informations suivantes :         II. Ajout de la propriete AiguilleSec        La propriete AiguilleSec va definir si l'aiguille des secondes est affichee ou non. La definition d'une nouvelle propriete est identique a la methode utilisee dans la VCL. Il faut ajouter une variable privee contenant la valeur de la propriete et definir les methodes eventuelles de lecture et ecriture de la propriete.     Pour ceci il faut ajoutez dans la definition du composant les ligne suivantes :     private
    { Private Declarations }
    FAiguilleSec:Boolean;
    Procedure SetAiguilleSec(Value:Boolean);
  public
    constructor Create;
  published
    [Category('Appearance'),
    Description('Affiche l''aiguille des secondes.'),
    DefaultValue(true)]
    Property AiguilleSec:Boolean Read FAiguilleSec Write SetAiguilleSec;
  end;
Notez ici la definition des attributs de la propriete permettant de definir la categorie d'affichage ainsi que le texte d'aide associe dans l'inspecteur d'objet.     Dans le constructeur du composant, ajouter la valeur initiale de la propriete :     constructor THorloge.Create;
begin
  inherited Create;
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent;
  //
  // TODO: Add any constructor code after InitializeComponent call
  //
  FAiguilleSec := True;
end;
Et pour terminer, definir le code de la methode d'ecriture de la propriete, l'appel d'invalidate va demander au controle de se redessiner.     procedure THorloge.SetAiguilleSec(Value: Boolean);
begin
  FAiguilleSec:=Value;
  Invalidate;
end;    III. Ajout du code de dessin        Le dessin devant etre effectue toutes les secondes, nous allons ajouter un Timer au controle afin d'obtenir un evenement regulier. Le dessin en lui-meme sera assure par la surcharge de la methode OnPaint du controle.     La definition de la classe devient donc :     THorloge = class(System.Windows.Forms.UserControl)
  //....
  strict protected
    /// 
    /// Clean up any resources being used.
    /// 
    procedure Dispose(Disposing: Boolean); override;
    procedure OnPaint(e:PaintEventArgs); Override;
  private
    { Private Declarations }
    T:Timer;
    FAiguilleSec:Boolean;
    Procedure SetAiguilleSec(Value:Boolean);
    Procedure Tempo(myObject:System.Object; myEventArgs:System.EventArgs );
  public
    constructor Create;
  published
    [Category('Appearance'),
    Description('Affiche l''aiguille des secondes.'),
    DefaultValue(true)]
    Property AiguilleSec:Boolean Read FAiguilleSec Write SetAiguilleSec;
  end;
Comme d'habitude le composant enfant sera cree dans le constructeur de l'objet.     constructor THorloge.Create;
begin
  inherited Create;
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent;
  //
  // TODO: Add any constructor code after InitializeComponent call
  //
  FAiguilleSec := True;
  SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.UserPaint Or
           ControlStyles.AllPaintingInWmPaint, true);
  T:=Timer.Create;
  Include(T.Tick,Tempo);
  T.Interval := 1000;
  T.Start;
end;
Notez ici l'ajout d'un gestionnaire d'evenement ( Tempo dans notre exemple ) a la liste des gestionnaire associes a T.Tick. Cet ajout est realise a l'aide de la procedure Include, ce point est different de la surcharge habituelle d'un evenement d'un controle VCL.     Notez aussi la modification du style du controle afin de definir un dessin personnalise et un double-buffer pour eviter le scintillement lors du trace.     Le code de la procedure Tempo ne fera qu'invalider la zone d'affichage du composant :     procedure THorloge.Tempo(myObject: TObject;
  myEventArgs: System.EventArgs);
begin
  Invalidate;
end;
L'evenement OnPaint se chargera du dessin du composant :     procedure THorloge.OnPaint(e: PaintEventArgs);
Var BlackPen :Pen;
    Rect     :Rectangle;
    d        :DateTime;
    Pinceau  :SolidBrush;
    drawFont :System.Drawing.Font;
    n,z,u,x0,y0,x1,y1,x2,y2,x3,y3:Single;
    aigPoints : Array[0..3]Of PointF;
begin
  BlackPen := Pen.Create(Color.Black, 1);
  Rect := Rectangle.Create( 2, 2, 118, 118);
  e.Graphics.DrawEllipse(blackPen, rect);      d := DateTime.Now;      //-----------------------
  // Aiguille des Secondes (si propriete AiguilleSec a true)
  if AiguilleSec Then
  Begin
    n := d.Second*200/60;
    z := n/100*3.14159;
    u := (n 50)/100*3.14159;        x0 := Math.Sin(z)*50;
    y0 := -Math.Cos(z)*50;        x1 := -Math.Sin(z)*10;
    y1 := Math.Cos(z)*10;        x2 := Math.Sin(u)*2;
    y2 := -Math.Cos(u)*2;        x3 := -Math.Sin(u)*2;
    y3 := Math.Cos(u)*2;        Pinceau:=SolidBrush.Create(Color.Red);        aigPoints[0].X := x1 60;
    aigPoints[0].Y := y1 60;        aigPoints[1].X := x2 60;
    aigPoints[1].Y := y2 60;        aigPoints[2].X := x0 60;
    aigPoints[2].Y := y0 60;        aigPoints[3].X := x3 60;
    aigPoints[3].Y := y3 60;        e.Graphics.FillPolygon(Pinceau, aigPoints);
    e.Graphics.DrawPolygon(blackPen, aigPoints);
    Pinceau.Dispose();
  End;      //-----------------------
  // Aiguille des Minutes      n := d.Minute*200/60;
  z := n/100*3.14159;
  u := (n 50)/100*3.14159;      x0 := Math.Sin(z)*50;
  y0 := -Math.Cos(z)*50;      x1 := -Math.Sin(z)*10;
  y1 := Math.Cos(z)*10;      x2 := Math.Sin(u)*4;
  y2 := -Math.Cos(u)*4;      x3 := -Math.Sin(u)*4;
  y3 := Math.Cos(u)*4;      Pinceau:=SolidBrush.Create(Color.Lime);      aigPoints[0].X := x1 60;
  aigPoints[0].Y := y1 60;      aigPoints[1].X := x2 60;
  aigPoints[1].Y := y2 60;      aigPoints[2].X := x0 60;
  aigPoints[2].Y := y0 60;      aigPoints[3].X := x3 60;
  aigPoints[3].Y := y3 60;      e.Graphics.FillPolygon(Pinceau , aigPoints);
  e.Graphics.DrawPolygon(blackPen, aigPoints);
  Pinceau.Dispose();      //-----------------------
  // Aiguille des Heures      n := d.Hour*200/12   d.Minute*200/60/12;
  z := n/100*3.14159;
  u := (n 50)/100*3.14159;      x0 := Math.Sin(z)*35;
  y0 := -Math.Cos(z)*35;      x1 := -Math.Sin(z)*10;
  y1 := Math.Cos(z)*10;      x2 := Math.Sin(u)*4;
  y2 := -Math.Cos(u)*4;      x3 := -Math.Sin(u)*4;
  y3 := Math.Cos(u)*4;      Pinceau:=SolidBrush.Create(Color.Yellow);      aigPoints[0].X := x1 60;
  aigPoints[0].Y := y1 60;      aigPoints[1].X := x2 60;
  aigPoints[1].Y := y2 60;      aigPoints[2].X := x0 60;
  aigPoints[2].Y := y0 60;      aigPoints[3].X := x3 60;
  aigPoints[3].Y := y3 60;      e.Graphics.FillPolygon(Pinceau , aigPoints);
  e.Graphics.DrawPolygon(blackPen, aigPoints);
  Pinceau.Dispose();
  //-----------------------
  // Chiffres
  drawFont := System.Drawing.Font.Create('Arial', 8);
  Pinceau := SolidBrush.Create(Color.Black);      e.Graphics.DrawString('12', drawFont, Pinceau,  55,   6);
  e.Graphics.DrawString( '6', drawFont, Pinceau,  58, 101);
  e.Graphics.DrawString( '3', drawFont, Pinceau, 105,  53);
  e.Graphics.DrawString( '9', drawFont, Pinceau,   8,  53);
  //-----------------------
  drawFont.Dispose();
  Pinceau.Dispose();
  blackPen.Dispose();
  inherited;
End;    IV. Surcharge de la taille par defaut        Afin que la taille du composant soit correcte ( 121 x 121 ) lors de sa creation, il faut redefinir la taille par defaut du composant par surcharge de la propriete taille :     THorloge = class(System.Windows.Forms.UserControl)
  {$REGION 'Designer Managed Code'}
  //...
  strict protected
    /// 
    /// Clean up any resources being used.
    /// 
    procedure Dispose(Disposing: Boolean); override;
    procedure OnPaint(e:PaintEventArgs); Override;
  private
    { Private Declarations }
    T:Timer;
    FAiguilleSec:Boolean;
    Function GetSize:Size;
    Procedure SetAiguilleSec(Value:Boolean);
    Procedure Tempo(myObject:System.Object; myEventArgs:System.EventArgs );
  public
    constructor Create;
  published
    Property Size  Read GetSize;
    [Category('Appearance'),
    Description('Affiche l''aiguille des secondes.'),
    DefaultValue(true)]
    Property AiguilleSec:Boolean Read FAiguilleSec Write SetAiguilleSec;
  end;
La methode GetSize est alors definie comme suit :     function THorloge.GetSize: Size;
begin
  Result := System.Drawing.Size.Create(121,121);
end;    V. Ajout d'un evenement        Un evenement en dotnet comporte toujours deux parametres, le premier est l'objet declenchant ( comme en VCL ) le deuxieme est un objet donnant la liste des valeurs specifiques a l'evenement. On va donc creer un nouvelle classe de description des parametres de l'evenement. Cette classe ne va donner ici que l'heure de declenchement, ce n'est pas tres utile, mais c'est juste pour l'exemple.     TReveilArgs = Class
Public
  DateHeureReveil : DateTime;
  Constructor Create(D:DateTime);
End;    TReveilEvent = Procedure ( Sender:TObject ; R : TReveilArgs )Of Object;
La date et l'heure de declenchement de l'evenement sera conserve dans une nouvelle propriete Reveil de type System.DateTime. L'ecriture d'un gestionnaire d'evenement est identique a celle utilisee dans la VCL.     Une propriete de type evenement n'est plus declaree avec les mots clef Read et Write ( bien que ce soit toujours possible par compatibilite ) mais par les mots clefs Add et Remove. Ceci permet de gerer les evenements multicast de la CLR .NET.     THorloge = class(System.Windows.Forms.UserControl)
    //...
  private
    { Private Declarations }
    FReveil:DateTime;
    FReveilEvent:TReveilEvent;
    //...
  published
    [Category('Misc'),
    Description('Date/heure de declenchement du reveil.'),
    DefaultValue(true)]
    Property Reveil:DateTime Read FReveil Write FReveil;
    [Category('Misc'),
    Description('Evenement declenche si Now=Reveil.'),
    DefaultValue(true)]
    Property OnReveil:TReveilEvent Add FReveilEvent Remove FReveilEvent;
  end;
Bien sur, le code du timer va etre modifie pour tester si l'heure de l'evenement correspond et ainsi appeler le gestionnaiure d'evenement. Notez qu'il faut appeler la variable privee et non l'evenement lui-meme comme on le faisait en VCL.     procedure THorloge.Tempo(myObject: TObject;
  myEventArgs: System.EventArgs);
begin
  Invalidate;
  If DateTime.Now.ToString=Reveil.ToString Then
    FReveilEvent(Self,TReveilArgs.Create(Reveil));
end;    VI. Utilisation du composant dans un projet Delphi .NET        Une fois le projet compile, installez le nouveau composant WinForm dans Delphi avec Composants->Composants .NET intalles. Puis en selectionnant l'assemblage nouvellement cree et de definir la categorie dans laquelle il faut ajouter le composant ( general par defaut ).     Apres installation le composant apparait dans la liste :         Il suffit alors de poser le composant sur une fiche ( WinForm ) afin de l'utiliser comme n'importe quel autre composant.         VII. Utilisation du composant dans un projet C#        Pour tester le composant das une application C# il suffit de compiler l'exemple suivant avec le compilateur en ligne csc.     using System;
using System.Drawing;
using System.Windows.Forms;    namespace MonProjet
{
  public class WinForm : Form
  {
    private UHorloge.THorloge horloge1 = new UHorloge.THorloge();        public WinForm()
    {        
     horloge1.Location = new Point(20, 20);         Size = new Size(170, 200);
     Text = "WinForm";          Controls.Add(this.horloge1);
    }        [STAThread]
    static void Main()
    {
      Application.Run(new WinForm());
    }
  }
}
Notez que l'espace de nom n'est pas celui de la dll mais celui de l'unite contenant le composant.     Lors de la compilation il faut donner en reference la dll contenant notre composant :     csc /target:winexe /reference:PHorloge.dll WinForm.cs
 
http://nono40.developpez.com/sources/zips/source0080.zip
附加檔案:51712_source0080.zip
系統時間:2024-05-19 0:08:57
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!