Bonjour,Vieille discussion qui est exhumée là...
Cela dit, c'est assez confus et je ne suis pas sur d'avoir tout compris sur les spécifications et les responsabilités de l'application et de la dll...
Pour résumer, actuellement, l'application transmet un Handle de windows (fenêtre) au sens Windows du terme (système d'exploitation) et un certain nombre de fonctions de la dll doivent dessiner sur cette fenêtre en utilisant que des appels directs aux API et aucun mécanisme de Delphi (dont TCanvas qui encapsule les DeviceContext).
AMHA, cette approche n'est pas la bonne sur la répartition des responsabilités : Comme l'a dit Paul TOTH, l'application doit se charger de l'affichage et votre dll doit se limiter au dessin. Pour ce faire, l'application doit transmettre à chaque fonction appelée dans la dll le device context du moment, la fonction réalise son dessin et rend la main. L'avantage est que vous pouvez alors utiliser dans votre dll les mécanismes et les encapsulations propres à Delphi, en l'occurrence un TCanvas !
Comment ? C'est simple, vous allez créer un TCanvas dans votre fonction, lui affecter le device context reçu en paramètre, faire votre dessin, puis supprimer le Canvas avant de rendre la main.
La seule complication est côté application appelante : elle doit fournir un device context et le gérer....
Voici un extrait de code tiré d'un petit exemple que j'ai écrit à partir du code que vous aviez fourni : une application Lazarus qui appelle une dll Delphi...
Côté dll Delphi
Côté application Lazarus
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 function Cadre(HDC: HWND): Integer; var Canvas: TCanvas; begin Canvas := TCanvas.Create; try Canvas.Handle := HDC; Canvas.Font.Name := 'Arial'; Canvas.Font.Size := 12; Canvas.Pen.Color := clBlack; Canvas.TextOut(0,0,format('Page %d',[1])); Canvas.Rectangle(100, 100, 400, 400); Canvas.TextOut(50, 50, 'Ligne 2'); Canvas.TextOut(75, 75, 'Ligne 3'); Canvas.TextOut(50,100,'Ligne 4'); finally Canvas.Free; end; end; function Lines(HDC: HWND): Integer; var Canvas: TCanvas; begin Canvas := TCanvas.Create; try Canvas.Handle := HDC; Canvas.Pen.Color := clRed; Canvas.MoveTo(20, 20); Canvas.LineTo(480, 20); Canvas.MoveTo(20, 28); Canvas.LineTo(480, 28); Canvas.MoveTo(20, 36); Canvas.LineTo(480, 36); finally Canvas.Free; end; end;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 procedure TForm1.BtnCreateWinClick(Sender: TObject); begin CreateWindows; end; procedure TForm1.CreateWindows; var Frm: TForm; Img: TImage; begin Frm := TForm.Create(nil); Frm.Left := Self.Left + Self.Width + 8; Frm.Top := Self.Top; Frm.Width := 500; Frm.Height := 500; Frm.Caption := 'Fenêtre Test'; Frm.OnClose := @DynFormClose; // Lazarus contrairement à Delphi demande que l'adresse de la fonction soit préfixée par @ BtnCreateWin.Enabled := False; // Img := TImage.Create(Frm); Img.Parent := Frm; Img.Left := 0; Img.Top := 0; Img.Width := Frm.ClientWidth; Img.Height := Frm.ClientHeight; Img.Canvas.FloodFill(0, 0, clWhite, fsBorder); ShowMessage('Handle 1 : ' + IntToStr(Img.Canvas.Handle)); // Les ShowMessage n'affectent pas le résultat ! Cadre(Img.Canvas.Handle); ShowMessage('Handle 2 : ' + IntToStr(Img.Canvas.Handle)); Lines(Img.Canvas.Handle); ShowMessage('Handle 3 : ' + IntToStr(Img.Canvas.Handle)); Img.Repaint; Frm.Show; end; procedure TForm1.DynFormClose(Sender: TObject; var CloseAction: TCloseAction); begin BtnCreateWin.Enabled := True; end;
Partager