Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations MikeeOK on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DrawItem vs DrawFocusRect... 1

Status
Not open for further replies.

rcloutie

Programmer
May 26, 2005
164
CA
Hi there,

I've built a new component based on TCheckListBox.
Implemented a property 'CheckBox' which displays/hides the CheckBox area. All works fine but when current item changes (that is, ItemIndex changes) a FocusRect corresponding to the CheckBox area still visible for all non-current rows. Any way to invalide only this region?

Here's my code within DrawItem protected procedure:
---------------------------------------------------
Procedure TMyList.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
RectText: TRect;
begin
if not bCheckBox then
begin
CopyRect(RectText, Rect);
RectText.Left := RectText.Left - 15;
inherited DrawItem(Index, Rect, State);
with Canvas do
begin
FillRect(RectText);
TextOut(RectText.Left+2, RectText.Top, Items[Index]);
if Index = ItemIndex then
begin
DrawFocusRect(Rect);
DrawFocusRect(RectText);
end

else
begin
// Problem's here...
//DrawFocusRect(Rect);
//DrawFocusRect(RectCheck);
end;
end;
end;

end;
---------------------------------------------------

Any ideas ???

Thanks in advance...
 
Wonderful idea to have such a control. Have a look at the code below. I tried it in Delphi 2005 and works. Please let me know if it works on your version of delphi.


Code:
unit CheckListBox1;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, CheckLst, Windows, Dialogs,Messages;

type
  TCheckListBox1 = class(TCheckListBox)
  private
    bCheckBox:Boolean;
    procedure SetCheckBox(bVal:Boolean);
    procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;

  protected
    procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;

  published
    property CheckBox:Boolean read bCheckBox write SetCheckBox;
  end;

procedure Register;

implementation

uses Graphics;

procedure Register;
begin
  RegisterComponents('Samples', [TCheckListBox1]);
end;

procedure TCheckListBox1.SetCheckBox(bVal:Boolean);
begin
    bCheckBox:=bVal;
    Invalidate;
end;

Procedure TCheckListBox1.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  RectText:  TRect;
begin
  if bCheckBox then
      inherited //draw as usual
  else
  begin
    CopyRect(RectText, Rect);
    RectText.Left := RectText.Left;

    with Canvas do
    begin
      FillRect(RectText);
      TextOut(RectText.Left+2, RectText.Top, Items[Index]);

      //Previously you were using Index=ItemIndex to check selected or not
      //instead you should have checked State (only to be disappointed by
      //some other side effect :)
      //if (odSelected in State) then
        //CAnvas.DrawFocusRect(rcItem);

    end;
  end;

end;

////////////////////////////////////////////////////////////////////////////////
// procedure: CnDrawItem
// purpose  : Must implement this to make sure the rectangle passed to
//            DrawItem is the right size
// note     : I think you could have done the exact same thing by implementing
//            CnMeasureItem, but hey this works !!!
////////////////////////////////////////////////////////////////////////////////
procedure TCheckListBox1.CNDrawItem(var Message: TWMDrawItem);
var
  State: TOwnerDrawState;
begin
  //Look in CheckLst.pas same procedure you may be suprised by the resemblance :)
  if Items.Count = 0 then exit;

  with Message.DrawItemStruct^ do
    if not Header[itemID] then
    begin
      if bCheckBox then //Your magic
      begin
          if not UseRightToLeftAlignment then
            rcItem.Left := rcItem.Left + GetCheckWidth
          else
            rcItem.Right := rcItem.Right - GetCheckWidth;
      end
      else
          rcItem.Left:=rcItem.Left-GetCheckWidth; //Your magic
    end;
  inherited;
end;



"It is in our collective behaviour that we are most mysterious" Lewis Thomas
 
It works fine... you're a king! :)

Some changes to switch live CheckBox True/False...
--------------------------------------------------
Procedure TChkList.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
sText: Array[0..12] of char;
RectText: TRect;
RectCheck: TRect;
begin
CopyRect(RectText, Rect);
CopyRect(RectCheck, Rect);
RectCheck.Left := 0;
RectCheck.Right := 15;

if not bCheckBox then
begin
inherited DrawItem(Index, Rect, State);
with Canvas do
begin
FillRect(RectText);
TextOut(RectText.Left+2, RectText.Top,
Items[Index]);
end;
end

else
begin
with Canvas do
begin
FillChar(sText, Sizeof(sText), #32);
TextOut(RectCheck.Left, RectCheck.Top,
sText);
FillRect(RectCheck);
end;
inherited DrawItem(Index, Rect, State);
end;

end;

procedure TChkList.CNDrawItem(var Message: TWMDrawItem);
begin
if Items.Count = 0 then exit;
with Message.DrawItemStruct^ do
if not Header[itemID] then
if not bCheckBox then
rcItem.Left:=rcItem.Left-GetCheckWidth;
inherited;
end;
--------------------------------------------------

Thanks again.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top