aflookup.pas

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

PAS
1,439
字号
begin
  if (FListField <> nil) and (FListField.DataType = ftString) then
    case Key of
      #8, #27: FSearchText := '';
      #32..#255:
        begin
          TickCount := GetTickCount;
          if TickCount - SearchTickCount > 2000 then FSearchText := '';
          SearchTickCount := TickCount;
          if Length(FSearchText) < 32 then
          begin
            S := FSearchText + Key;

            if FListLink.DataSet.Locate(FListField.FieldName, S,
              [loCaseInsensitive, loPartialKey]) then
            begin
              SelectKeyValue(FKeyField.Value);
              FSearchText := S;
            end;
          end;
        end;
    end;
end;

procedure TAutoCustomLookup.SelectKeyValue(const Value: Variant);
begin
  SetKeyValue(Value);
  Repaint;
  Click;
end;

procedure TAutoCustomLookup.SetKeyFieldName(const Value: string);
begin
  if FKeyFieldName <> Value then
  begin
    FKeyFieldName := Value;
    ListLinkActiveChanged;
  end;
end;

procedure TAutoCustomLookup.SetItems(Value: TStrings);
begin
  Items.Assign(Value);
end;

procedure TAutoCustomLookup.SetItemIndex(Value : Integer);
begin
  if(Value >= Items.Count) then
    Value := -1;
  if(IsValueItems <> Value) then begin
     IsValueItems := Value;
     FKeyValue := GetItemsValue(Value);
     KeyValueChanged;
  end;
end;

procedure TAutoCustomLookup.SetItemsColor(Value: TColor);
begin
  FItemsColor := Value;
  Paint;
end;

procedure TAutoCustomLookup.SetKeyValue(const Value: Variant);
begin
  if not VarEquals(FKeyValue, Value) then
  begin
    FKeyValue := Value;
    KeyValueChanged;
  end;
end;

procedure TAutoCustomLookup.SetListFieldName(const Value: string);
begin
  if FListFieldName <> Value then
  begin
    FListFieldName := Value;
    ListLinkActiveChanged;
  end;
end;

procedure TAutoCustomLookup.SetListSource(Value: TDataSource);
begin
  FListLink.DataSource := Value;
  if Value <> nil then Value.FreeNotification(Self);
end;

procedure TAutoCustomLookup.WMGetDlgCode(var Message: TMessage);
begin
  Message.Result := DLGC_WANTARROWS or DLGC_WANTCHARS;
end;

procedure TAutoCustomLookup.WMKillFocus(var Message: TMessage);
begin
  FFocused := False;
  Invalidate;
end;

procedure TAutoCustomLookup.WMSetFocus(var Message: TMessage);
begin
  FFocused := True;
  Invalidate;
end;

{ TAutoCustomLookupList }

constructor TAutoCustomLookupList.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Width := 121;
  FBorderStyle := bsSingle;
  RowCount := 7;
end;

procedure TAutoCustomLookupList.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do
    if FBorderStyle = bsSingle then
      if NewStyleControls and Ctl3D then
        ExStyle := ExStyle or WS_EX_CLIENTEDGE
      else
        Style := Style or WS_BORDER;
end;

procedure TAutoCustomLookupList.CreateWnd;
begin
  inherited CreateWnd;
  UpdateScrollBar;
end;

function TAutoCustomLookupList.GetKeyIndex(Delta : Integer): Boolean;
var
  FieldValue: Variant;
  i : Integer;
begin
  Result := True;
  if not VarIsNull(FKeyValue) then begin
    if(IsValueItems >= 0) then begin
      KeyValue := GetItemsValue(IsValueItems);
      if(Delta < 0) then begin
        if(IsValueItems + Delta < 0) then
          IsValueItems := 0
        else IsValueItems := IsValueItems + Delta;
      end;
      if(Delta > 0) then begin
        if(IsValueItems + Delta >= Items.Count) then begin
          Delta := Delta - Items.Count + IsValueItems;
          FListLink.DataSet.First;
          FListLink.DataSet.MoveBy(Delta);
          IsValueItems := -1;          
          exit;
        end
        else IsValueItems := IsValueItems + Delta;
      end;
    end;
    if(IsValueItems >= 0) then exit;

    for i := 0 to FRecordCount - 1 do    begin
      FListLink.ActiveRecord := i;
      FieldValue := FKeyField.Value;
      FListLink.ActiveRecord := FRecordIndex;
      if VarEquals(FieldValue, FKeyValue) then break;
    end;
    if(i = FRecordCount) then begin
      Result := False;
      exit;
    end;
    if(Delta < 0) then begin
      FListLink.DataSet.Prior;
      if(FListLink.DataSet.BOF) And (FItems.Count > 0 )then begin
        IsValueItems := FItems.Count -1;
        KeyValue := GetItemsValue(IsValueItems);
        exit;
      end;  
    end;
    FListLink.DataSet.MoveBy(i - FRecordIndex + Delta);
  end;
