Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, ComCtrls, CommCtrl;
- type
- TListView = class(ComCtrls.TListView)
- private
- FCheckIndex: Integer;
- procedure CNNotify(var AMessage: TWMNotifyLV); message CN_NOTIFY;
- protected
- function CanChangeEx(Item: TListItem; OldState, NewState, Changed: UINT): Boolean; virtual;
- public
- constructor Create(AOwner: TComponent); override;
- end;
- type
- TForm1 = class(TForm)
- ListView1: TListView;
- procedure FormCreate(Sender: TObject);
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- procedure TForm1.FormCreate(Sender: TObject);
- var
- I: Integer;
- begin
- ListView1.Columns.Add;
- ListView1.Checkboxes := True;
- ListView1.ViewStyle := vsReport;
- for I := 1 to 10 do
- ListView1.AddItem('Item ' + IntToStr(I), nil);
- ListView1.Items[5].Checked := True;
- end;
- { TListView }
- constructor TListView.Create(AOwner: TComponent);
- begin
- inherited;
- FCheckIndex := -1;
- end;
- function IsChecked(State: UINT): Boolean; inline;
- begin
- Result := ((State and LVIS_STATEIMAGEMASK) and $2000) <> 0;
- end;
- function IsUnchecked(State: UINT): Boolean; inline;
- begin
- Result := ((State and LVIS_STATEIMAGEMASK) and $1000) <> 0;
- end;
- function CheckChanged(OldState, NewState, Changed: UINT): Boolean; inline;
- begin
- Result := (Changed = LVIF_STATE) and (((OldState and LVIS_STATEIMAGEMASK) and $3000) <>
- ((NewState and LVIS_STATEIMAGEMASK) and $3000));
- end;
- function TListView.CanChangeEx(Item: TListItem; OldState, NewState, Changed: UINT): Boolean;
- begin
- // allow the change only when the check box is going to be unchecked and the item is not
- // the remembered one, or if the check box going to be checked
- Result := (IsUnchecked(NewState) and (Item.Index <> FCheckIndex)) or IsChecked(NewState);
- end;
- procedure TListView.CNNotify(var AMessage: TWMNotifyLV);
- var
- OldCheck: Integer;
- begin
- if AMessage.NMHdr.code = LVN_ITEMCHANGING then
- begin
- with AMessage.NMListView^ do
- begin
- if CheckChanged(uOldState, uNewState, uChanged) then
- begin
- if not CanChangeEx(Items[iItem], uOldState, uNewState, uChanged) then
- AMessage.Result := 1
- else
- if IsChecked(uNewState) then
- begin
- // store the check index of the item to be unchecked
- OldCheck := FCheckIndex;
- // remember the index of the item that will be checked
- FCheckIndex := iItem;
- // and uncheck the previously checked item if there was any; this can fail
- // with an access to a not existing item; there must be added other things
- // anyway, like e.g. updating the FCheckIndex field whenever the items are
- // reordered, deleted etc.
- if OldCheck <> -1 then
- Items[OldCheck].Checked := False;
- end;
- end
- else
- inherited;
- end;
- end
- else
- inherited;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement