aflookup.pas

来自「delphi编程控件」· PAS 代码 · 共 1,439 行 · 第 1/3 页

PAS
1,439
字号
unit aflookup;
(*
 COPYRIGHT (c) RSD software 1997 - 98
 All Rights Reserved.
*)

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  DB;

type
  TAutoCustomLookup = class;

  TAutoListSourceLink = class(TDataLink)
  private
    AutoCustomLookup: TAutoCustomLookup;
  protected
    procedure ActiveChanged; override;
    procedure DataSetChanged; override;
  end;

  TAutoCustomLookup = class(TCustomControl)
  private
    FLookupSource: TDataSource;
    FListLink: TAutoListSourceLink;
    FKeyFieldName: string;
    FListFieldName: string;
    FListFieldIndex: Integer;
    FKeyField: TField;
    FListField: TField;
    FListFields: TList;
    FKeyValue: Variant;
    FSearchText: string;
    FFocused: Boolean;
    FItems : TStrings;
    FItemsAlignment : TAlignment;
    FItemsColor : TColor;
    IsValueItems : Integer;
    FCaption : Boolean;

    function GetBorderSize: Integer;
    function GetKeyFieldName: string;
    function GetListSource: TDataSource;
    function GetTextHeight: Integer;
    procedure ItemsChange(Sender : TObject);
    procedure ListLinkActiveChanged; virtual;
    procedure ListLinkDataChanged; virtual;
    function LocateKey: Boolean;
    procedure ProcessSearchKey(Key: Char);
    procedure SelectKeyValue(const Value: Variant);
    procedure SetItems(Value: TStrings);
    procedure SetItemIndex(Value : Integer);
    procedure SetItemsColor(Value: TColor);
    procedure SetKeyFieldName(const Value: string);
    procedure SetKeyValue(const Value: Variant);
    procedure SetListFieldName(const Value: string);
    procedure SetListSource(Value: TDataSource);
    procedure WMGetDlgCode(var Message: TMessage); message WM_GETDLGCODE;
    procedure WMKillFocus(var Message: TMessage); message WM_KILLFOCUS;
    procedure WMSetFocus(var Message: TMessage); message WM_SETFOCUS;
  protected
    FListActive: Boolean;

    function GetItemsLabel(Index : Integer) : String;
    function GetItemsValue(Index : Integer) : Variant;
    function FindItemsValue(V : Variant) : Integer;
    procedure KeyValueChanged; virtual;
    procedure Notification(AComponent: TComponent;
      Operation: TOperation); override;
    property Items: TStrings read FItems write SetItems;
    property ItemIndex : Integer read IsValueItems write SetItemIndex;
    property ItemsColor : TColor read FItemsColor write SetItemsColor;
    property ItemsAlignment : TAlignment read FItemsAlignment write FItemsAlignment;
    property KeyValue: Variant read FKeyValue write SetKeyValue;
    property ListFieldIndex: Integer read FListFieldIndex write FListFieldIndex default 0;
    property ParentColor default False;
    property TabStop default True;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    property KeyField: string read GetKeyFieldName write SetKeyFieldName;
    property ListField: string read FListFieldName write SetListFieldName;
    property ListSource: TDataSource read GetListSource write SetListSource;
    property Caption : Boolean read FCaption write FCaption;
  end;

  TAutoCustomLookupList = class(TAutoCustomLookup)
  private
    FRecordIndex: Integer;
    FRecordCount: Integer;
    FRealRowCount: Integer;
    FRowCount: Integer;
    FBorderStyle: TBorderStyle;
    FKeySelected: Boolean;
    FTracking: Boolean;
    FTimerActive: Boolean;
    FLockPosition: Boolean;
    FMousePos: Integer;
    FPopup : Boolean;
    function GetKeyIndex(Delta : Integer): Boolean;
    procedure ListLinkActiveChanged; override;
    procedure ListLinkDataChanged; override;
    procedure SelectCurrent;
    procedure SelectItemAt(X, Y: Integer);
    procedure SetBorderStyle(Value: TBorderStyle);
    procedure SetRowCount(Value: Integer);
    procedure StopTimer;
    procedure StopTracking;
    procedure TimerScroll;
    procedure UpdateScrollBar;
    procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
    procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
    procedure WMCancelMode(var Message: TMessage); message WM_CANCELMODE;
    procedure WMTimer(var Message: TMessage); message WM_TIMER;
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWnd; override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure KeyPress(var Key: Char); override;
    procedure KeyValueChanged; override;    
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
    property KeyValue;
  published
    property Align;
    property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
    property Caption;    
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragMode;
    property Enabled;
    property Font;
    property Items;
    property ItemsAlignment;
    property ItemsColor;
    property KeyField;
    property ListField;
    property ListFieldIndex;
    property ListSource;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property RowCount: Integer read FRowCount write SetRowCount stored False;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
  end;

  TAutoDBLookupList = class(TAutoCustomLookupList)
  end;

  TAutoPopupDataList = class(TAutoCustomLookupList)
  private
    procedure WMMouseActivate(var Message: TMessage); message WM_MOUSEACTIVATE;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;


  TAutoDropDownAlign = (daLeft, daRight, daCenter);

  TAutoCustomLookupCombo = class(TAutoCustomLookup)
  private
    FDataList: TAutoPopupDataList;
    FText: string;
    FDropDownRows: Integer;
    FDropDownWidth: Integer;
    FDropDownAlign: TAutoDropDownAlign;
    FListVisible: Boolean;
    FTracking: Boolean;
    FAlignment: TAlignment;
    FOnDropDown: TNotifyEvent;
    FOnCloseUp: TNotifyEvent;
    procedure ListLinkActiveChanged; override;
    procedure ListMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure StopTracking;
    procedure TrackButton(X, Y: Integer);
    procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
    procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
    procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
    procedure WMCancelMode(var Message: TMessage); message WM_CANCELMODE;
    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  protected
    FButtonWidth: Integer;
    FPressed: Boolean;
          
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Paint; override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure KeyPress(var Key: Char); override;
    procedure KeyValueChanged; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
    procedure CloseUp(Accept: Boolean);
    procedure DropDown;
    property KeyValue;
    property ListVisible: Boolean read FListVisible;
    property Text: string read FText;
  published
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragMode;
    property DropDownAlign: TAutoDropDownAlign read FDropDownAlign write FDropDownAlign default daLeft;
    property DropDownRows: Integer read FDropDownRows write FDropDownRows default 7;
    property DropDownWidth: Integer read FDropDownWidth write FDropDownWidth default 0;
    property Enabled;
    property Font;
    property Items;
    property ItemsAlignment;    
    property ItemsColor;
    property KeyField;
    property ListField;
    property ListFieldIndex;
    property ListSource;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;
    property OnClick;
    property OnCloseUp: TNotifyEvent read FOnCloseUp write FOnCloseUp;
    property OnDragDrop;
    property OnDragOver;
    property OnDropDown: TNotifyEvent read FOnDropDown write FOnDropDown;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
  end;