end;

procedure TAutoCustomLookupList.KeyDown(var Key: Word; Shift: TShiftState);
Var
  Delta : Integer;
begin
  inherited KeyDown(Key, Shift);
  begin
    Delta := 0;
    case Key of
      VK_UP, VK_LEFT: Delta := -1;
      VK_DOWN, VK_RIGHT: Delta := 1;
      VK_PRIOR: Delta := 1 - FRealRowCount;
      VK_NEXT: Delta := FRealRowCount - 1;
      VK_HOME: Delta := -Maxint;
      VK_END: Delta := Maxint;
    end;
    if Delta <> 0 then
    begin
      FSearchText := '';
      if Delta = -Maxint then begin
        FListLink.DataSet.First;
        IsValueItems := -1;
      end
      else
        if Delta = Maxint then begin
          FListLink.DataSet.Last;
          IsValueItems := -1;
        end
        else begin
          if Not GetKeyIndex(Delta) then begin
            KeyValueChanged;
          end;
        end;
      SelectCurrent;
    end;
  end;
end;

procedure TAutoCustomLookupList.KeyPress(var Key: Char);
begin
  inherited KeyPress(Key);
  ProcessSearchKey(Key);
end;

procedure TAutoCustomLookupList.KeyValueChanged;
begin
  if FListActive and not FLockPosition then
    if not LocateKey then FListLink.DataSet.First;
end;

procedure TAutoCustomLookupList.ListLinkActiveChanged;
begin
  try
    inherited;
  finally
    if FListActive then KeyValueChanged else ListLinkDataChanged;
  end;
end;

procedure TAutoCustomLookupList.ListLinkDataChanged;
begin
  if FListActive then
  begin
    FRecordIndex := FListLink.ActiveRecord;
    FRecordCount := FListLink.RecordCount;
    FKeySelected := not VarIsNull(FKeyValue) or
      not FListLink.DataSet.BOF;
  end else
  begin
    FRecordIndex := 0;
    FRecordCount := 0;
    FKeySelected := False;
  end;
  if HandleAllocated then
  begin
    UpdateScrollBar;
    Invalidate;
  end;
end;

procedure TAutoCustomLookupList.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
begin
  if Button = mbLeft then begin
    FSearchText := '';
    if not FPopup then
    begin
      SetFocus;
      if not FFocused then Exit;
    end;
    if ssDouble in Shift then begin
      if FRecordIndex = Y div GetTextHeight then DblClick;
    end
    else begin
      MouseCapture := True;
      FTracking := True;
      SelectItemAt(X, Y);
    end;
  end;
  inherited MouseDown(Button, Shift, X, Y);
end;

procedure TAutoCustomLookupList.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
  if FTracking then
  begin
    SelectItemAt(X, Y);
    FMousePos := Y;
    TimerScroll;
  end;
  inherited MouseMove(Shift, X, Y);
end;

