Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1615
  • Last Modified:

TListView and checkboxes

How can I trap when a checkbox get checked and unchecked (an checkbox inside a listview. IE Checkboxses = True on TListView)

How can I set the state to clGreyed on a checkbox inside a TListView
0
wqclatre
Asked:
wqclatre
  • 6
1 Solution
 
mikelittlewoodCommented:
You can simulate it using the onClick event

procedure TForm1.ListView1Click(Sender: TObject);
var
  ListItem:TListItem;
  CurrPos:TPoint;
begin
  CurrPos:=Mouse.CursorPos;
  CurrPos:=ListView1.ScreenToClient(CurrPos);
  ListItem:=ListView1.GetItemAt(CurrPos.x,CurrPos.y);
  if Assigned(ListItem) then
  begin
    if ListItem.Checked then ShowMessage(ListItem.Caption+' Checked')
    else ShowMessage(ListItem.Caption+' not Checked');
  end;
end;
Just make sure you have rowselect = True
0
 
mikelittlewoodCommented:
In fact it will work if you dont have rowselect on.
My mistake.
0
 
mikelittlewoodCommented:
>How can I set the state to clGreyed on a checkbox inside a TListView<

Sorry this part Im not sure if you can.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
wqclatreAuthor Commented:
Strange. I thought I made a comment here before.

Your "solution" don't solve my problem since I don't know the state before. I can't know if just an item is cliked at or if the chekbox is checked. The strange thing is that VB have an OnItemChecked event. Delphi don't.
0
 
TheRealLokiSenior DeveloperCommented:
well you can code it manually
here is an example i wrote for you on how to notice the "Checkbox change" if the viewstyle is vsReport

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

// some constants for dealing with the checkbox position - only for ViewStyle vsReport atm
const
    lv_distancefromleft = 3;
    lv_distancefromtop = 18;
    lv_checkboxheight = 18;
    lv_checkboxwidth = 15;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    Memo1: TMemo;
    procedure ListView1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
// ADDED EVENT HERE FOR HANDLING CHECKBOX CHANGE NICELY
    procedure OnListviewItemChecked(Sender: TObject; const Item: TListItem; const NewState: boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
    CurrentlyPressedListViewCheckbox: integer;
begin
    if
      ( X >= lv_distancefromleft) and
      (X < (lv_distancefromleft + lv_checkboxwidth)) and
      (Y >= lv_distancefromtop) and
      (Y < lv_distancefromtop + ( lv_checkboxheight * (Sender as TListView).Items.Count) )
    then
    begin
        CurrentlyPressedListViewCheckbox := Trunc( (Y - lv_distancefromtop) / lv_checkboxheight);
// now call our nice handling routine
        OnListviewItemChecked( Sender, (Sender as TListView).Items[CurrentlyPressedListViewCheckbox],
          (Sender as TListView).Items[CurrentlyPressedListViewCheckbox].Checked);
    end;

end;

// This procedure is just an example f you wanted to have 1 nice routine for handling the "checkbox"
procedure TForm1.OnListviewItemChecked(Sender: TObject; const Item: TListItem; const NewState: boolean);
begin
    if NewState then memo1.lines.add('checked item: ' + inttostr(Item.index))
    else memo1.lines.add('unchecked item: ' + inttostr(Item.index))
// old check state is obviously "not item.checked"
end;

end.
0
 
mikelittlewoodCommented:
That does the same as what I wrote before

Im not sure why you want to know the state before, it can only be one of two, so if it is checked now, it must have been unchecked.

If you REALLY wanted to hold values for some other reason, maybe store them in an array for checking later

type
  TForm1 = class(TForm)
    ListView1: TListView;
    Memo1: TMemo;
    procedure ListView1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    arrChecked: array of Boolean;
  public
    { Public declarations }
  end;

var
  Form1: TForm;

implementation

{$R *.dfm}

procedure TForm1.ListView1Click(Sender: TObject);
var
  ListItem:TListItem;
  CurrPos:TPoint;
  i: Integer;
begin
  CurrPos:=Mouse.CursorPos;
  CurrPos:=ListView1.ScreenToClient(CurrPos);
  ListItem:=ListView1.GetItemAt(CurrPos.x,CurrPos.y);
  if Assigned(ListItem) then
  begin
    // this bit is pretty pointless to be honest
    // it can only be one of two states
    i := ListItem.Index;
    if arrChecked[i] then
      Memo1.Lines.Add('Item ' + IntToStr(i) + ' was previously Checked')
    else
      Memo1.Lines.Add('Item ' + IntToStr(i) + ' was previously unchecked');

    if ListItem.Checked then
      Memo1.Lines.Add('Item ' + IntToStr(i) + ' is now Checked')
    else
      Memo1.Lines.Add('Item ' + IntToStr(i) + ' is now unchecked');

    // set the item
    arrChecked[i] := ListItem.Checked;
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
var
  i: Integer;
begin
  // get current states
  SetLength(arrChecked, ListView1.Items.Count);
  for i := 0 to Pred(ListView1.Items.Count) do
    arrChecked[i] := ListView1.Items[i].Checked;
end;
0
 
mikelittlewoodCommented:
I forgot that you need to set the length of the array to the number of items in the TListView, and this will need to be adjusted when items are added or removed.
  // set the length of the array
  SetLength(arrChecked,TListView1.Items.Count)

If you update the number of items in a listview, you will need to re-run

  // get current states
  SetLength(arrChecked, ListView1.Items.Count);
  for i := 0 to Pred(ListView1.Items.Count) do
    arrChecked[i] := ListView1.Items[i].Checked;


you might not want to set the array variable
    // set the item
    arrChecked[i] := ListItem.Checked;
within the OnClick event.
If you are doing some processing on the checked items, it might be worth repopulating the array once processing complete, before checking again.
0
 
mikelittlewoodCommented:
Im presuming that you are populating a lot of data rather than one column, otherwise you could use a CheckListBox which has an OnClickCheck event.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now