Link to home
Start Free TrialLog in
Avatar of surfbored
surfboredFlag for United States of America

asked on

CheckListBox Paints Poorly With Horizontal Scrollbar

I've tried a couple different ways to add a horizontal scrollbar with a checklistbox, and while they sort of work, all the approaches have the effect of "erasing" the checks in each checkbox when the horizontal scrollbar is used.

To be more precise, the checks are still in the boxes, they're just poorly repainted when the scrollbar is moved back to the left. Scrolling up or down repaints the checks, as does using the arrow keys to move the list.

I'd like my program to look as professional as possible, any suggestions?

It might also help to know that I'm using Delphi 2005, Windows XP SP2 and XPManifest.

Thanks!
Avatar of MerijnB
MerijnB
Flag of Netherlands image

show some source of your effort (as small as possible please)
Avatar of surfbored

ASKER

Here's two examples of what I tried...

    //Add Horizontal scrollbar, if needed.
  MaxWidth := 0;
  for i := 0 to lstInputFiles.Items.Count - 1 do
  if MaxWidth < lstInputFiles.Canvas.TextWidth(lstInputFiles.Items.Strings[i]) then
    MaxWidth := lstInputFiles.Canvas.TextWidth(lstInputFiles.Items.Strings[i]);
  SendMessage(lstInputFiles.Handle, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
 
  //Add Horizontal scrollbar, regardless of need.
  lstInputFiles.Perform(LB_SETHORIZONTALEXTENT,500,0)

(And to be clear, lstInputFiles is a TCheckListBox)

Thanks!
nasty bug which seems to go quite deep.
As a 'workaround' I can offer you this; please let me know if it's clear enough for you.
It's not a neat solution, but it does do the trick.


Make your own TCheckListBox descendant, like this:

type
 TMyChecklistbox = class(TChecklistBox)
  private
   procedure WMHSCROLL(var WMHScroll: TWMHScroll); message WM_HSCROLL;
 end;

...

procedure tMyChecklistbox.WMHSCROLL(var WMHScroll: TWMHScroll);
begin
 inherited;

 if GetScrollPos(Handle, SB_HORZ) < 15 then
  Invalidate();
end;
Uh...

I'm afraid this fix is a little over my head.

If you could provide some more information on the topic of creating descendants, that would be most helpful. Or, at the least, guide me as to where this coding would be placed so I can try it.

Thanks again!
ok, try this.

Make a new unit, name it CheckListBoxFixer.pas.
Use it in the form where you have the checklistbox, and in the formcreate call:

  FixChecklistBox(CheckListBox1);


here is the contents of the file CheckListBoxFixer.pas:

unit CheckListBoxFixer;

interface

uses CheckLst, Messages;

procedure FixChecklistBox(CheckListBox: TCheckListBox);

implementation

uses Contnrs, Windows, Classes;

type TChecklistBoxFixer = class(TObject)
     private
      fCheckListBox: TCheckListBox;
      fPrevWndProc: Pointer;

      procedure NewWndProc(Var Message: TMessage);
     public
      constructor Create(CheckListBox: TCheckListBox); reintroduce;
      destructor Destroy; override;
     end;

var Fixes: TObjectList;

procedure FixChecklistBox(CheckListBox: TCheckListBox);
begin
 Fixes.Add(TChecklistBoxFixer.Create(CheckListBox));
end;

{ TChecklistBoxFixer }

constructor TChecklistBoxFixer.Create(CheckListBox: TCheckListBox);
begin
 inherited Create();

 fCheckListBox := CheckListBox;
 fPrevWndProc := Pointer(GetWindowLong(fCheckListBox.Handle, GWL_WNDPROC));
 SetWindowLong(fCheckListBox.Handle, GWL_WNDPROC, integer(MakeObjectInstance(NewWndProc)));
end;

destructor TChecklistBoxFixer.Destroy;
begin
 SetWindowLong(fCheckListBox.Handle, GWL_WNDPROC, integer(fPrevWndProc));

 inherited;
end;

procedure TChecklistBoxFixer.NewWndProc(var Message: TMessage);
begin
 Message.Result := CallWindowProc(fPrevWndProc, fCheckListBox.Handle, Message.Msg, Message.WParam, Message.LParam);

 if (Message.Msg = WM_HSCROLL) and (GetScrollPos(fCheckListBox.Handle, SB_HORZ) < 15) then
  fCheckListBox.Invalidate();
end;

initialization
 Fixes := TObjectList.Create();

finalization
 Fixes.Free();

end.
This answer goes above and beyond, thank you very much.

I have only found one problem, when I use this code, I get an error when I close the program. It reads as follows:

First chance exception at $7C812A5B. Exception class EInvalidOperation with message 'Control '' has no parent window'.  Process test.exe (2828)

It's not clear to me where/why this error is happening. Any suggestions?

PS: Point value has been doubled, thanks for all the help!
ASKER CERTIFIED SOLUTION
Avatar of MerijnB
MerijnB
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial