📄 salphalistbox.pas
字号:
unit sAlphaListBox;
{$I sDefs.inc}
{.$DEFINE LOGGED}
interface
uses StdCtrls, controls, classes, forms, graphics, messages, windows, sysutils, consts, sCommonData,
sConst, sDefaults, commctrl, acSBUtils{$IFNDEF DELPHI5}, types{$ENDIF};
type
{$IFNDEF NOTFORHELP}
{$IFNDEF DELPHI6UP}
TListBoxStyle = (lbStandard, lbOwnerDrawFixed, lbOwnerDrawVariable, lbVirtual, lbVirtualOwnerDraw);
TLBGetDataEvent = procedure(Control: TWinControl; Index: Integer; var Data: string) of object;
TLBGetDataObjectEvent = procedure(Control: TWinControl; Index: Integer; var DataObject: TObject) of object;
TLBFindDataEvent = function(Control: TWinControl; FindString: string): Integer of object;
{$ENDIF}
{$ENDIF} // NOTFORHELP
TsAlphaListBox = class(TWinControl)
{$IFNDEF NOTFORHELP}
private
FCount: Integer;
FOldCount: Integer;
FFilter: String;
FLastTime: DWord;
FItems: TStrings;
FBorderStyle: TBorderStyle;
FCanvas: TCanvas;
FColumns: Integer;
FItemHeight: Integer;
FStyle: TListBoxStyle;
FIntegralHeight: Boolean;
FMultiSelect: Boolean;
FSorted: Boolean;
FExtendedSelect: Boolean;
FTabWidth: Integer;
FSaveItems: TStringList;
FSaveTopIndex: Integer;
FSaveItemIndex: Integer;
FOnDrawItem: TDrawItemEvent;
FOnMeasureItem: TMeasureItemEvent;
FCommonData: TsCommonData;
FOnVScroll: TNotifyEvent;
FDisabledKind: TsDisabledKind;
FBoundLabel: TsBoundLabel;
FOnDataFind: TLBFindDataEvent;
FOnData: TLBGetDataEvent;
FOnDataObject: TLBGetDataObjectEvent;
FAutoComplete: Boolean;
FAutoHideScroll: boolean;
FAutoCompleteDelay: Word;
function GetItemHeight: Integer;
function GetItemIndex: Integer;
function GetSelCount: Integer;
function GetSelected(Index: Integer): Boolean;
function GetTopIndex: Integer;
procedure SetBorderStyle(Value: TBorderStyle);
procedure SetColumnWidth;
procedure SetColumns(Value: Integer);
procedure SetExtendedSelect(Value: Boolean);
procedure SetIntegralHeight(Value: Boolean);
procedure SetItemHeight(Value: Integer);
procedure SetItems(Value: TStrings);
procedure SetItemIndex(Value: Integer);
procedure SetMultiSelect(Value: Boolean);
procedure SetSelected(Index: Integer; Value: Boolean);
procedure SetSorted(Value: Boolean);
procedure SetStyle(Value: TListBoxStyle);
procedure SetTabWidth(Value: Integer);
procedure SetTopIndex(Value: Integer);
procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure WMNCCalcSize (var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
procedure WMEraseBkgnd (var Message: TWMPaint); message WM_ERASEBKGND;
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
procedure WMLButtonUp(var Message: TMessage); message WM_LBUTTONUP;
procedure SetDisabledKind(const Value: TsDisabledKind);
procedure WMPrint (var Message: TWMPaint); message WM_PRINT;
procedure LBGetText(var Message: TMessage); message LB_GETTEXT;
procedure LBGetTextLen(var Message: TMessage); message LB_GETTEXTLEN;
function GetCount: Integer;
procedure SetCount(const Value: Integer);
procedure SetAutoHideScroll(const Value: boolean);
function GetScrollWidth: Integer;
procedure SetScrollWidth(const Value: Integer);
protected
FMoving: Boolean;
FTopIndex : integer;
ListSW : TacScrollWnd;
function DoGetData(const Index: Integer): String;
function DoGetDataObject(const Index: Integer): TObject;
function DoFindData(const Data: String): Integer;
procedure KeyPress(var Key: Char); override;
procedure PrepareCache; virtual;
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateWnd; override;
procedure DestroyWnd; override;
procedure DragCanceled; override;
procedure MeasureItem(Index: Integer; var Height: Integer); virtual;
function InternalGetItemData(Index: Integer): Longint; dynamic;
procedure InternalSetItemData(Index: Integer; AData: Longint); dynamic;
function GetItemData(Index: Integer): LongInt; dynamic;
function VisibleRows : integer;
procedure SetItemData(Index: Integer; AData: LongInt); dynamic;
procedure ResetContent; dynamic;
procedure DeleteString(Index: Integer); dynamic;
property ExtendedSelect: Boolean read FExtendedSelect write SetExtendedSelect default True;
procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); virtual;
procedure WndProc(var Message: TMessage); override;
public
procedure AfterConstruction; override;
procedure DeleteSelected;
procedure ClearSelection;
procedure Loaded; override;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear;
function ItemAtPos(Pos: TPoint; Existing: Boolean): Integer;
function ItemRect(Index: Integer): TRect;
procedure RepaintItem(Index : Integer);
property Canvas: TCanvas read FCanvas;
property ItemIndex: Integer read GetItemIndex write SetItemIndex;
property SelCount: Integer read GetSelCount;
property Selected[Index: Integer]: Boolean read GetSelected write SetSelected;
property TopIndex: Integer read GetTopIndex write SetTopIndex;
property MultiSelect: Boolean read FMultiSelect write SetMultiSelect default False;
property ScrollWidth: Integer read GetScrollWidth write SetScrollWidth default 0;
{$ENDIF} // NOTFORHELP
property Count: Integer read GetCount write SetCount;
published
property AutoCompleteDelay : Word read FAutoCompleteDelay write FAutoCompleteDelay;
property AutoComplete: Boolean read FAutoComplete write FAutoComplete default True;
property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
property BoundLabel : TsBoundLabel read FBoundLabel write FBoundLabel;
property Columns: Integer read FColumns write SetColumns default 0;
property SkinData : TsCommonData read FCommonData write FCommonData;
property DisabledKind : TsDisabledKind read FDisabledKind write SetDisabledKind default DefDisabledKind;
property IntegralHeight: Boolean read FIntegralHeight write SetIntegralHeight default False;
property ItemHeight: Integer read GetItemHeight write SetItemHeight;
property Items: TStrings read FItems write SetItems;
property Sorted: Boolean read FSorted write SetSorted default False;
property Style: TListBoxStyle read FStyle write SetStyle default lbStandard;
property TabWidth: Integer read FTabWidth write SetTabWidth default 0;
{$IFNDEF NOTFORHELP}
property AutoHideScroll : boolean read FAutoHideScroll write SetAutoHideScroll default True;
property OnData: TLBGetDataEvent read FOnData write FOnData;
property OnDataObject: TLBGetDataObjectEvent read FOnDataObject write FOnDataObject;
property OnDataFind: TLBFindDataEvent read FOnDataFind write FOnDataFind;
property OnDrawItem: TDrawItemEvent read FOnDrawItem write FOnDrawItem;
property OnMeasureItem: TMeasureItemEvent read FOnMeasureItem write FOnMeasureItem;
property OnVScroll : TNotifyEvent read FOnVScroll write FOnVScroll;
property Align;
property Anchors;
property BiDiMode;
property Color;
property Constraints;
property Ctl3D;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Font;
property ImeMode;
property ImeName;
property ParentBiDiMode;
property ParentColor default False;
property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property TabOrder;
property TabStop default True;
property Visible;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDock;
property OnStartDrag;
{$ENDIF} // NOTFORHELP
end;
TsListBox = class(TsAlphaListBox)
published
{$IFNDEF NOTFORHELP}
property MultiSelect;
property ExtendedSelect;
{$ENDIF} // NOTFORHELP
end;
{$IFNDEF NOTFORHELP}
var
mPressed : boolean = False;
ScrollsUpdating : boolean = False;
{$ENDIF}
implementation
uses sVCLUtils, sGraphUtils, math, sMessages, sStyleSimply, sSkinProps, sAlphaGraph, sStrings
{$IFDEF DELPHI6UP}, RTLConsts{$ENDIF} {$IFDEF LOGGED}, sDebugMsgs{$ENDIF};
const
BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
type
TListBoxStrings = class(TStrings)
private
ListBox: TsAlphaListBox;
protected
procedure Put(Index: Integer; const S: string); override;
function Get(Index: Integer): string; override;
function GetCount: Integer; override;
function GetObject(Index: Integer): TObject; override;
procedure PutObject(Index: Integer; AObject: TObject); override;
procedure SetUpdateState(Updating: Boolean); override;
procedure Update;
public
function Add(const S: string): Integer; override;
procedure Clear; override;
procedure Delete(Index: Integer); override;
procedure Exchange(Index1, Index2: Integer); override;
function IndexOf(const S: string): Integer; override;
procedure Insert(Index: Integer; const S: string); override;
procedure Move(CurIndex, NewIndex: Integer); override;
end;
{ TsAlphaListBox }
procedure TsAlphaListBox.AfterConstruction;
begin
inherited AfterConstruction;
SkinData.Loaded;
end;
procedure TsAlphaListBox.Clear;
begin
FItems.Clear;
end;
procedure TsAlphaListBox.ClearSelection;
var
I: Integer;
begin
if MultiSelect then for I := 0 to Items.Count - 1 do Selected[I] := False else ItemIndex := -1;
end;
procedure TsAlphaListBox.CMCtl3DChanged(var Message: TMessage);
begin
if NewStyleControls and (FBorderStyle = bsSingle) and not (csLoading in ComponentState) then RecreateWnd;
inherited;
end;
procedure TsAlphaListBox.CMEnabledChanged(var Message: TMessage);
begin
FCommonData.BGChanged := True;
Perform(WM_PAINT, 0, 0);
Perform(WM_NCPAINT, 0, 0);
inherited;
end;
procedure TsAlphaListBox.CMFontChanged(var Message: TMessage);
var
R : TRect;
begin
inherited;
if not (csLoading in ComponentState) then begin
SkinData.BGChanged := True;
Repaint;
if HandleAllocated and (FStyle = lbStandard) then begin
Perform(LB_GETITEMRECT, 0, Longint(@R));
ItemHeight := R.Bottom - R.Top;
end;
end;
end;
procedure TsAlphaListBox.CNCommand(var Message: TWMCommand);
begin
case Message.NotifyCode of
LBN_SELCHANGE: begin
inherited Changed;
Click;
end;
LBN_DBLCLK: DblClick;
end;
end;
procedure TsAlphaListBox.CNDrawItem(var Message: TWMDrawItem);
var
State: TOwnerDrawState;
begin
FCommonData.Updating := FCommonData.Updating;
if FCommonData.Updating and SkinData.Skinned then Exit;
if Items.Count < 1 then Exit;
with Message.DrawItemStruct^ do begin
State := TOwnerDrawState(LongRec(itemState).Lo);
FCanvas.Handle := hDC;
FCanvas.Font := Font;
FCanvas.Brush := Brush;
if not ((Style in [lbOwnerDrawFixed, lbOwnerDrawVariable, lbVirtualOwnerDraw]) and Assigned(OnDrawItem)) and (Integer(itemID) >= 0) and ((odSelected in State) or ((integer(itemID) = ItemIndex) and not Focused)) then begin
FCanvas.Brush.Color := clHighlight;
FCanvas.Font.Color := clHighlightText
end
else if not FCommonData.CustomFont then begin
if not Enabled then FCanvas.Font.Color := AverageColor(Font.Color, Color) else FCanvas.Font.Color := Font.Color;
end;
DrawItem(Message.DrawItemStruct^.itemID, Message.DrawItemStruct^.rcItem, State);
FCanvas.Handle := 0;
end;
end;
procedure TsAlphaListBox.CNMeasureItem(var Message: TWMMeasureItem);
begin
with Message.MeasureItemStruct^ do begin
itemHeight := FItemHeight;
if FStyle = lbOwnerDrawVariable then MeasureItem(itemID, Integer(itemHeight));
end;
end;
constructor TsAlphaListBox.Create(AOwner: TComponent);
const
ListBoxStyle = [csSetCaption, csDoubleClicks];
begin
inherited Create(AOwner);
if NewStyleControls then ControlStyle := ListBoxStyle else ControlStyle := ListBoxStyle + [csFramed, csOpaque];
Width := 121;
Height := 97;
TabStop := True;
ParentColor := False;
FItems := TListBoxStrings.Create;
TListBoxStrings(FItems).ListBox := Self;
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
FItemHeight := 16;
FAutoComplete := True;
FBorderStyle := bsSingle;
FExtendedSelect := True;
FAutoHideScroll := True;
FCommonData := TsCommonData.Create(Self, True);
FCommonData.COC := COC_TsAlphaListBox;
if FCommonData.SkinSection = '' then FCommonData.SkinSection := s_Edit;
FTopIndex := 0;
FDisabledKind := DefDisabledKind;
FBoundLabel := TsBoundLabel.Create(Self, FCommonData);
FOldCount := -1;
FAutoCompleteDelay := 500;
DoubleBuffered := False;
end;
procedure TsAlphaListBox.CreateParams(var Params: TCreateParams);
type
PSelects = ^TSelects;
TSelects = array[Boolean] of DWORD;
const
Styles: array[TListBoxStyle] of DWORD = (0, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWFIXED);
Sorteds: array[Boolean] of DWORD = (0, LBS_SORT);
MultiSelects: array[Boolean] of DWORD = (0, LBS_MULTIPLESEL);
ExtendSelects: array[Boolean] of DWORD = (0, LBS_EXTENDEDSEL);
IntegralHeights: array[Boolean] of DWORD = (LBS_NOINTEGRALHEIGHT, 0);
MultiColumns: array[Boolean] of DWORD = (0, LBS_MULTICOLUMN);
TabStops: array[Boolean] of DWORD = (0, LBS_USETABSTOPS);
CSHREDRAW: array[Boolean] of DWORD = (CS_HREDRAW, 0);
Data: array[Boolean] of DWORD = (LBS_HASSTRINGS, LBS_NODATA);
var
Selects: PSelects;
begin
inherited CreateParams(Params);
CreateSubClass(Params, 'LISTBOX');
with Params do begin
Selects := @MultiSelects;
if FExtendedSelect then Selects := @ExtendSelects;
Style := Style or ({WS_HSCROLL or }WS_VSCROLL or Data[Self.Style in [lbVirtual, lbVirtualOwnerDraw]] or
LBS_NOTIFY) or Styles[FStyle] or Sorteds[FSorted] or Selects^[FMultiSelect] or IntegralHeights[FIntegralHeight] or
MultiColumns[FColumns <> 0] or BorderStyles[FBorderStyle] or TabStops[FTabWidth <> 0];
if FColumns <> 0 then Style := Style or WS_HSCROLL;
if not FAutoHideScroll then Style := Style or LBS_DISABLENOSCROLL;
if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then begin
Style := Style and not WS_BORDER;
ExStyle := ExStyle or WS_EX_CLIENTEDGE;
end;
WindowClass.style := WindowClass.style and not (CSHREDRAW[UseRightToLeftAlignment] or CS_VREDRAW);
end;
end;
procedure TsAlphaListBox.CreateWnd;
var
W, H: Integer;
begin
W := Width;
H := Height;
inherited CreateWnd;
SetWindowPos(Handle, 0, Left, Top, W, H, SWP_NOZORDER or SWP_NOACTIVATE);
if FTabWidth <> 0 then SendMessage(Handle, LB_SETTABSTOPS, 1, Longint(@FTabWidth));
SetColumnWidth;
if (FOldCount <> -1) or Assigned(FSaveItems) then begin
if (Style in [lbVirtual, lbVirtualOwnerDraw]) then
Count := FOldCount;
if FSaveItems <> nil then begin
FItems.Assign(FSaveItems);
FreeAndNil(FSaveItems);
end;
SetTopIndex(FSaveTopIndex);
SetItemIndex(FSaveItemIndex);
FOldCount := -1;
end;
end;
procedure TsAlphaListBox.DeleteSelected;
var
I: Integer;
begin
if MultiSelect then begin
for I := Items.Count - 1 downto 0 do if Selected[I] then Items.Delete(I);
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -