📄 jvxchecklistbox.pas
字号:
Self.State[I] := TJvxCheckListBox(TJvListBoxStrings(Value).ListBox).State[I];
EnabledItem[I] :=
TJvxCheckListBox(TJvListBoxStrings(Value).ListBox).EnabledItem[I];
end;
end;
finally
Items.EndUpdate;
end;
end;
procedure TJvxCheckListBox.InternalLoad(const Section: string);
begin
if Assigned(IniStorage) then
with IniStorage do
LoadFromAppStorage(AppStorage, AppStorage.ConcatPaths([AppStoragePath, Section]));
end;
procedure TJvxCheckListBox.InternalSave(const Section: string);
begin
if Assigned(IniStorage) then
with IniStorage do
SaveToAppStorage(AppStorage, AppStorage.ConcatPaths([AppStoragePath, Section]));
end;
function TJvxCheckListBox.GetItemWidth(Index: Integer): Integer;
begin
Result := inherited GetItemWidth(Index) + GetCheckWidth;
end;
function TJvxCheckListBox.GetCheckWidth: Integer;
begin
Result := FCheckWidth + 2;
end;
function TJvxCheckListBox.GetAllowGrayed: Boolean;
begin
Result := FAllowGrayed and (FCheckKind in [ckCheckBoxes, ckCheckMarks]);
end;
procedure TJvxCheckListBox.FontChanged;
begin
inherited FontChanged;
ResetItemHeight;
end;
function TJvxCheckListBox.GetItemHeight: Integer;
var
R: TRect;
begin
Result := FItemHeight;
if HandleAllocated and ((FStyle = lbStandard) or
((FStyle = lbOwnerDrawFixed) and not Assigned(FOnDrawItem))) then
begin
Perform(LB_GETITEMRECT, 0, Longint(@R));
Result := R.Bottom - R.Top;
end;
end;
procedure TJvxCheckListBox.ResetItemHeight;
var
H: Integer;
begin
if csDestroying in ComponentState then
Exit;
if (Style = lbStandard) or ((Style = lbOwnerDrawFixed) and
not Assigned(FOnDrawItem)) then
begin
FCanvas.Font := Font;
H := Max(CanvasMaxTextHeight(FCanvas), FCheckHeight);
if Style = lbOwnerDrawFixed then
H := Max(H, FItemHeight);
Perform(LB_SETITEMHEIGHT, 0, H);
if (H * Items.Count) <= ClientHeight then
SetScrollRange(Handle, SB_VERT, 0, 0, True);
end;
end;
procedure TJvxCheckListBox.DrawItem(Index: Integer; Rect: TRect;
State: TOwnerDrawState);
var
R: TRect;
SaveEvent: TDrawItemEvent;
begin
if csDestroying in ComponentState then
Exit;
if Index < Items.Count then
begin
R := Rect;
if not UseRightToLeftAlignment then
begin
R.Right := Rect.Left;
R.Left := R.Right - GetCheckWidth;
end
else
begin
R.Left := Rect.Right;
R.Right := R.Left + GetCheckWidth;
end;
DrawCheck(R, GetState(Index), EnabledItem[Index]);
if not EnabledItem[Index] then
if odSelected in State then
FCanvas.Font.Color := clInactiveCaptionText
else
FCanvas.Font.Color := clGrayText;
end;
if (Style = lbStandard) and Assigned(FOnDrawItem) then
begin
SaveEvent := OnDrawItem;
OnDrawItem := nil;
try
inherited DrawItem(Index, Rect, State);
finally
OnDrawItem := SaveEvent;
end;
end
else
inherited DrawItem(Index, Rect, State);
end;
procedure TJvxCheckListBox.CNDrawItem(var Msg: TWMDrawItem);
begin
with Msg.DrawItemStruct^ do
if not UseRightToLeftAlignment then
rcItem.Left := rcItem.Left + GetCheckWidth
else
rcItem.Right := rcItem.Right - GetCheckWidth;
inherited;
end;
procedure TJvxCheckListBox.DrawCheck(R: TRect; AState: TCheckBoxState;
Enabled: Boolean);
const
CheckImages: array [TCheckBoxState, TCheckKind, Boolean] of Integer =
(((3, 0), (9, 6), (15, 12)), { unchecked }
((4, 1), (10, 7), (16, 13)), { checked }
((5, 2), (11, 8), (17, 14))); { grayed }
var
DrawRect: TRect;
SaveColor: TColor;
{$IFDEF JVCLThemesEnabled}
Flags: Cardinal;
{$ENDIF JVCLThemesEnabled}
begin
if csDestroying in ComponentState then
Exit;
DrawRect.Left := R.Left + (R.Right - R.Left - FCheckWidth) div 2;
DrawRect.Top := R.Top + (R.Bottom - R.Top - FCheckHeight) div 2;
DrawRect.Right := DrawRect.Left + FCheckWidth;
DrawRect.Bottom := DrawRect.Top + FCheckHeight;
SaveColor := FCanvas.Brush.Color;
{$IFDEF JVCLThemesEnabled}
if ThemeServices.ThemesEnabled and (CheckKind in [ckCheckBoxes, ckRadioButtons]) then
begin
Flags := 0;
if not Enabled then
Flags := Flags or DFCS_INACTIVE;
if AState = cbChecked then
Flags := Flags or DFCS_CHECKED
else
if AState = cbGrayed then
Flags := Flags or DFCS_MONO;
if CheckKind = ckCheckBoxes then
DrawThemedFrameControl(Self, Canvas.Handle, DrawRect, DFC_BUTTON,
DFCS_BUTTONCHECK or Flags)
else
if CheckKind = ckRadioButtons then
DrawThemedFrameControl(Self, Canvas.Handle, DrawRect, DFC_BUTTON,
DFCS_BUTTONRADIO or Flags);
end
else
{$ENDIF JVCLThemesEnabled}
begin
AssignBitmapCell(CheckBitmap, FDrawBitmap, 6, 3,
CheckImages[AState, CheckKind, Enabled]);
FCanvas.Brush.Color := Self.Color;
try
FCanvas.BrushCopy(DrawRect, FDrawBitmap, Bounds(0, 0, FCheckWidth,
FCheckHeight), CheckBitmap.TransparentColor and not PaletteMask);
finally
FCanvas.Brush.Color := SaveColor;
end;
end;
end;
procedure TJvxCheckListBox.ApplyState(AState: TCheckBoxState; EnabledOnly: Boolean);
var
I: Integer;
begin
if FCheckKind in [ckCheckBoxes, ckCheckMarks] then
for I := 0 to Items.Count - 1 do
if not EnabledOnly or EnabledItem[I] then
State[I] := AState;
end;
function TJvxCheckListBox.GetCheckedIndex: Integer;
var
I: Integer;
begin
Result := -1;
if FCheckKind = ckRadioButtons then
for I := 0 to Items.Count - 1 do
if State[I] = cbChecked then
begin
Result := I;
Break;
end;
end;
procedure TJvxCheckListBox.SetCheckedIndex(Value: Integer);
begin
if (FCheckKind = ckRadioButtons) and (Items.Count > 0) then
SetState(Max(Value, 0), cbChecked);
end;
procedure TJvxCheckListBox.UpdateCheckStates;
begin
if (FCheckKind = ckRadioButtons) and (Items.Count > 0) then
begin
FInUpdateStates := True;
try
SetState(Max(GetCheckedIndex, 0), cbChecked);
finally
FInUpdateStates := False;
end;
end;
end;
procedure TJvxCheckListBox.SetCheckKind(Value: TCheckKind);
begin
if FCheckKind <> Value then
begin
FCheckKind := Value;
UpdateCheckStates;
Invalidate;
end;
end;
procedure TJvxCheckListBox.SetChecked(Index: Integer; AChecked: Boolean);
const
CheckStates: array [Boolean] of TCheckBoxState = (cbUnchecked, cbChecked);
begin
SetState(Index, CheckStates[AChecked]);
end;
procedure TJvxCheckListBox.SetState(Index: Integer; AState: TCheckBoxState);
var
I: Integer;
begin
if (AState <> GetState(Index)) or FInUpdateStates then
begin
if (FCheckKind = ckRadioButtons) and (AState = cbUnchecked) and
(GetCheckedIndex = Index) then
Exit;
TJvCheckListBoxItem(GetCheckObject(Index)).State := AState;
if (FCheckKind = ckRadioButtons) and (AState = cbChecked) then
for I := Items.Count - 1 downto 0 do
begin
if (I <> Index) and (GetState(I) = cbChecked) then
begin
TJvCheckListBoxItem(GetCheckObject(I)).State := cbUnchecked;
InvalidateCheck(I);
end;
end;
InvalidateCheck(Index);
if not (csReading in ComponentState) then
ChangeItemState(Index);
end;
end;
procedure TJvxCheckListBox.SetItemEnabled(Index: Integer; Value: Boolean);
begin
if Value <> GetItemEnabled(Index) then
begin
TJvCheckListBoxItem(GetCheckObject(Index)).Enabled := Value;
InvalidateItem(Index);
end;
end;
procedure TJvxCheckListBox.InvalidateCheck(Index: Integer);
var
R: TRect;
begin
R := ItemRect(Index);
if not UseRightToLeftAlignment then
R.Right := R.Left + GetCheckWidth
else
R.Left := R.Right - GetCheckWidth;
InvalidateRect(Handle, @R, not (csOpaque in ControlStyle));
UpdateWindow(Handle);
end;
procedure TJvxCheckListBox.InvalidateItem(Index: Integer);
var
R: TRect;
begin
R := ItemRect(Index);
InvalidateRect(Handle, @R, not (csOpaque in ControlStyle));
UpdateWindow(Handle);
end;
function TJvxCheckListBox.GetChecked(Index: Integer): Boolean;
begin
if IsCheckObject(Index) then
Result := TJvCheckListBoxItem(GetCheckObject(Index)).GetChecked
else
Result := False;
end;
function TJvxCheckListBox.GetState(Index: Integer): TCheckBoxState;
begin
if IsCheckObject(Index) then
Result := TJvCheckListBoxItem(GetCheckObject(Index)).State
else
Result := clbDefaultState;
if (FCheckKind = ckRadioButtons) and (Result <> cbChecked) then
Result := cbUnchecked;
end;
function TJvxCheckListBox.GetItemEnabled(Index: Integer): Boolean;
begin
if IsCheckObject(Index) then
Result := TJvCheckListBoxItem(GetCheckObject(Index)).Enabled
else
Result := clbDefaultEnabled;
end;
procedure TJvxCheckListBox.KeyPress(var Key: Char);
begin
inherited KeyPress(Key);
case Key of
' ':
begin
ToggleClickCheck(ItemIndex);
Key := #0;
end;
'+':
begin
ApplyState(cbChecked, True);
ClickCheck;
end;
'-':
begin
ApplyState(cbUnchecked, True);
ClickCheck;
end;
end;
end;
procedure TJvxCheckListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
Index: Integer;
begin
inherited MouseDown(Button, Shift, X, Y);
if Button = mbLeft then
begin
Index := ItemAtPos(Point(X, Y), True);
if Index <> -1 then
begin
if not UseRightToLeftAlignment then
begin
if X - ItemRect(Index).Left < GetCheckWidth then
ToggleClickCheck(Index);
end
else
begin
Dec(X, ItemRect(Index).Right - GetCheckWidth);
if (X > 0) and (X < GetCheckWidth) then
ToggleClickCheck(Index);
end;
end;
end;
end;
procedure TJvxCheckListBox.ToggleClickCheck(Index: Integer);
var
State: TCheckBoxState;
begin
if (Index >= 0) and (Index < Items.Count) and EnabledItem[Index] then
begin
State := Self.State[Index];
case State of
cbUnchecked:
if AllowGrayed then
State := cbGrayed
else
State := cbChecked;
cbChecked:
State := cbUnchecked;
cbGrayed:
State := cbChecked;
end;
Self.State[Index] := State;
ClickCheck;
end;
end;
procedure TJvxCheckListBox.ChangeItemState(Index: Integer);
begin
if Assigned(FOnStateChange) then
FOnStateChange(Self, Index);
end;
procedure TJvxCheckListBox.ClickCheck;
begin
if Assigned(FOnClickCheck) then
FOnClickCheck(Self);
end;
function TJvxCheckListBox.GetItemData(Index: Integer): Longint;
var
Item: TJvCheckListBoxItem;
begin
Result := 0;
if IsCheckObject(Index) then
begin
Item := TJvCheckListBoxItem(GetCheckObject(Index));
if Item <> nil then
Result := Item.FData;
end;
end;
function TJvxCheckListBox.GetCheckObject(Index: Integer): TObject;
begin
Result := FindCheckObject(Index);
if Result = nil then
Result := CreateCheckObject(Index);
end;
function TJvxCheckListBox.FindCheckObject(Index: Integer): TObject;
var
ItemData: Longint;
begin
Result := nil;
ItemData := inherited GetItemData(Index);
if ItemData = LB_ERR then
ListIndexError(Index)
else
begin
Result := TJvCheckListBoxItem(ItemData);
if not (Result is TJvCheckListBoxItem) then
Result := nil;
end;
end;
function TJvxCheckListBox.CreateCheckObject(Index: Integer): TObject;
begin
Result := TJvCheckListBoxItem.Create;
inherited SetItemData(Index, Longint(Result));
end;
function TJvxCheckListBox.IsCheckObject(Index: Integer): Boolean;
begin
Result := FindCheckObject(Index) <> nil;
end;
procedure TJvxCheckListBox.SetItemData(Index: Integer; AData: Longint);
var
Item: TJvCheckListBoxItem;
L: Longint;
begin
Item := TJvCheckListBoxItem(GetCheckObject(Index));
Item.FData := AData;
if (FSaveStates <> nil) and (FSaveStates.Count > 0) then
begin
L := Longint(Pointer(FSaveStates[0]));
Item.FState := TCheckBoxState(LongRec(L).Hi);
Item.FEnabled := LongRec(L).Lo <> 0;
FSaveStates.Delete(0);
end;
end;
procedure TJvxCheckListBox.ResetContent;
var
I: Integer;
begin
for I := Items.Count - 1 downto 0 do
begin
if IsCheckObject(I) then
GetCheckObject(I).Free;
inherited SetItemData(I, 0);
end;
inherited ResetContent;
end;
procedure TJvxCheckListBox.DeleteString(Index: Integer);
begin
if IsCheckObject(Index) then
GetCheckObject(Index).Free;
inherited SetItemData(Index, 0);
inherited DeleteString(Index);
end;
initialization
{$IFDEF UNITVERSIONING}
RegisterUnitVersion(HInstance, UnitVersioning);
{$ENDIF UNITVERSIONING}
finalization
FreeAndNil(GCheckBitmap);
{$IFDEF UNITVERSIONING}
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -