fmain.pas

来自「FlexGraphics是一套创建矢量图形的VCL组件」· PAS 代码 · 共 931 行 · 第 1/2 页

PAS
931
字号
unit fMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  FlexBase, FlexUtils, FlexControls, FlexProps, Utils, ComCtrls, StdCtrls,
  ImgList, ExtCtrls, ToolWin, Buttons, ACCtrls, FlexPath;

type
  TfmMain = class(TForm)
    sbMain: TStatusBar;
    tbMain: TTabControl;
    tmSelected: TTimer;
    Panel1: TPanel;
    Panel2: TPanel;
    sbtControl: TSpeedButton;
    sbtZoomIn: TSpeedButton;
    sbtZoomOut: TSpeedButton;
    sbtOptions: TSpeedButton;
    sbtAbout: TSpeedButton;
    sbtExit: TSpeedButton;
    tmLamps: TTimer;
    tmTimeOuts: TTimer;
    fpMain: TFlexPanel;
    procedure FormCreate(Sender: TObject);
    procedure tbMainChange(Sender: TObject);
    procedure fpMainMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure fpMainNotify(Sender: TObject; Control: TFlexControl;
      Notify: TFlexNotify);
    procedure FormDestroy(Sender: TObject);
    procedure sbtExitClick(Sender: TObject);
    procedure sbtControlClick(Sender: TObject);
    procedure fpMainExit(Sender: TObject);
    procedure sbtOptionsClick(Sender: TObject);
    procedure fpMainPaintOver(ACanvas: TCanvas; AControl: TFlexControl;
      ChildrenOnly, SelectedOnly: Boolean);
    procedure tmSelectedTimer(Sender: TObject);
    procedure fpMainMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure sbtZoomClick(Sender: TObject);
    procedure sbtAboutClick(Sender: TObject);
    procedure tmLampsTimer(Sender: TObject);
    procedure tmTimeOutsTimer(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
    FCopyright: TFlexText;
    FSelectionBrush: TBrush;
    FSelected: TFlexControl;
    FSelectedDisp: integer;
    FZoneNamesLayer: TFlexLayer;
    FZoneNames: TList;
    FZones: TList;
    FDoors: TList;
    FLamps: TList;
    FLampsDisp: integer;
    FLastActive: TFlexControl;
    FLastActiveStyle: TColorStyles;
    FSchemeBtn: TFlexControl;
    FDoorsTimeOuts: TList;
    FMinimized: boolean;
    procedure SortLamps;
    function  GetSchemeBtn(PTabIndex: PInteger = Nil): TFlexControl;
    procedure PaintActive(AsActive: boolean);
    procedure PaintSchemeBtn(AsActive: boolean);
    procedure SetSelected(const Value: TFlexControl);
    function  CreateSelectedRegion(ForInvalidate: boolean = false): HRGN;
    procedure RefreshSelected;
    procedure EventsChange(Sender: TObject);
    procedure SetDoorTimeOut(Door: TFlexDoor; PassId: integer);
    procedure AppMinimize(Sender: TObject);
    procedure AppMaximize(Sender: TObject);
    procedure PaintMarquee(DC: HDC);
  public
    { Public declarations }
    procedure SetOptions;
    function  FindZone(ZoneId: integer): TFlexControl;
    function  FindPass(PassId: integer): TFlexControl;
    function  DoPass(PassId, PersonId: integer; DoOpen: boolean): boolean;
    procedure DoBlock(PassId: integer; IsBlock: boolean);
    property  Selected: TFlexControl read FSelected write SetSelected;
  end;

var
  fmMain: TfmMain;

implementation

{$R *.DFM}

uses
  dMain, fControl, fOptions, fAboutPrg, fSplash, fPersCard, FlexCards;

type
  PDoorTimeOut = ^TDoorTimeOut;
  TDoorTimeOut = record
   Door: TFlexDoor;
   PassId: integer;
   TimeToClose: TDateTime;
  end;

procedure TfmMain.FormCreate(Sender: TObject);
var i, NewWidth, NewHeight: integer;
begin
 // Creating lists
 FZoneNames := TList.Create;
 FZones := TList.Create;
 FDoors := TList.Create;
 FLamps := TList.Create;
 FDoorsTimeOuts := TList.Create;
 // Creating selection brush
 FSelectionBrush := CreateSelectionBrush(clNavy);
 // Loading from file
 LoadFlexCursors;
 fpMain.OnProgress := fmSplash.FlexProgress;
 Screen.Cursor := crHourGlass;
 try
  fpMain.LoadFromFile(ExtractFilePath(ParamStr(0))+'access.fxd');
 finally
  fpMain.OnProgress := Nil;
  Screen.Cursor := crDefault;
 end;
 // Cache all schemes bitmap
 for i:=0 to fpMain.Schemes.Count-1 do
  (fpMain.Schemes[i] as TFlexScheme).BrushProp.BitmapCache := true;
 // Sort lamp controls
 SortLamps;
 // Adjust window size
 fpMain.HorzScrollBar.Visible := False;
 fpMain.VertScrollBar.Visible := False;
 NewWidth := Width + (fpMain.DocWidth - fpMain.ClientWidth);
 NewHeight := Height + (fpMain.DocHeight - fpMain.ClientHeight);
 if (NewWidth > Screen.Width) or (NewHeight > Screen.Height) then
  WindowState := wsMaximized
 else begin
  Width := NewWidth;
  Height := NewHeight;
 end;
 fpMain.HorzScrollBar.Visible := True;
 fpMain.VertScrollBar.Visible := True;
 // Making layer "ZoneNames" non selectable
 if Assigned(FZoneNamesLayer) then FZoneNamesLayer.Selectable := false;
 fpMain.Layers.ByName['Building'].Selectable := false;
 FCopyright.Hint := 'About';
 // Load and set options from ini-file
 LoadOptions;
 SetOptions;
 // Start event
 dmMain.OnEventAdd := EventsChange;
 dmMain.AddEvent('System online', 0, 0, 0);
 tmTimeOuts.Enabled := true;
 Application.OnMinimize := AppMinimize;
 Application.OnRestore := AppMaximize;
end;

procedure TfmMain.FormDestroy(Sender: TObject);
begin
 dmMain.tmMovements.Enabled := false;
 DestroyAllFlexCards;
 HideAllPersonCards;
 // Destroy selection brush
 if Assigned(FSelectionBrush) then begin
  FSelectionBrush.Bitmap.Free;
  FSelectionBrush.Bitmap := Nil;
  FSelectionBrush.Free;
  FSelectionBrush := Nil;
 end;
 // Destroy lists
 FZoneNames.Free;
 FZones.Free;
 FDoors.Free;
 FLamps.Free;
 // Destroy door timeouts
 while FDoorsTimeOuts.Count > 0 do begin
  Dispose(PDoorTimeOut(FDoorsTimeOuts[FDoorsTimeOuts.Count-1]));
  FDoorsTimeOuts.Delete(FDoorsTimeOuts.Count-1);
 end;
 FDoorsTimeOuts.Free;
end;

procedure TfmMain.AppMinimize(Sender: TObject);
begin
 FMinimized := true;
 HideAllPersonCards;
end;

procedure TfmMain.AppMaximize(Sender: TObject);
begin
 FMinimized := false;
end;

procedure TfmMain.SetSelected(const Value: TFlexControl);
var Index: integer;
    Rgn: HRGN;
begin
 if Value = FSelected then exit;
 // Invalidate frame around old selected control
 if Assigned(FSelected) then begin
  //RefreshSelected;
  Rgn := CreateSelectedRegion(True);
  InvalidateRgn(fpMain.Handle, Rgn, false);
  DeleteObject(Rgn);
  FSelected := Nil;
 end;
 // Check Value parent scheme
 if Assigned(Value) and (Value.ParentScheme <> fpMain.ActiveScheme) then
  fpMain.ActiveScheme := Value.ParentScheme;
 // Set new selected control
 FSelected:= Value;
 if Assigned(FSelected) then begin
  // Start refresh timer
  tmSelected.Enabled := true;
  // Invalidate frame around new selected control
  RefreshSelected;
  if Assigned(fmControl) then begin
   // Locate object in lists
   if FSelected is TFlexDoor then begin
    // Locate PassA of FlexDoor
    Index := dmMain.FindPass(TFlexDoor(FSelected).PassAProp.Value);
    if Index >= 0 then begin
     fmControl.lbPasses.ItemIndex := Index;
     fmControl.pgTables.ActivePage := fmControl.tsPasses;
    end else
     fmControl.lbPasses.ItemIndex := -1;
    fmControl.RefreshPassInfo;
   end else
   if TFlexControl(FSelected).UserData.Values['ZoneID'] <> '' then begin
    // Locate zone
    Index := StrToIntDef(TFlexControl(FSelected).UserData.Values['ZoneID'], 0);
    Index := dmMain.FindZone(Index);
    if Index >= 0 then begin
     fmControl.lbZones.ItemIndex := Index;
     fmControl.pgTables.ActivePage := fmControl.tsZones;
    end else
     fmControl.lbZones.ItemIndex := -1;
    fmControl.RefreshZoneInfo;
   end;
  end;
 end;
end;

function TfmMain.CreateSelectedRegion(ForInvalidate: boolean = false): HRGN;
var GroupRect: TRect;
    GroupInited: boolean;

 procedure ProcessControl(Control: TFlexControl);
 var i: integer;
     Points: TPointArray;
     Rgn: HRGN;
 begin
  Points := Nil;
  if Control is TFlexGroup then begin
   // Process group controls
   for i:=0 to Control.Count-1 do ProcessControl(Control[i]);
  end else
  if ForInvalidate then begin
   // Create region for bounding box
   if GroupInited then
    UnionRect(GroupRect, GroupRect, Control.PaintRect)
   else begin
    GroupRect := Control.PaintRect;
    GroupInited := true;
   end;
  end else begin
   if Control.PointCount > 0 then with Control.PaintRect do begin
    // Process polyline
    Points := Control.GetTransformPoints(Left, Top, fpMain.Scale);
    Rgn := CreatePolygonRgn(Points[0], Length(Points), ALTERNATE);
   end else
   if Control is TFlexEllipse then
    // Process ellipse
    Rgn := CreateEllipticRgnIndirect(Control.PaintRect)
   else
   if Control is TFlexBox then with Control.PaintRect do begin
    // Process rectangle
    if TFlexBox(Control).RoundnessProp.Value > 0 then begin
     i := ScaleValue(TFlexBox(Control).RoundnessProp.Value, Control.Owner.Scale);
     Rgn := CreateRoundRectRgn(Left, Top, Right+1, Bottom+1, i, i);
    end else
     Rgn := CreateRectRgnIndirect(Control.PaintRect);
   end else
    // Process unknown other control (as rect)
    Rgn := CreateRectRgnIndirect(Control.PaintRect);
   if Rgn = 0 then exit;
   if Result = 0 then
    Result := Rgn
   else begin
    CombineRgn(Result, Result, Rgn, RGN_OR);
    DeleteObject(Rgn);
   end;
  end;
 end;

begin
 Result := 0;
 if not Assigned(FSelected) then exit;
 GroupInited := not ForInvalidate;
 ProcessControl(FSelected);
 if ForInvalidate and GroupInited then with GroupRect do
  Result := CreateRectRgn(Left, Top, Right+1, Bottom+1);
end;

procedure TfmMain.PaintMarquee(DC: HDC);
var Rgn: HRGN;
    P: TPoint;
begin
 // Paint selected frame
 Rgn := CreateSelectedRegion;
 if Rgn = 0 then exit;
 SetBrushOrgEx(DC, 7-FSelectedDisp, 7-FSelectedDisp, @P);
 FrameRgn(DC, Rgn, FSelectionBrush.Handle,
   Options.SelFrameWidth, Options.SelFrameWidth);
 SetBrushOrgEx(DC, P.X, P.Y, Nil);
 DeleteObject(Rgn);
end;

procedure TfmMain.fpMainPaintOver(ACanvas: TCanvas; AControl: TFlexControl;
  ChildrenOnly, SelectedOnly: Boolean);
begin
 if Assigned(FSelected) and tmSelected.Enabled then
  PaintMarquee(ACanvas.Handle);
end;

procedure TfmMain.RefreshSelected;
var DC: HDC;
begin
 if not Assigned(FSelected) then exit;
 DC := GetDC(fpMain.Handle);
 try
  PaintMarquee(DC);
 finally
  ReleaseDC(fpMain.Handle, DC);
 end;
end;

procedure TfmMain.tmSelectedTimer(Sender: TObject);
begin
 dec(FSelectedDisp);
 FSelectedDisp := FSelectedDisp and 7;
 RefreshSelected;
end;

procedure TfmMain.tmLampsTimer(Sender: TObject);
const
  NumColors = 6;
  RunColors: array[0..NumColors-1] of TColor = (
   // $00800000, $00901D0A, $00A84717, $00BF7125, $00D89B32, $00EEC440 );
      $000000FF, $00002AFF, $000064FF, $00009CFF, $0000D5FF, $0000FFFF );
   // $00800000, $00800000, $00800000, $00800000, $00800000, $00FFFFFF );
var i, Idx: integer;
begin
 if FLampsDisp = 0
  then FLampsDisp := NumColors - 1
  else dec(FLampsDisp);
 for i:=0 to FLamps.Count-1 do with TFlexEllipse(FLamps[i]) do
  case Options.LampsEffect of
   leRunning:
     begin
      Idx := (i+FLampsDisp) mod NumColors;
      BrushProp.Color := RunColors[Idx];
     end;
   leFlashing:
     if (i+FLampsDisp) and 1 = 0
      then BrushProp.Color := clNavy
      else BrushProp.Color := clAqua;
  end;
end;

function TfmMain.FindZone(ZoneId: integer): TFlexControl;
var i: integer;
begin
 Result := Nil;
 for i:=0 to FZones.Count-1 do
  if StrToIntDef(TFlexControl(FZones[i]).UserData.Values['ZoneID'], 0) =
     ZoneId then begin
   Result := TFlexControl(FZones[i]);
   break;
  end;
end;

function TfmMain.FindPass(PassId: integer): TFlexControl;
var i: integer;
begin
 Result := Nil;
 for i:=0 to FDoors.Count-1 do
  if (TFlexDoor(FDoors[i]).PassAProp.Value = PassId) or
     (TFlexDoor(FDoors[i]).PassBProp.Value = PassId) then begin
   Result := TFlexControl(FDoors[i]);
   break;
  end;
end;

procedure TfmMain.tbMainChange(Sender: TObject);
var Scheme: TFlexControl;
begin
 Scheme := Nil;
 case tbMain.TabIndex of
  0: Scheme := fpMain.FindControl('MainPlan');
  1: Scheme := fpMain.FindControl('ControlPost');
  2: Scheme := fpMain.FindControl('AdmGrandFloor');
  3: Scheme := fpMain.FindControl('ProdGrandFloor');
  4: Scheme := fpMain.FindControl('TechGrandFloor');
 end;
 if Assigned(Scheme) and (fpMain.ActiveScheme <> TFlexScheme(Scheme)) then begin
  HideAllPersonCards;
  fpMain.ActiveScheme := TFlexScheme(Scheme);
 end;
end;

procedure TfmMain.SetOptions;
var i: integer;
    Layer: TFlexLayer;
begin
 fpMain.ShowHint := Options.ShowHints;
 case Options.ShowZoneCaptions of
  zsNone:
    begin
     // Make ZoneNames layer invisible
     if Assigned(FZoneNamesLayer) then FZoneNamesLayer.Visible := False;
    end;
  zsSelected:
    begin
     // Hide all ZoneName controls
     for i:=0 to FZoneNames.Count-1 do
      TFlexControl(FZoneNames[i]).Visible := False;
     // Make ZoneNames layer visible
     if Assigned(FZoneNamesLayer) then FZoneNamesLayer.Visible := True;
    end;
  zsAll:
    begin
     // Show all ZoneName controls
     for i:=0 to FZoneNames.Count-1 do
      TFlexControl(FZoneNames[i]).Visible := true;
     // Make ZoneNames layer visible
     if Assigned(FZoneNamesLayer) then FZoneNamesLayer.Visible := True;
    end;
 end;
 Layer := fpMain.Layers.ByName['Lamps'];
 case Options.LampsEffect of
  leNone:
    begin
     if Assigned(Layer) then Layer.Visible := false;
    end;
  leFlashing,
  leRunning:
    begin
     if Assigned(Layer) then Layer.Visible := true;
     tmLamps.Enabled := true;
    end;
 end;

 if not Options.ShowPersonsCards or not Options.Emulation then begin
  HideAllPersonCards;
  DestroyAllFlexCards;
 end else
 if Options.ShowCardsInFlex
  then HideAllPersonCards
  else DestroyAllFlexCards;
 // Emualtion
 dmMain.tmMovements.Enabled := Options.Emulation;
end;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?