implementation
{ TListSourceLink }

procedure TAutoListSourceLink.ActiveChanged;
begin
  if AutoCustomLookup <> nil then AutoCustomLookup.ListLinkActiveChanged;
end;

procedure TAutoListSourceLink.DataSetChanged;
begin
  if AutoCustomLookup <> nil then AutoCustomLookup.ListLinkDataChanged;
end;

{ TAutoCustomLookup }

function VarEquals(const V1, V2: Variant): Boolean;
begin
  Result := False;
  try
    Result := V1 = V2;
  except
  end;
end;

var
  SearchTickCount: Integer = 0;

constructor TAutoCustomLookup.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  if NewStyleControls then
    ControlStyle := [csOpaque] else
    ControlStyle := [csOpaque, csFramed];
  ParentColor := False;
  TabStop := True;
  FItems := TStringList.Create;
  TStringList(FItems).OnChange := ItemsChange;
  FLookupSource := TDataSource.Create(Self);
  FListLink := TAutoListSourceLink.Create;
  FListLink.AutoCustomLookup := Self;
  FListFields := TList.Create;
  FKeyValue := Null;
  FItemsColor := clBtnFace;
  IsValueItems := -1;
end;

destructor TAutoCustomLookup.Destroy;
begin
  FItems.Free;
  FListFields.Free;
  FListLink.AutoCustomLookup := nil;
  FListLink.Free;
  inherited Destroy;
