Advertisement
TLama

Untitled

Apr 12th, 2014
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 2.99 KB | None | 0 0
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, ComCtrls, CommCtrl;
  8.  
  9. type
  10.   TListView = class(ComCtrls.TListView)
  11.   private
  12.     FCheckIndex: Integer;
  13.     procedure CNNotify(var AMessage: TWMNotifyLV); message CN_NOTIFY;
  14.   protected
  15.     function CanChangeEx(Item: TListItem; OldState, NewState, Changed: UINT): Boolean; virtual;
  16.   public
  17.     constructor Create(AOwner: TComponent); override;
  18.   end;
  19.  
  20.  
  21. type
  22.   TForm1 = class(TForm)
  23.     ListView1: TListView;
  24.     procedure FormCreate(Sender: TObject);
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.dfm}
  33.  
  34. procedure TForm1.FormCreate(Sender: TObject);
  35. var
  36.   I: Integer;
  37. begin
  38.   ListView1.Columns.Add;
  39.   ListView1.Checkboxes := True;
  40.   ListView1.ViewStyle := vsReport;
  41.  
  42.   for I := 1 to 10 do
  43.     ListView1.AddItem('Item ' + IntToStr(I), nil);
  44.  
  45.   ListView1.Items[5].Checked := True;
  46. end;
  47.  
  48. { TListView }
  49.  
  50. constructor TListView.Create(AOwner: TComponent);
  51. begin
  52.   inherited;
  53.   FCheckIndex := -1;
  54. end;
  55.  
  56. function IsChecked(State: UINT): Boolean; inline;
  57. begin
  58.   Result := ((State and LVIS_STATEIMAGEMASK) and $2000) <> 0;
  59. end;
  60.  
  61. function IsUnchecked(State: UINT): Boolean; inline;
  62. begin
  63.   Result := ((State and LVIS_STATEIMAGEMASK) and $1000) <> 0;
  64. end;
  65.  
  66. function CheckChanged(OldState, NewState, Changed: UINT): Boolean; inline;
  67. begin
  68.   Result := (Changed = LVIF_STATE) and (((OldState and LVIS_STATEIMAGEMASK) and $3000) <>
  69.     ((NewState and LVIS_STATEIMAGEMASK) and $3000));
  70. end;
  71.  
  72. function TListView.CanChangeEx(Item: TListItem; OldState, NewState, Changed: UINT): Boolean;
  73. begin
  74.   // allow the change only when the check box is going to be unchecked and the item is not
  75.   // the remembered one, or if the check box going to be checked
  76.   Result := (IsUnchecked(NewState) and (Item.Index <> FCheckIndex)) or IsChecked(NewState);
  77. end;
  78.  
  79. procedure TListView.CNNotify(var AMessage: TWMNotifyLV);
  80. var
  81.   OldCheck: Integer;
  82. begin
  83.   if  AMessage.NMHdr.code = LVN_ITEMCHANGING then
  84.   begin
  85.     with AMessage.NMListView^ do
  86.     begin
  87.       if CheckChanged(uOldState, uNewState, uChanged) then
  88.       begin
  89.         if not CanChangeEx(Items[iItem], uOldState, uNewState, uChanged) then
  90.           AMessage.Result := 1
  91.         else
  92.         if IsChecked(uNewState) then
  93.         begin
  94.           // store the check index of the item to be unchecked
  95.           OldCheck := FCheckIndex;
  96.           // remember the index of the item that will be checked
  97.           FCheckIndex := iItem;
  98.           // and uncheck the previously checked item if there was any; this can fail
  99.           // with an access to a not existing item; there must be added other things
  100.           // anyway, like e.g. updating the FCheckIndex field whenever the items are
  101.           // reordered, deleted etc.
  102.           if OldCheck <> -1 then
  103.             Items[OldCheck].Checked := False;
  104.         end;
  105.       end
  106.       else
  107.         inherited;
  108.     end;
  109.   end
  110.   else
  111.     inherited;
  112. end;
  113.  
  114. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement