This commit is contained in:
f1iwq2
2025-03-01 13:42:15 +01:00
parent 3d109c0b3c
commit 662da541c0
21 changed files with 14472 additions and 529 deletions

507
UnitCompteur.pas Normal file
View File

@@ -0,0 +1,507 @@
unit UnitCompteur;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, math, ComCtrls, Menus;
const
pisur180=pi/180;
NbreCompteurs=10;
type
TFormCompteur = class(TForm)
ImageCompteur: TImage;
TrackBar1: TTrackBar;
LabelTrain: TLabel;
PopupMenu1: TPopupMenu;
Verrouillerdevant1: TMenuItem;
Dverrouiller1: TMenuItem;
N1: TMenuItem;
Compteurdevitesse11: TMenuItem;
Compteurdevitesse21: TMenuItem;
Compteurtachro1: TMenuItem;
ImageTachro: TImage;
procedure FormActivate(Sender: TObject);
procedure Dverrouiller1Click(Sender: TObject);
procedure Verrouillerdevant1Click(Sender: TObject);
procedure Compteurdevitesse11Click(Sender: TObject);
procedure Compteurdevitesse21Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Compteurtachro1Click(Sender: TObject);
private
{ Déclarations privées }
protected
procedure WMExitSizeMove(var Message: TMessage); message WM_EXITSIZEMOVE; // détecte fin de redimensionnement fenêtre
public
{ Déclarations publiques }
end;
var
formCompteur : array[1..10] of TformCompteur;
AigCX,AigCY,Raig,Rav : array[1..NbreCompteurs] of integer;
redX,redY,ComptA,ComptB : array[1..NbreCompteurs] of single;
FCBitMap : array[1..NbreCompteurs] of tBitmap;
VerrouilleCompteur : boolean;
LargeurCompteurs,HauteurCompteurs : integer;
Procedure Init_compteur(i : integer);
procedure aiguille_compteur_l(id,idTrain : integer);
procedure position_compteur;
procedure affiche_train_compteur(c : integer);
implementation
uses UnitPrinc, UnitTCO, UnitClock;
{$R *.dfm}
// event fin de redimmensionnement
procedure TFormCompteur.WMExitSizeMove(var Message: TMessage);
begin
inherited;
// Affiche(IntToSTR(Message.Msg)+' '+inTtOstr(message.WParam)+' '+intToSTR(message.LParam)+' '+intToSTR(message.WParamLo),clred);
LargeurCompteurs:=formCompteur[1].Width; // nouvelle largeur
init_compteur(1);
end;
// affiche le nom du train
procedure affiche_train_compteur(c : integer);
var s : string;
begin
s:=trains[IdTrainClic].nom_train;
FormCompteur[c].caption:=s;
with FormCompteur[c].labelTrain do
begin
caption:=s;
Width:=FormCompteur[c].Width-5;
end;
end;
procedure aiguille_compteur_l(id,idTrain : integer);
var x1,y1,x2,y2,x3,y3,x4,y4,vitesse,vitesseFin,lim,him : integer;
angleDeb,AngleFin,sinD,cosD,sinF,cosF : extended ;
begin
if compteur<1 then exit;
if idTrain<>0 then
begin
vitesse:=abs(trains[idTrain].VitesseCompteur);
vitesseFin:=abs(trains[idTrain].vitesseCons);
end
else
begin
vitesse:=0;VitesseFin:=0;
end;
// convertir les vitesses instantanées et fin en angles par
// la formule angle=A.vitesse+b
angleDeb:=comptA[id]*vitesse+comptB[id];
angleFin:=ComptA[id]*vitesseFin+comptB[id];
sincos(angleDeb*pisur180,sinD,cosD);
with formCompteur[id].ImageCompteur do
begin
lim:=width;
him:=Height;
end;
with formCompteur[id].ImageCompteur.Canvas do
begin
copyrect(rect(0,0,lim,him),FcBitMap[id].canvas,rect(0,0,lim,him));
// afficher l'arc vert
if (vitesse<>0) and (angleDeb<>angleFin) then
begin
x1:=AigCX[id] - rav[id];
y1:=AigCY[id] - rav[id];
x2:=AigCX[id] + rav[id];
y2:=AigCY[id] + rav[id];
x3:=AigCX[id] + Round(rav[id]*sinD);
y3:=AigCY[id] - Round(rav[id]*cosD);
sincos(AngleFin*pisur180,sinF,cosF); // paramètres d'angleFin
x4:=AigCX[id] + Round(rav[id]*sinF);
y4:=AigCY[id] - Round(rav[id]*cosF);
pen.color:=clLime;
moveTo(X3,y3);LineTo(x3+2,y3+2);
if angleDeb>angleFin then setArcDirection(Handle,AD_COUNTERCLOCKWISE) else setArcDirection(Handle,AD_CLOCKWISE) ;
Arc(x1,y1,x2,y2,x3,y3,x4,y4);
end;
// Afficher l'aiguille (angleDeb)
if compteur=3 then Pen.color:=$ffa0a0 else Pen.color:=clred;
MoveTo(AigCX[id],AigCY[id]);
LineTo(round(rAig[id]*sinD)+AigCX[id],round(-rAig[id]*cosD)+AigCY[id]);
end;
formCompteur[id].ImageCompteur.Repaint;
end;
procedure compteur_tachro;
var l,av,n,v,rayon2,rayon3,rayon4,x1,y1,x2,y2,xt,yt,lim,him,rg : integer;
angle,angleFin,incr,r,a : single;
s : string;
begin
angle:=-40; // angle début des graduations
angleFin:=220; // angle fin des graduations
incr:=2.5; // incrément d'angle en ° des graduations
n:=0;
v:=0;
lim:=fcbitmap[1].Width;
him:=fcbitmap[1].height;
with fcBitmap[1] do
begin
AigCX[1]:=width div 2; // centre aiguille
AigCY[1]:=AigCX[1];
r:=width/400; // réduction
//Raig[1]:=(Lim div 2)-round(10*r); // rayon
rg:=round(AigCX[1]/1.05); // rayon des graduations
rayon2:=Rg-round(10*r); // rayon de fin des graduations
rayon3:=Rg-round(20*r);
rayon4:=Rg-round(20*r); // chiffres
with fcBitmap[1].Canvas do
begin
pen.width:=1;
pen.Color:=clWhite;
Brush.Color:=clBlack;
Brush.Style:=bsSolid;
FillRect(Rect(0,0,lim,him));
Cercle(fcBitmap[1].Canvas,AigCX[1],AigCY[1],round(130*r),clGray,clblack);
Cercle(fcBitmap[1].Canvas,AigCX[1],AigCY[1],round(10*r),clwhite,clWhite);
font.Name:='Arial';
brush.color:=clBlack;
pen.color:=clwhite;
font.color:=clWhite;
font.size:=round(r*20);
//Affiche(intToSTR(font.size),clred);
font.style:=[fsbold];
end;
end;
// dessine le cadran
repeat
// affiche les chiffres
if n mod 10=0 then
begin
s:=intToSTR(round(v));
// pour centrer le chiffre de vitesse sur l'axe de la graduation
a:=(fcBitmap[1].canvas.TextWidth(s) div 2)/rayon4;
if abs(a)>1 then a:=1;
a:=arcSin(a);
l:=round(a*180/pi);
//Affiche(intToSTR(l),clYellow);
xt:=round(cos((angle+180-l)*pisur180)*rayon4)+AigCX[1];
yt:=round(sin((angle+180-l)*pisur180)*rayon4)+AigCY[1];
// affiche les chiffres
{$IF CompilerVersion >= 28.0}
av:=round(90-angle)*10;
fcBitmap[1].canvas.font.orientation:=av;
fcBitmap[1].canvas.Textout(xt,yt,s);
{$ELSE}
av:=10+round(90-angle)*10;
AffTexteIncliBordeTexture(fcBitmap[1].canvas,xt,yt,fcBitmap[1].canvas.font,clYellow,0,pmcopy,s,av);
{$IFEND}
inc(v,20);
end;
x1:=round(cos((angle+180)*pisur180)*Rg)+AigCX[1];
y1:=round(sin((angle+180)*pisur180)*Rg)+AigCY[1];
// gros traits
if n mod 5 = 0 then
begin
fcBitmap[1].canvas.pen.Width:=round(4*r);
x2:=round(cos((angle+180)*pisur180)*rayon3)+AigCX[1];
y2:=round(sin((angle+180)*pisur180)*rayon3)+AigCY[1];
end
else
begin
// traits fins
fcBitmap[1].canvas.pen.Width:=round(2*r);
x2:=round(cos((angle+180)*pisur180)*rayon2)+AigCX[1];
y2:=round(sin((angle+180)*pisur180)*rayon2)+AigCY[1];
end;
with fcBitmap[1].canvas do
begin
MoveTo(x1,y1);
lineTo(x2,y2);
end;
inc(n);
angle:=angle+incr; // 18
until angle>AngleFin+incr;
lim:=formCompteur[1].ImageTachro.width;
him:=formCompteur[1].ImageTachro.height;
// copie l'image tachro mise à l'échelle
StretchBlt(fcBitmap[1].canvas.Handle,round(145*r),round(85*r),round(lim*r),round(him*r),
FormCompteur[1].ImageTachro.canvas.Handle,0,0,lim,him,srcCopy);
end;
Procedure Init_compteur(i : integer);
const ofs=20; // décalage entre la taille de l'image et de la fenetre
var l,h,lim,him,hfen,mini,maxi,vmax : integer;
begin
if i<1 then exit;
//Affiche('Init compteur de vitesse',clYellow);
// fixer la largeur de la fenêtre
formCompteur[i].Width:=LargeurCompteurs;
Lim:=LargeurCompteurs-ofs;
formCompteur[i].ImageCompteur.width:=Lim;
case compteur of
1 :
begin
mini:=-135;
maxi:=152;
vmax:=127;
l:=formPrinc.ImageCompteur1.width;
h:=formPrinc.ImageCompteur1.height;
end;
2 :
begin
mini:=-81; // le 0 est à mini degrés
maxi:=82; // le vmax est à max degrés
vmax:=160; // vmax du compteur
l:=formPrinc.ImageCompteur2.width;
h:=formPrinc.ImageCompteur2.height;
end;
3 :
begin
mini:=-130; // le 0 est à mini degrés
maxi:=132; // le vmax est à max degrés
vmax:=210; // vmax du compteur
l:=400;
h:=340;
end;
end;
ComptA[i]:=(maxi-mini)/vmax; // pente de conversion vitesse en degrés compteur
ComptB[i]:=mini; // coordonnées origine conversion
if l>=h then
begin
him:=round(lim*h/l); // hauteur image
//Affiche('Lim him = '+IntToSTR(lim)+' '+intToSTR(him),clLime);
//Affiche('L h = '+IntToSTR(l)+' '+intToSTR(h),clLime);
end
else
begin
him:=round(h*largeurCompteurs/l); // a revoir
end;
redX[i]:=Lim/l;
redY[i]:=Him/h;
case compteur of
1 : rav[i]:=round(70*redx[i]); // rayon de l'arc vert
2 : rav[i]:=round(100*redx[i]);
3 : rav[i]:=round(122*redx[i]);
end;
with formCompteur[i] do
begin
if VerrouilleCompteur then Left:=formprinc.Left+formprinc.Width-width;
// ajuster hauteur de la fenetre
hfen:=him+LabelTrain.Height+40; //formCompteur[i].TrackBar1.height+48;//+10;
height:=hfen;
with constraints do
begin
MaxWidth:=400;
MinWidth:=200;
MaxHeight:=450;
MinHeight:=100;
end;
ImageCompteur.Width:=Lim;
ImageCompteur.Height:=Him;
ImageCompteur.Picture.Bitmap.Width:=Lim;
ImageCompteur.Picture.Bitmap.Height:=Him;
trackBar1.top:=ImageCompteur.Height+8;
trackBar1.width:=LargeurCompteurs-5;
LabelTrain.top:=ImageCompteur.top+ImageCompteur.Height; //trackBar1.top+formCompteur[i].trackBar1.height;
LabelTrain.Width:=Lim-2;
end;
// imageC <-- FCBitMap (on écrit les vitesses) <- ImageCompteur2 (grande)
// créer un bitmap réduit qui sert de référence
FCBitMap[i].Free;
FCBitMap[i]:=TBitMap.Create;
FCBitMap[i].Width:=lim;
FCBitMap[i].Height:=him;
with FCBitMap[i].Canvas do
begin
Brush.Style:=bsSolid;
Brush.Color:=$141414; //$e0e0e0;
if compteur=1 then StretchDraw(rect(0,0,Lim,Him),Formprinc.ImageCompteur1.Picture.Bitmap);
if compteur=2 then StretchDraw(rect(0,0,Lim,Him),Formprinc.ImageCompteur2.Picture.Bitmap);
font.name:='arial';
font.Style:=[fsBold];
// les compteurs 1 et 2 proviennent de bitmaps
// le compteur 3 (tachro) est dessiné par "compteur_tachro"
case compteur of
1 : begin
Brush.Style:=bsSolid;
Brush.Color:=$1F1A17;
font.color:=clwhite;
font.size:=round(redx[i]*10);
TextOut(round(50*redX[i]),round(128*redY[i]),'0');
TextOut(round(36*redX[i]),round(90*redY[i]),'20');
TextOut(round(50*redX[i]),round(54*redY[i]),'40');
TextOut(round(90*redX[i]),round(36*redY[i]),'60');
TextOut(round(129*redX[i]),round(53*redY[i]),'80');
TextOut(round(137*redX[i]),round(91*redY[i]),'100');
TextOut(round(126*redX[i]),round(126*redY[i]),'120');
// centre de l'aiguille
AigCX[i]:=round(98*redX[i]);
AigCY[i]:=round(96*redY[i]);
rAig[i]:=round(AigCX[i] / 1.5);
end;
2 : begin
font.color:=clblue;
Brush.Style:=bsSolid;
Brush.Color:=clWhite;
font.size:=round(redx[i]*22);
TextOut(round(47*redX[i]),round(167*redY[i]),'0');
TextOut(round(58*redX[i]),round(118*redY[i]),'20');
TextOut(round(89*redX[i]),round(80*redY[i]),'40');
TextOut(round(133*redX[i]),round(50*redY[i]),'60');
TextOut(round(190*redX[i]),round(40*redY[i]),'80');
TextOut(round(232*redX[i]),round(50*redY[i]),'100');
TextOut(round(274*redX[i]),round(80*redY[i]),'120');
TextOut(round(306*redX[i]),round(118*redY[i]),'140');
TextOut(round(324*redX[i]),round(168*redY[i]),'160');
// centre de l'aiguille et longueur
AigCX[i]:=round(204*redX[i]);
AigCY[i]:=round(207*redY[i]);
rAig[i]:=round(AigCX[i]/1.05);
end;
3 : begin
// centre de l'aiguille et longueur
AigCX[i]:=lim div 2;
AigCY[i]:=him div 2;
rAig[i]:=round(AigCX[i]/1.07);
compteur_tachro;
end;
end;
end;
// ajuste la taille
with FormCompteur[i].ImageCompteur do
begin
canvas.pen.color:=clRed;
canvas.pen.width:=3; // épaisseur aiguille
end;
//formprinc.DoubleBuffered:=true;
Aiguille_compteur_l(i,IdTrainClic);
end;
procedure position_compteur;
begin
if not(Verrouillecompteur) then exit;
if formCompteur[1]=nil then exit;
with formCompteur[1] do
begin
Left:=formprinc.Left+formprinc.Width-width-2;
//left:=0;
end;
if (formClock<>nil) and not(fermeSC) then
begin
if FormClock.Showing then
formCompteur[1].top:=formclock.top-formCompteur[1].height
else
formCompteur[1].top:=FormPrinc.top+formprinc.PageControl.top+100;
end;
//Affiche(intToSTR(formCompteur[1].top),clYellow);
end;
procedure TFormCompteur.FormActivate(Sender: TObject);
begin
//Affiche('FormCompteur activate',clyellow);
if VerrouilleCompteur then position_compteur;
end;
procedure TFormCompteur.Dverrouiller1Click(Sender: TObject);
begin
SetWindowPos(Handle,HWND_NOTOPMOST,0,0,0,0,SWP_NoMove or SWP_NoSize);
Verrouillerdevant1.Checked:=false;
Dverrouiller1.Checked:=true;
VerrouilleCompteur:=false;
end;
procedure TFormCompteur.Verrouillerdevant1Click(Sender: TObject);
begin
SetWindowPos(Handle,HWND_TOPMOST,0,0,0,0,SWP_NoMove or SWP_NoSize);
Verrouillerdevant1.Checked:=true;
Dverrouiller1.Checked:=false;
VerrouilleCompteur:=true;
end;
procedure TFormCompteur.Compteurdevitesse11Click(Sender: TObject);
begin
Compteurdevitesse11.checked:=true;
Compteurdevitesse21.checked:=false;
Compteurtachro1.checked:=false;
compteur:=1;
init_compteur(1);
affiche_train_compteur(1);
aiguille_compteur_l(1,idTrainClic);
end;
procedure TFormCompteur.Compteurdevitesse21Click(Sender: TObject);
begin
Compteurdevitesse11.checked:=false;
Compteurdevitesse21.checked:=true;
Compteurtachro1.checked:=false;
compteur:=2;
init_compteur(1);
affiche_train_compteur(1);
aiguille_compteur_l(1,idTrainClic);
end;
procedure TFormCompteur.Compteurtachro1Click(Sender: TObject);
begin
Compteurdevitesse11.checked:=false;
Compteurdevitesse21.checked:=false;
Compteurtachro1.checked:=true;
compteur:=3;
init_compteur(1);
affiche_train_compteur(1);
aiguille_compteur_l(1,idTrainClic);
end;
procedure TFormCompteur.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
AffCompteur:=false;
end;
begin
LargeurCompteurs:=200;
HauteurCompteurs:=200;
end.