📄 rxctrls.pas
字号:
OffsetRect(Result, 0, Result.Bottom - Result.Top);
end
else FillChar(Result, SizeOf(Result), 0);
end;
procedure TRxCustomListBox.CreateParams(var Params: TCreateParams);
type
PSelects = ^TSelects;
TSelects = array[Boolean] of Longword;
const
BorderStyles: array[TBorderStyle] of Longword = (0, WS_BORDER);
Styles: array[TListBoxStyle] of Longword =
(0, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE);
Sorteds: array[Boolean] of Longword = (0, LBS_SORT);
MultiSelects: array[Boolean] of Longword = (0, LBS_MULTIPLESEL);
ExtendSelects: array[Boolean] of Longword = (0, LBS_EXTENDEDSEL);
IntegralHeights: array[Boolean] of Longword = (LBS_NOINTEGRALHEIGHT, 0);
MultiColumns: array[Boolean] of Longword = (0, LBS_MULTICOLUMN);
TabStops: array[Boolean] of Longword = (0, LBS_USETABSTOPS);
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 LBS_HASSTRINGS 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 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 (CS_HREDRAW or CS_VREDRAW);
end;
end;
procedure TRxCustomListBox.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 FSaveItems <> nil then begin
FItems.Assign(FSaveItems);
SetTopIndex(FSaveTopIndex);
SetItemIndex(FSaveItemIndex);
FSaveItems.Free;
FSaveItems := nil;
end;
end;
procedure TRxCustomListBox.DestroyWnd;
begin
if FItems.Count > 0 then begin
FSaveItems := TStringList.Create;
FSaveItems.Assign(FItems);
FSaveTopIndex := GetTopIndex;
FSaveItemIndex := GetItemIndex;
end;
inherited DestroyWnd;
end;
procedure TRxCustomListBox.WndProc(var Message: TMessage);
begin
if AutoScroll then begin
case Message.Msg of
LB_ADDSTRING, LB_INSERTSTRING:
begin
inherited WndProc(Message);
FMaxItemWidth := Max(FMaxItemWidth, GetItemWidth(Message.Result));
SetHorizontalExtent;
Exit;
end;
LB_DELETESTRING:
begin
if GetItemWidth(Message.wParam) >= FMaxItemWidth then begin
Perform(WM_HSCROLL, SB_TOP, 0);
inherited WndProc(Message);
ResetHorizontalExtent;
end
else inherited WndProc(Message);
Exit;
end;
LB_RESETCONTENT:
begin
FMaxItemWidth := 0;
SetHorizontalExtent;
Perform(WM_HSCROLL, SB_TOP, 0);
inherited WndProc(Message);
Exit;
end;
WM_SETFONT:
begin
inherited WndProc(Message);
Canvas.Font.Assign(Self.Font);
ResetHorizontalExtent;
Exit;
end;
end;
end;
{for auto drag mode, let listbox handle itself, instead of TControl}
if not (csDesigning in ComponentState) and ((Message.Msg = WM_LBUTTONDOWN) or
(Message.Msg = WM_LBUTTONDBLCLK)) and not Dragging then
begin
if DragMode = dmAutomatic then begin
if IsControlMouseMsg(TWMMouse(Message)) then Exit;
ControlState := ControlState + [csLButtonDown];
Dispatch(Message); {overrides TControl's BeginDrag}
Exit;
end;
end;
inherited WndProc(Message);
end;
procedure TRxCustomListBox.WMLButtonDown(var Message: TWMLButtonDown);
var
ItemNo: Integer;
ShiftState: TShiftState;
begin
ShiftState := KeysToShiftState(Message.Keys);
if (DragMode = dmAutomatic) and FMultiSelect then begin
if not (ssShift in ShiftState) or (ssCtrl in ShiftState) then begin
ItemNo := ItemAtPos(SmallPointToPoint(Message.Pos), True);
if (ItemNo >= 0) and (Selected[ItemNo]) then begin
BeginDrag(False);
Exit;
end;
end;
end;
inherited;
if (DragMode = dmAutomatic) and not (FMultiSelect and
((ssCtrl in ShiftState) or (ssShift in ShiftState))) then
BeginDrag(False);
end;
procedure TRxCustomListBox.WMNCHitTest(var Msg: TWMNCHitTest);
begin
if csDesigning in ComponentState then DefaultHandler(Msg)
else inherited;
end;
procedure TRxCustomListBox.CNCommand(var Message: TWMCommand);
begin
case Message.NotifyCode of
LBN_SELCHANGE:
begin
{$IFDEF RX_D3}
inherited Changed;
{$ENDIF}
Click;
end;
LBN_DBLCLK: DblClick;
end;
end;
procedure TRxCustomListBox.WMPaint(var Message: TWMPaint);
procedure PaintListBox;
var
DrawItemMsg: TWMDrawItem;
MeasureItemMsg: TWMMeasureItem;
DrawItemStruct: TDrawItemStruct;
MeasureItemStruct: TMeasureItemStruct;
R: TRect;
Y, I, H, W: Integer;
begin
{ Initialize drawing records }
DrawItemMsg.Msg := CN_DRAWITEM;
DrawItemMsg.DrawItemStruct := @DrawItemStruct;
DrawItemMsg.Ctl := Handle;
DrawItemStruct.CtlType := ODT_LISTBOX;
DrawItemStruct.itemAction := ODA_DRAWENTIRE;
DrawItemStruct.itemState := 0;
DrawItemStruct.hDC := Message.DC;
DrawItemStruct.CtlID := Handle;
DrawItemStruct.hwndItem := Handle;
{ Intialize measure records }
MeasureItemMsg.Msg := CN_MEASUREITEM;
MeasureItemMsg.IDCtl := Handle;
MeasureItemMsg.MeasureItemStruct := @MeasureItemStruct;
MeasureItemStruct.CtlType := ODT_LISTBOX;
MeasureItemStruct.CtlID := Handle;
{ Draw the listbox }
Y := 0;
I := TopIndex;
GetClipBox(Message.DC, R);
H := Height;
W := Width;
while Y < H do begin
MeasureItemStruct.itemID := I;
if I < Items.Count then
MeasureItemStruct.itemData := Longint(Pointer(Items.Objects[I]));
MeasureItemStruct.itemWidth := W;
MeasureItemStruct.itemHeight := FItemHeight;
DrawItemStruct.itemData := MeasureItemStruct.itemData;
DrawItemStruct.itemID := I;
Dispatch(MeasureItemMsg);
DrawItemStruct.rcItem := Rect(0, Y, MeasureItemStruct.itemWidth,
Y + Integer(MeasureItemStruct.itemHeight));
Dispatch(DrawItemMsg);
Inc(Y, MeasureItemStruct.itemHeight);
Inc(I);
if I >= Items.Count then break;
end;
end;
begin
if Message.DC <> 0 then PaintListBox
else inherited;
end;
procedure TRxCustomListBox.WMSize(var Message: TWMSize);
begin
inherited;
SetColumnWidth;
end;
procedure TRxCustomListBox.DragCanceled;
var
M: TWMMouse;
MousePos: TPoint;
begin
with M do begin
Msg := WM_LBUTTONDOWN;
GetCursorPos(MousePos);
Pos := PointToSmallPoint(ScreenToClient(MousePos));
Keys := 0;
Result := 0;
end;
DefaultHandler(M);
M.Msg := WM_LBUTTONUP;
DefaultHandler(M);
end;
procedure TRxCustomListBox.DefaultDrawText(X, Y: Integer; const S: string);
var
ATabWidth: Longint;
begin
{$IFDEF RX_D4}
TControlCanvas(FCanvas).UpdateTextFlags;
{$ENDIF}
if FTabWidth = 0 then FCanvas.TextOut(X, Y, S)
else begin
ATabWidth := Round((TabWidth * Canvas.TextWidth('0')) * 0.25);
TabbedTextOut(FCanvas.Handle, X, Y, @S[1], Length(S), 1, ATabWidth, X);
end;
end;
procedure TRxCustomListBox.DrawItem(Index: Integer; Rect: TRect;
State: TOwnerDrawState);
begin
if Assigned(FOnDrawItem) then FOnDrawItem(Self, Index, Rect, State)
else begin
FCanvas.FillRect(Rect);
if Index < Items.Count then begin
{$IFDEF RX_D4}
if not UseRightToLeftAlignment then Inc(Rect.Left, 2)
else Dec(Rect.Right, 2);
{$ELSE}
Inc(Rect.Left, 2);
{$ENDIF}
DefaultDrawText(Rect.Left, Max(Rect.Top, (Rect.Bottom +
Rect.Top - Canvas.TextHeight('Wy')) div 2), Items[Index]);
end;
end;
end;
procedure TRxCustomListBox.MeasureItem(Index: Integer; var Height: Integer);
begin
if Assigned(FOnMeasureItem) then FOnMeasureItem(Self, Index, Height)
end;
procedure TRxCustomListBox.CNDrawItem(var Message: TWMDrawItem);
var
State: TOwnerDrawState;
begin
with Message.DrawItemStruct^ do begin
{$IFDEF RX_D5}
State := TOwnerDrawState(LongRec(itemState).Lo);
{$ELSE}
State := TOwnerDrawState(WordRec(LongRec(itemState).Lo).Lo);
{$ENDIF}
FCanvas.Handle := hDC;
FCanvas.Font := Font;
FCanvas.Brush := Brush;
if (Integer(itemID) >= 0) and (odSelected in State) then begin
with FCanvas do
if not (csDesigning in ComponentState) and FGraySelection and
not Focused then
begin
Brush.Color := clBtnFace;
if ColorToRGB(Font.Color) = ColorToRGB(clBtnFace) then
Font.Color := clBtnText;
end
else begin
Brush.Color := clHighlight;
Font.Color := clHighlightText
end;
end;
if Integer(itemID) >= 0 then DrawItem(itemID, rcItem, State)
else FCanvas.FillRect(rcItem);
if odFocused in State then DrawFocusRect(hDC, rcItem);
FCanvas.Handle := 0;
end;
end;
procedure TRxCustomListBox.CNMeasureItem(var Message: TWMMeasureItem);
begin
with Message.MeasureItemStruct^ do begin
itemHeight := FItemHeight;
if FStyle = lbOwnerDrawVariable then
MeasureItem(itemID, Integer(itemHeight));
end;
end;
procedure TRxCustomListBox.WMKillFocus(var Msg: TWMKillFocus);
begin
inherited;
if FGraySelection and MultiSelect and (SelCount > 1) then Invalidate;
end;
procedure TRxCustomListBox.WMSetFocus(var Msg: TWMSetFocus);
begin
inherited;
if FGraySelection and MultiSelect and (SelCount > 1) then Invalidate;
end;
procedure TRxCustomListBox.CMCtl3DChanged(var Message: TMessage);
begin
if NewStyleControls and (FBorderStyle = bsSingle) then RecreateWnd;
inherited;
end;
{ TCheckListBoxItem }
type
TCheckListBoxItem = class
private
FData: LongInt;
FState: TCheckBoxState;
FEnabled: Boolean;
function GetChecked: Boolean;
public
constructor Create;
property Checked: Boolean read GetChecked;
property Enabled: Boolean read FEnabled write FEnabled;
property State: TCheckBoxState read FState write FState;
end;
constructor TCheckListBoxItem.Create;
begin
inherited Create;
FState := clbDefaultState;
FEnabled := clbDefaultEnabled;
end;
function TCheckListBoxItem.GetChecked: Boolean;
begin
Result := FState = cbChecked;
end;
{ TCheckListBoxStrings }
type
TCheckListBoxStrings = class(TRxListBoxStrings)
public
procedure Exchange(Index1, Index2: Integer); override;
procedure Move(CurIndex, NewIndex: Integer); override;
end;
procedure TCheckListBoxStrings.Exchange(Index1, Index2: Integer);
var
TempEnabled1, TempEnabled2: Boolean;
TempState1, TempState2: TCheckBoxState;
TempHint1, TempHint2 :string;
begin
with TRxCheckListBox(ListBox) do begin
TempState1 := State[Index1];
TempEnabled1 := EnabledItem[Index1];
TempState2 := State[Index2];
TempEnabled2 := Ena
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -