508 lines
14 KiB
ObjectPascal
508 lines
14 KiB
ObjectPascal
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.
|