surfbored
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!
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!
show some source of your effort (as small as possible please)
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.TextW idth(lstIn putFiles.I tems.Strin gs[i]) then
MaxWidth := lstInputFiles.Canvas.TextW idth(lstIn putFiles.I tems.Strin gs[i]);
SendMessage(lstInputFiles. Handle, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
//Add Horizontal scrollbar, regardless of need.
lstInputFiles.Perform(LB_S ETHORIZONT ALEXTENT,5 00,0)
(And to be clear, lstInputFiles is a TCheckListBox)
Thanks!
//Add Horizontal scrollbar, if needed.
MaxWidth := 0;
for i := 0 to lstInputFiles.Items.Count - 1 do
if MaxWidth < lstInputFiles.Canvas.TextW
MaxWidth := lstInputFiles.Canvas.TextW
SendMessage(lstInputFiles.
//Add Horizontal scrollbar, regardless of need.
lstInputFiles.Perform(LB_S
(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;
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(
begin
inherited;
if GetScrollPos(Handle, SB_HORZ) < 15 then
Invalidate();
end;
ASKER
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!
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(CheckListB ox1);
here is the contents of the file CheckListBoxFixer.pas:
unit CheckListBoxFixer;
interface
uses CheckLst, Messages;
procedure FixChecklistBox(CheckListB ox: 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(CheckListB ox: TCheckListBox);
begin
Fixes.Add(TChecklistBoxFix er.Create( CheckListB ox));
end;
{ TChecklistBoxFixer }
constructor TChecklistBoxFixer.Create( CheckListB ox: TCheckListBox);
begin
inherited Create();
fCheckListBox := CheckListBox;
fPrevWndProc := Pointer(GetWindowLong(fChe ckListBox. Handle, GWL_WNDPROC));
SetWindowLong(fCheckListBo x.Handle, GWL_WNDPROC, integer(MakeObjectInstance (NewWndPro c)));
end;
destructor TChecklistBoxFixer.Destroy ;
begin
SetWindowLong(fCheckListBo x.Handle, GWL_WNDPROC, integer(fPrevWndProc));
inherited;
end;
procedure TChecklistBoxFixer.NewWndP roc(var Message: TMessage);
begin
Message.Result := CallWindowProc(fPrevWndPro c, fCheckListBox.Handle, Message.Msg, Message.WParam, Message.LParam);
if (Message.Msg = WM_HSCROLL) and (GetScrollPos(fCheckListBo x.Handle, SB_HORZ) < 15) then
fCheckListBox.Invalidate() ;
end;
initialization
Fixes := TObjectList.Create();
finalization
Fixes.Free();
end.
Make a new unit, name it CheckListBoxFixer.pas.
Use it in the form where you have the checklistbox, and in the formcreate call:
FixChecklistBox(CheckListB
here is the contents of the file CheckListBoxFixer.pas:
unit CheckListBoxFixer;
interface
uses CheckLst, Messages;
procedure FixChecklistBox(CheckListB
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(CheckListB
begin
Fixes.Add(TChecklistBoxFix
end;
{ TChecklistBoxFixer }
constructor TChecklistBoxFixer.Create(
begin
inherited Create();
fCheckListBox := CheckListBox;
fPrevWndProc := Pointer(GetWindowLong(fChe
SetWindowLong(fCheckListBo
end;
destructor TChecklistBoxFixer.Destroy
begin
SetWindowLong(fCheckListBo
inherited;
end;
procedure TChecklistBoxFixer.NewWndP
begin
Message.Result := CallWindowProc(fPrevWndPro
if (Message.Msg = WM_HSCROLL) and (GetScrollPos(fCheckListBo
fCheckListBox.Invalidate()
end;
initialization
Fixes := TObjectList.Create();
finalization
Fixes.Free();
end.
ASKER
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!
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.