procedure TAutoCustomLookupList.MouseUp(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
begin
  if FTracking then
  begin
    StopTracking;
    SelectItemAt(X, Y);
  end;
  inherited MouseUp(Button, Shift, X, Y);
end;

procedure TAutoCustomLookupList.Paint;
var
  I, II,  J, W, X, TextWidth, TextHeight, LastFieldIndex: Integer;
  S: string;
  R: TRect;
  Selected: Boolean;
  Field: TField;
begin
  FrealRowCount := FRowCount - Items.Count;
  if FCaption then
    Dec(FrealRowCount);
  if FListLink.BufferCount <> FRealRowCount then
  begin
    FListLink.BufferCount := FRealRowCount;
    ListLinkDataChanged;
  end;
  Canvas.Font := Font;
  TextWidth := Canvas.TextWidth('0');
  TextHeight := Canvas.TextHeight('0');
  LastFieldIndex := FListFields.Count - 1;
  if ColorToRGB(Color) <> ColorToRGB(clBtnFace) then
    Canvas.Pen.Color := clBtnFace
  else Canvas.Pen.Color := clBtnShadow;

  II := 0;
  if(FCaption) then begin
    Inc(II);
    Canvas.Brush.Color := clBtnFace;

    R.Top := 1;
    R.Bottom := TextHeight - 1;
    R.Right := 1;
    for J := 0 to LastFieldIndex do begin
       Field := FListFields[J];
        if J < LastFieldIndex then
          W := Field.DisplayWidth * TextWidth + 4
        else W := ClientWidth - R.Right;
        S := Field.DisplayLabel;
        X := (W - Canvas.TextWidth(S)) div 2;
        R.Left := R.Right + 2*J;
        R.Right := R.Right + W;
        //    ExtTextOut(ACanvas.Handle, Left, ARect.Top + DY, ETO_OPAQUE or
        //      ETO_CLIPPED, @ARect, PChar(Text), Length(Text), nil);
        Canvas.TextRect(R, R.Left + X, R.Top, S);
        InflateRect(R, 1, 1);
        DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
        DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_TOPLEFT);
        InflateRect(R, -1, -1);
    end;
  end;

  for I := II to FRowCount - 1 do
  begin
    Canvas.Font.Color := Font.Color;
    if(I >= FItems.Count) then
      Canvas.Brush.Color := Color
    else Canvas.Brush.Color := FItemsColor;
    Selected := not FKeySelected and (I = II);
    R.Top := I * TextHeight;
    R.Bottom := R.Top + TextHeight;

    if I  < FRecordCount + FItems.Count then
    begin
      if I >= FItems.Count then begin
        FListLink.ActiveRecord := I - FItems.Count;
        if not VarIsNull(FKeyValue) and VarEquals(FKeyField.Value, FKeyValue) then begin
          Canvas.Font.Color := clHighlightText;
          Canvas.Brush.Color := clHighlight;
          Selected := True;
        end;
      end
      else if IsValueItems = I then begin
          Canvas.Font.Color := clHighlightText;
          Canvas.Brush.Color := clHighlight;
          Selected := True;
        end;
      R.Right := 0;
      if I >= FItems.Count then
        for J := 0 to LastFieldIndex do
        begin
          Field := FListFields[J];
          if J < LastFieldIndex then
            W := Field.DisplayWidth * TextWidth + 4
          else W := ClientWidth - R.Right;

          S := Field.DisplayText;
          X := 2;
          case Field.Alignment of
            taRightJustify: X := W - Canvas.TextWidth(S) - 3;
            taCenter: X := (W - Canvas.TextWidth(S)) div 2;
          end;
          R.Left := R.Right;
          R.Right := R.Right + W;
          Canvas.TextRect(R, R.Left + X, R.Top, S);
          if J < LastFieldIndex then
          begin
            Canvas.MoveTo(R.Right, R.Top);
            Canvas.LineTo(R.Right, R.Bottom);
            Inc(R.Right);
            if R.Right >= ClientWidth then Break;
          end;
      end
      else begin
        W := ClientWidth - R.Right;
        S := GetItemsLabel(I);
        X := 2;
        case FItemsAlignment of
          taRightJustify: X := W - Canvas.TextWidth(S) - 3;
          taCenter: X := (W - Canvas.TextWidth(S)) div 2;
        end;
        R.Left := R.Right;
        R.Right := R.Right + W;
        Canvas.TextRect(R, R.Left + X, R.Top, S);
      end;  
    end;
    R.Left := 0;
    R.Right := ClientWidth;
    if I - FItems.Count >= FRecordCount then Canvas.FillRect(R);
    if Selected and FFocused  then Canvas.DrawFocusRect(R);
  end;
  if FRecordCount <> 0 then FListLink.ActiveRecord := FRecordIndex;
end;

procedure TAutoCustomLookupList.SelectCurrent;
begin
  FLockPosition := True;
  if(IsValueItems > -1) then begin
    SelectKeyValue(GetItemsValue(IsValueItems));
    exit;
  end;
  try
    SelectKeyValue(FKeyField.Value);
  finally
    FLockPosition := False;
  end;
end;

procedure TAutoCustomLookupList.SelectItemAt(X, Y: Integer);
var
  Delta: Integer;
begin
  if Y < 0 then Y := 0;
  if Y >= ClientHeight then Y := ClientHeight - 1;
  Delta := Y div GetTextHeight;
  if(Delta < Items.Count) then
    IsValueItems := Delta
  else  begin
    Delta :=  Delta - FRecordIndex - Items.Count;
    IsValueItems := -1;
    FListLink.DataSet.MoveBy(Delta);
  end;
  SelectCurrent;
end;

procedure TAutoCustomLookupList.SetBorderStyle(Value: TBorderStyle);
begin
  if FBorderStyle <> Value then
  begin
    FBorderStyle := Value;
    RecreateWnd;
    RowCount := RowCount;
  end;
end;

procedure TAutoCustomLookupList.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
  BorderSize, TextHeight, Rows: Integer;
begin
  BorderSize := GetBorderSize;
  TextHeight := GetTextHeight;
  Rows := (AHeight - BorderSize) div TextHeight;
  if Rows < 1 then Rows := 1;
  FRowCount := Rows;
  inherited SetBounds(ALeft, ATop, AWidth, Rows * TextHeight + BorderSize);
end;

procedure TAutoCustomLookupList.SetRowCount(Value: Integer);
begin

⌨️ 快捷键说明

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