end;

function TAutoCustomLookup.GetBorderSize: Integer;
var
  Params: TCreateParams;
  R: TRect;
begin
  CreateParams(Params);
  SetRect(R, 0, 0, 0, 0);
  AdjustWindowRectEx(R, Params.Style, False, Params.ExStyle);
  Result := R.Bottom - R.Top;
end;

function TAutoCustomLookup.GetKeyFieldName: string;
begin
  Result := FKeyFieldName;
end;

function TAutoCustomLookup.GetListSource: TDataSource;
begin
  Result := FListLink.DataSource;
end;

function TAutoCustomLookup.GetTextHeight: Integer;
var
  DC: HDC;
  SaveFont: HFont;
  Metrics: TTextMetric;
begin
  DC := GetDC(0);
  SaveFont := SelectObject(DC, Font.Handle);
  GetTextMetrics(DC, Metrics);
  SelectObject(DC, SaveFont);
  ReleaseDC(0, DC);
  Result := Metrics.tmHeight;
end;

procedure TAutoCustomLookup.KeyValueChanged;
begin
end;

procedure TAutoCustomLookup.ItemsChange(Sender : TObject);
begin
  Paint;
end;  

procedure TAutoCustomLookup.ListLinkActiveChanged;
var
  DataSet: TDataSet;
begin
  FListActive := False;
  FKeyField := nil;
  FListField := nil;
  FListFields.Clear;
  if FListLink.Active and (FKeyFieldName <> '') then  begin
    DataSet := FListLink.DataSet;
    FKeyField := DataSet.FieldByName(FKeyFieldName);
    DataSet.GetFieldList(FListFields, FListFieldName);
    if FListFields.Count = 0 then FListFields.Add(FKeyField);
     if (FListFieldIndex >= 0) and (FListFieldIndex < FListFields.Count) then
       FListField := FListFields[FListFieldIndex] else
       FListField := FListFields[0];
    FListActive := True;
  end;
end;

procedure TAutoCustomLookup.ListLinkDataChanged;
begin
end;

function TAutoCustomLookup.LocateKey: Boolean;
begin
  Result := False;

  IsValueItems := FindItemsValue(FKeyValue);
  if(IsValueItems > -1) then begin;
    Result := True;
    exit;
  end;
  if not VarIsNull(FKeyValue) then begin
    try
      if FListLink.DataSet.Locate(FKeyFieldName, FKeyValue, []) then
        Result := True;
    except
    end;
  end;
end;

function TAutoCustomLookup.FindItemsValue(V : Variant) : Integer;
Var
  i : Integer;
begin
  Result := -1;
  for i := 0 to Items.Count - 1 do
    if Not VarIsNull(V) then begin
      if VarEquals(V, GetItemsValue(i)) then begin
        Result := i;
        exit;
      end;
    end
    else if VarIsNull(GetItemsValue(i)) then begin
       Result := i;
       exit;
    end;  
end;

function TAutoCustomLookup.GetItemsLabel(Index : Integer) : String;
Var
  p : Integer;
begin
  Result := '';
  if(Index > -1) And (Index < FItems.Count) then begin
    p := Pos(',', FItems[Index]);
    if(p > 0) then
      Result := Copy(FItems[Index], 1, p - 1)
    else Result := FItems[Index];
  end;
end;

function TAutoCustomLookup.GetItemsValue(Index : Integer) : Variant;
Var
  p : Integer;
  St : String;
begin
  St := '';
  if(Index > -1) And (Index < FItems.Count) then begin
    p := Pos(',', FItems[Index]);
    if(p > 0) then
      St := Copy(FItems[Index], p + 1, 1000)
    else St := FItems[Index];
  end;
  if(St = '') then
    Result := Null
  else Result := Variant(St);
end;

procedure TAutoCustomLookup.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (FListLink <> nil)
  and (AComponent = ListSource) then ListSource := nil;
end;

procedure TAutoCustomLookup.ProcessSearchKey(Key: Char);
var
  TickCount: Integer;
  S: string;

⌨️ 快捷键说明

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