📄 tflatlistboxunit.pas
字号:
canvas.Brush.Color := Color;
canvas.FillRect(Rect(ClientRect.Left, ClientRect.Top, ClientRect.Right, ClientRect.Top + 11));
canvas.FillRect(Rect(ClientRect.Left, ClientRect.Bottom - 11, ClientRect.Right, ClientRect.Bottom));
// Draw the ScrollBar border
canvas.Brush.Color := FBorderColor;
canvas.FrameRect(Rect(ClientRect.Left, ClientRect.Top, ClientRect.Right, ClientRect.Top + 11));
canvas.FrameRect(Rect(ClientRect.Left, ClientRect.Bottom - 11, ClientRect.Right, ClientRect.Bottom));
// Draw the up arrow
x := (ClientRect.Right - ClientRect.Left) div 2 - 6;
y := ClientRect.Top + 4;
if (firstItem <> 0) and Enabled then
begin
canvas.Brush.Color := FArrowColor;
canvas.Pen.Color := FArrowColor;
canvas.Polygon([Point(x + 4, y + 2), Point(x + 8, y + 2), Point(x + 6, y)]);
end
else
begin
canvas.Brush.Color := clWhite;
canvas.Pen.Color := clWhite;
Inc(x); Inc(y);
canvas.Polygon([Point(x + 4, y + 2), Point(x + 8, y + 2), Point(x + 6, y)]);
Dec(x); Dec(y);
canvas.Brush.Color := clGray;
canvas.Pen.Color := clGray;
canvas.Polygon([Point(x + 4, y + 2), Point(x + 8, y + 2), Point(x + 6, y)]);
end;
// Draw the down arrow
y := ClientRect.Bottom - 7;
if (firstItem + maxItems + 1 <= FItems.Count) and Enabled then
begin
canvas.Brush.Color := FArrowColor;
canvas.Pen.Color := FArrowColor;
canvas.Polygon([Point(X + 4, Y), Point(X + 8, Y), Point(X + 6, Y + 2)]);
end
else
begin
canvas.Brush.Color := clWhite;
canvas.Pen.Color := clWhite;
Inc(x); Inc(y);
canvas.Polygon([Point(X + 4, Y), Point(X + 8, Y), Point(X + 6, Y + 2)]);
Dec(x); Dec(y);
canvas.Brush.Color := clGray;
canvas.Pen.Color := clGray;
canvas.Polygon([Point(X + 4, Y), Point(X + 8, Y), Point(X + 6, Y + 2)]);
end;
end;
procedure TFlatListBox.Paint;
var
memoryBitmap: TBitmap;
counterRect, counterItem: Integer;
itemRect: ^TRect;
Format: UINT;
begin
{$IFDEF DFS_COMPILER_4_UP}
if BidiMode = bdRightToLeft then
Format := DT_RIGHT or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX
else
Format := DT_LEFT or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX;
{$ELSE}
Format := DT_LEFT or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX;
{$ENDIF}
// create memory-bitmap to draw flicker-free
memoryBitmap := TBitmap.Create;
try
memoryBitmap.Height := ClientRect.Bottom;
memoryBitmap.Width := ClientRect.Right;
memoryBitmap.Canvas.Font.Assign(Self.Font);
// Clear Background
case FTransparent of
tmAlways:
DrawParentImage(Self, memoryBitmap.Canvas);
tmNone:
begin
memoryBitmap.canvas.Brush.Color := FItemsRectColor;
memoryBitmap.canvas.FillRect(ClientRect);
end;
tmNotFocused:
if Focused then
begin
memoryBitmap.canvas.Brush.Color := FItemsRectColor;
memoryBitmap.canvas.FillRect(ClientRect);
end
else
DrawParentImage(Self, memoryBitmap.Canvas);
end;
// Draw Border
memoryBitmap.canvas.Brush.Color := FBorderColor;
memoryBitmap.canvas.FrameRect(ClientRect);
// Draw ScrollBars
if ScrollBars then
DrawScrollBar(memoryBitmap.canvas);
// Initialize the counter for the Items
counterItem := firstItem;
// Draw Items
for counterRect := 0 to maxItems - 1 do
begin
itemRect := FItemsRect.Items[counterRect];
if (counterItem <= FItems.Count - 1) then
begin
// Item is selected
if counterItem in FSelected then
begin
// Fill ItemRect
memoryBitmap.canvas.brush.color := FItemsSelectColor;
memoryBitmap.canvas.FillRect(itemRect^);
// Draw ItemBorder
memoryBitmap.canvas.brush.color := FBorderColor;
memoryBitmap.canvas.FrameRect(itemRect^);
end;
// Draw ItemText
memoryBitmap.canvas.brush.style := bsClear;
InflateRect(itemRect^, -3, 0);
if Enabled then
DrawText(memoryBitmap.canvas.Handle, PChar(FItems[counterItem]), Length(FItems[counterItem]), itemRect^, Format)
else
begin
OffsetRect(itemRect^, 1, 1);
memoryBitmap.canvas.Font.Color := clBtnHighlight;
DrawText(memoryBitmap.canvas.Handle, PChar(FItems[counterItem]), Length(FItems[counterItem]), itemRect^, Format);
OffsetRect(itemRect^, -1, -1);
memoryBitmap.canvas.Font.Color := clBtnShadow;
DrawText(memoryBitmap.canvas.Handle, PChar(FItems[counterItem]), Length(FItems[counterItem]), itemRect^, Format);
end;
InflateRect(itemRect^, 3, 0);
Inc(counterItem);
end;
end;
// Copy bitmap to screen
canvas.CopyRect(ClientRect, memoryBitmap.canvas, ClientRect);
finally
// delete the memory bitmap
memoryBitmap.free;
end;
end;
procedure TFlatListBox.MouseDown (Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
cursorPos: TPoint;
counterRect: Integer;
currentRect: ^TRect;
begin
GetCursorPos(cursorPos);
cursorPos := ScreenToClient(cursorPos);
if (FItems.Count > 0) and (Button = mbLeft) then
begin
for counterRect := 0 to FItemsRect.Count - 1 do
begin
currentRect := FItemsRect.Items[counterRect];
if PtInRect(currentRect^, cursorPos) then
begin
if MultiSelect then
begin
if (firstItem + counterRect) in FSelected then
Exclude(FSelected, firstItem + counterRect)
else
Include(FSelected, firstItem + counterRect);
FItemIndex := firstItem + counterRect;
end
else
begin
FSelected := FSelected - [0..High(Byte)];
Include(FSelected, firstItem + counterRect);
FItemIndex := firstItem + counterRect;
end;
SetFocus;
Invalidate;
Exit;
end;
end;
end;
if ScrollBars then
begin
if PtInRect(Rect(ClientRect.Left, ClientRect.Top, ClientRect.Right, ClientRect.Top + 11), cursorPos) then
begin
if (firstItem - 1) < 0 then
firstItem := 0
else
Dec(firstItem);
SetFocus;
Invalidate;
scrollType := up;
if ScrollTimer.Enabled then
ScrollTimer.Enabled := False;
ScrollTimer.OnTimer := ScrollTimerHandler;
ScrollTimer.Enabled := True;
end;
if PtInRect(Rect(ClientRect.Left, ClientRect.Bottom - 11, ClientRect.Right, ClientRect.Bottom), cursorPos) then
begin
if firstItem + maxItems + 1 <= FItems.Count then
Inc(firstItem);
SetFocus;
Invalidate;
scrollType := down;
if ScrollTimer.Enabled then
ScrollTimer.Enabled := False;
ScrollTimer.OnTimer := ScrollTimerHandler;
ScrollTimer.Enabled := True;
end;
end;
Inherited;
end;
procedure TFlatListBox.MouseUp (Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ScrollTimer.Enabled := False;
ScrollTimer.Interval := FTimerInterval;
inherited MouseUp(Button, Shift, X, Y);
end;
procedure TFlatListBox.ScrollTimerHandler (Sender: TObject);
begin
ScrollTimer.Interval := FScrollSpeed;
if scrollType = up then
if (firstItem - 1) < 0 then
begin
firstItem := 0;
ScrollTimer.Enabled := False;
end
else
Dec(firstItem)
else
if firstItem + maxItems + 1 <= FItems.Count then
Inc(firstItem)
else
ScrollTimer.Enabled := False;
Invalidate;
end;
procedure TFlatListBox.Loaded;
begin
inherited;
SetItemsRect;
end;
procedure TFlatListBox.WMSize (var Message: TWMSize);
begin
inherited;
// Calculate the maximum items to draw
if ScrollBars then
maxItems := (Height - 24) div (FItemsHeight + 2)
else
maxItems := (Height - 4) div (FItemsHeight + 2);
// Set the new Bounds
if ScrollBars then
SetBounds(Left, Top, Width, maxItems * (FItemsHeight + 2) + 24)
else
SetBounds(Left, Top, Width, maxItems * (FItemsHeight + 2) + 4);
// Recalculate the itemRects
SetItemsRect;
end;
procedure TFlatListBox.CMEnabledChanged (var Message: TMessage);
begin
inherited;
Invalidate;
end;
procedure TFlatListBox.CMSysColorChange (var Message: TMessage);
begin
if FUseAdvColors then
begin
ParentColor := True;
CalcAdvColors;
end;
Invalidate;
end;
procedure TFlatListBox.CMParentColorChanged (var Message: TWMNoParams);
begin
inherited;
if FUseAdvColors then
begin
ParentColor := True;
CalcAdvColors;
end;
Invalidate;
end;
procedure TFlatListBox.SetTransparent (const Value: TTransparentMode);
begin
FTransparent := Value;
Invalidate;
end;
procedure TFlatListBox.WMMove (var Message: TWMMove);
begin
inherited;
if not (FTransparent = tmNone) then
Invalidate;
end;
procedure TFlatListBox.WMKillFocus (var Message: TWMKillFocus);
begin
inherited;
if not (FTransparent = tmNone) then
Invalidate;
end;
procedure TFlatListBox.WMSetFocus (var Message: TWMSetFocus);
begin
inherited;
if not (FTransparent = tmNone) then
Invalidate;
end;
procedure TFlatListBox.CNKeyDown (var Message: TWMKeyDown);
begin
case Message.CharCode of
VK_UP:
if (firstItem - 1) < 0 then
firstItem := 0
else
Dec(firstItem);
VK_DOWN:
if firstItem + maxItems + 1 <= FItems.Count then
Inc(firstItem);
VK_PRIOR:
if (firstItem - maxItems) < 0 then
firstItem := 0
else
Dec(firstItem, maxItems);
VK_NEXT:
if firstItem + (maxItems * 2) <= FItems.Count then
Inc(firstItem, maxItems)
else
firstItem := FItems.Count - maxItems;
else
inherited;
end;
Invalidate;
end;
function TFlatListBox.GetItemIndex: Integer;
begin
Result := FItemIndex;
end;
procedure TFlatListBox.SetItemIndex (Value: Integer);
begin
if GetItemIndex <> Value then
begin
FItemIndex := Value;
if MultiSelect then
begin
if (Value) in FSelected then
Exclude(FSelected, Value)
else
Include(FSelected, Value);
end
else
begin
FSelected := FSelected - [0..High(Byte)];
Include(FSelected, Value);
end;
Invalidate;
end;
end;
procedure TFlatListBox.SetMultiSelect (Value: Boolean);
begin
FMultiSelect := Value;
if Value then
FItemIndex := 0;
end;
{$IFDEF DFS_COMPILER_4_UP}
procedure TFlatListBox.SetBiDiMode(Value: TBiDiMode);
begin
inherited;
Invalidate;
end;
{$ENDIF}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -