Componentes.Terceros.jvcl/official/3.36/run/JvListBox.pas
2009-02-27 12:23:32 +00:00

2432 lines
69 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvListbox2.PAS, released on 2001-02-28.
The Initial Developer of the Original Code is Sébastien Buysse [sbuysse att buypin dott com]
Portions created by Sébastien Buysse are Copyright (C) 2001 Sébastien Buysse.
All Rights Reserved.
This unit is a merging of the original TJvListBox, JvListBox2, TJvExListBox.
Merging done 2002-06-15 by Peter Thornqvist [peter3 at sourceforge dot net]
Contributor(s):
Michael Beck [mbeck att bigfoot dott com].
Petr Vones (petr dott v att mujmail dott cz)
Peter Below <100113 dott 1101 att compuserve dott com>
MERGE NOTES:
* The Alignment property might mess things up depending on other property settings
* not very extensively tested
* TJvListBox in JvCtrls inherits from TJvCustomListbox in this unit.
Maybe TJvListBox should be moved here instead (or this code into JvCtrls)?
* TJvPlaylist now inherits from JvListBox
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
Merge notes (2002-03-21):
* (p3) merged JvMultilineListBox, JvReorderListBox, JvTextListBox, JvBMPListBox
Notes (2003-05-21) // Remko Bonte
* Removed OwnerData
* Some bug-fixes. Combinations of Multiline, Alignment, Scrollbars seem to work now.
* Did some rewrite of background-drawing. Most of it seems to work, but a lot
of flickering, best avoid it or set ScrollBars to ssNone.
* Updated drag image to use with MultiLine.
-----------------------------------------------------------------------------}
// $Id: JvListBox.pas 11893 2008-09-09 20:45:14Z obones $
unit JvListBox;
{$I jvcl.inc}
{$I vclonly.inc}
interface
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
{$IFDEF CLR}
System.Reflection,
Types,
{$ENDIF CLR}
Windows, Messages, SysUtils, Classes, Graphics, StdCtrls, Controls, Forms,
JvItemsSearchs, JvDataProvider, JvDataProviderIntf, JvExStdCtrls;
type
TJvListboxFillMode = (bfmTile, bfmStretch);
TJvListBoxDataEvent = procedure(Sender: TWinControl; Index: Integer; var Text: string) of object;
TJvListboxChange = procedure(Sender: TObject; Item: string) of object;
TJvScrollEvent = procedure(Sender: TObject; const Msg: TWMScroll; var DontScroll: Boolean) of object;
TJvListBoxBackground = class(TPersistent)
private
FOnChange: TNotifyEvent;
FImage: TBitmap;
FFillMode: TJvListboxFillMode;
FVisible: Boolean;
procedure SetFillMode(const Value: TJvListboxFillMode);
procedure SetImage(const Value: TBitmap);
procedure SetVisible(const Value: Boolean);
function GetDoDraw: Boolean;
protected
procedure Change;
public
constructor Create;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
published
property DoDraw: Boolean read GetDoDraw;
property Image: TBitmap read FImage write SetImage;
property FillMode: TJvListboxFillMode read FFillMode write SetFillMode;
property Visible: Boolean read FVisible write SetVisible;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
TJvCustomListBox = class;
{ This class will be used for the Items property of the list box.
If a provider is active at the list box, this list will keep the strings stored in an internal
list.
Whenever an item is added to the list the provider will be deactivated and the list will be
handled by the list box as usual. }
TJvListBoxStrings = class(TStrings)
private
FListBox: TJvCustomListBox;
FInternalList: TStringList;
FUseInternal: Boolean;
FUpdating: Boolean;
FDestroyCnt: Integer;
function GetInternalList: TStrings;
protected
function Get(Index: Integer): string; override;
function GetCount: Integer; override;
function GetObject(Index: Integer): TObject; override;
procedure Put(Index: Integer; const S: string); override;
procedure PutObject(Index: Integer; AObject: TObject); override;
procedure SetUpdateState(Updating: Boolean); override;
procedure SetWndDestroying(Destroying: Boolean);
function GetListBox: TJvCustomListBox;
procedure SetListBox(Value: TJvCustomListBox);
property ListBox: TJvCustomListBox read GetListBox write SetListBox;
property InternalList: TStrings read GetInternalList;
property UseInternal: Boolean read FUseInternal write FUseInternal;
property Updating: Boolean read FUpdating;
property DestroyCount: Integer read FDestroyCnt;
public
constructor Create; virtual;
destructor Destroy; override;
function Add(const S: string): Integer; override;
procedure Clear; override;
procedure Delete(Index: Integer); override;
function IndexOf(const S: string): Integer; override;
procedure Insert(Index: Integer; const S: string); override;
procedure Move(CurIndex, NewIndex: Integer); override;
procedure MakeListInternal; virtual;
procedure ActivateInternal; virtual;
end;
TJvListBoxStringsClass = class of TJvListBoxStrings;
TJvCustomListBox = class(TJvExCustomListBox)
private
FHotTrack: Boolean;
FAlignment: TAlignment;
FMaxWidth: Integer;
FScrollBars: TScrollStyle;
FSorted: Boolean;
FOnGetText: TJvListBoxDataEvent;
FOnSelectCancel: TNotifyEvent;
FOnDeleteString: TJvListboxChange;
FOnAddString: TJvListboxChange;
FOnChange: TNotifyEvent;
FOnHorizontalScroll: TJvScrollEvent;
FOnVerticalScroll: TJvScrollEvent;
FDragIndex: Integer;
FDragImage: TDragImageList;
FMultiline: Boolean;
FShowFocusRect: Boolean;
FSelectedTextColor: TColor;
FSelectedColor: TColor;
FDisabledTextColor: TColor;
FBackground: TJvListBoxBackground;
FLeftPosition: Integer;
{$IFNDEF CLR}
FConsumerSvc: TJvDataConsumer;
FConsumerStrings: TJvConsumerStrings;
{$ENDIF !CLR}
FProviderIsActive: Boolean;
FProviderToggle: Boolean;
FMoving: Boolean;
procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
procedure CNKeyDown(var Msg: TWMKeyDown); message CN_KEYDOWN;
procedure DrawBackGround(ADC: HDC; const DoOffSet: Boolean);
procedure UpdateStyle;
{ Handle messages that insert or delete strings from the listbox to
manage the horizontal scrollbar if FMutliline is false. }
procedure LBAddString(var Msg: TMessage); message LB_ADDSTRING;
procedure LBInsertString(var Msg: TMessage); message LB_INSERTSTRING;
procedure LBDeleteString(var Msg: TMessage); message LB_DELETESTRING;
{ Override CN_DRAWITEM handling to be able to switch off focus rect. }
procedure CNDrawItem(var Msg: TWMDrawItem); message CN_DRAWITEM;
procedure SetAlignment(const Value: TAlignment);
procedure SetMultiline(const Value: Boolean);
procedure SetSelectedColor(const Value: TColor);
procedure SetSelectedTextColor(const Value: TColor);
procedure SetShowFocusRect(const Value: Boolean);
procedure SetDisabledTextColor(const Value: TColor);
procedure SetMaxWidth(const Value: Integer);
procedure SetScrollBars(const Value: TScrollStyle);
procedure SetSorted(const Value: Boolean);
procedure SetHotTrack(const Value: Boolean);
procedure SetBackground(const Value: TJvListBoxBackground);
function GetLimitToClientWidth: Boolean;
function GetFlat: Boolean;
procedure SetFlat(const Value: Boolean);
function GetParentFlat: Boolean;
procedure SetParentFlat(const Value: Boolean);
protected
procedure FontChanged; override;
function GetItemsClass: TJvListBoxStringsClass; virtual;
procedure BeginRedraw;
procedure EndRedraw;
{$IFNDEF CLR}
procedure SetConsumerService(Value: TJvDataConsumer);
procedure ConsumerServiceChanging(Sender: TJvDataConsumer; Reason: TJvDataConsumerChangeReason);
procedure ConsumerServiceChanged(Sender: TJvDataConsumer; Reason: TJvDataConsumerChangeReason);
procedure ConsumerSubServiceCreated(Sender: TJvDataConsumer;
SubSvc: TJvDataConsumerAggregatedObject);
{$ENDIF !CLR}
function IsProviderSelected: Boolean;
function IsProviderToggle: Boolean;
procedure DeselectProvider;
procedure UpdateItemCount;
{$IFNDEF CLR}
property Provider: TJvDataConsumer read FConsumerSvc write SetConsumerService;
property ConsumerStrings: TJvConsumerStrings read FConsumerStrings;
{$ENDIF !CLR}
procedure LBFindString(var Msg: TMessage); message LB_FINDSTRING;
procedure LBFindStringExact(var Msg: TMessage); message LB_FINDSTRINGEXACT;
procedure LBSelectString(var Msg: TMessage); message LB_SELECTSTRING;
procedure LBGetText(var Msg: TMessage); message LB_GETTEXT;
procedure LBGetTextLen(var Msg: TMessage); message LB_GETTEXTLEN;
procedure DoStartDrag(var DragObject: TDragObject); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); override;
function DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean; override;
procedure MouseEnter(Control: TControl); override;
procedure MouseLeave(Control: TControl); override;
procedure SelectCancel(var Msg: TMessage); message LBN_SELCANCEL;
procedure Changed; virtual;
procedure DrawItem(Index: Integer; Rect: TRect;
State: TOwnerDrawState); override;
procedure MeasureItem(Index: Integer; var Height: Integer); override;
procedure RemeasureAll;
procedure DoBackgroundChange(Sender: TObject);
procedure Loaded; override;
{$IFNDEF CLR}
procedure DrawProviderItem(Canvas: TCanvas; Rect: TRect; Index: Integer;
State: TOwnerDrawState);
{$ENDIF !CLR}
procedure DoGetText(Index: Integer; var AText: string); virtual;
property LimitToClientWidth: Boolean read GetLimitToClientWidth;
property MaxWidth: Integer read FMaxWidth write SetMaxWidth;
property ScrollBars: TScrollStyle read FScrollBars write SetScrollBars default ssBoth;
property Sorted: Boolean read FSorted write SetSorted default False;
property OnGetText: TJvListBoxDataEvent read FOnGetText write FOnGetText;
property Alignment: TAlignment read FAlignment write SetAlignment
default taLeftJustify;
property HotTrack: Boolean read FHotTrack write SetHotTrack default False;
property OnSelectCancel: TNotifyEvent read FOnSelectCancel write FOnSelectCancel;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnDeleteString: TJvListboxChange read FOnDeleteString write FOnDeleteString;
property OnAddString: TJvListboxChange read FOnAddString write FOnAddString;
property OnVerticalScroll: TJvScrollEvent read FOnVerticalScroll write FOnVerticalScroll;
property OnHorizontalScroll: TJvScrollEvent read FOnHorizontalScroll write FOnHorizontalScroll;
{$IFDEF CLR}
// access protected members across assembly borders
function DoGetData(const Index: Integer): string;
function DoGetDataObject(const Index: Integer): TObject;
function GetItemData(Index: Integer): TObject; override;
function InternalGetItemData(Index: Integer): TObject; override;
procedure InternalSetItemData(Index: Integer; AData: TObject); override;
procedure SetItemData(Index: Integer; AData: TObject); override;
procedure ResetContent; override;
procedure DeleteString(Index: Integer); override;
function DoFindData(const Data: String): Integer;
property Style;
{$ENDIF CLR}
property Moving: Boolean read FMoving write FMoving;
property DragIndex: Integer read FDragIndex;
property DragImages: TDragImageList read GetDragImages;
procedure WndProc(var Msg: TMessage); override;
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateWnd; override;
procedure DestroyWnd; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function ItemRect(Index: Integer): TRect;
function ItemsShowing: TStrings; virtual;
{$IFNDEF CLR}
procedure MeasureProviderItem(Index, WidthAvail: Integer; var ASize: TSize);
{$ENDIF !CLR}
procedure MeasureString(const S: string; WidthAvail: Integer; var ASize: TSize);
procedure DefaultDrawItem(Index: Integer; ARect: TRect;
State: TOwnerDrawState); virtual;
procedure DefaultDragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); virtual;
procedure DefaultStartDrag(var DragObject: TDragObject); virtual;
procedure DefaultDragDrop(Source: TObject; X, Y: Integer); virtual;
procedure CreateDragImage(const S: string);
procedure UpdateHorizontalExtent;
function SearchExactString(const Value: string; CaseSensitive: Boolean = True;
StartIndex: Integer = -1): Integer;
function SearchPrefix(const Value: string; CaseSensitive: Boolean = True;
StartIndex: Integer = -1): Integer;
function SearchSubString(const Value: string; CaseSensitive: Boolean = True;
StartIndex: Integer = -1): Integer;
function DeleteExactString(const Value: string; All: Boolean;
CaseSensitive: Boolean = True): Integer;
procedure DragDrop(Source: TObject; X, Y: Integer); override;
function GetDragImages: TDragImageList; override;
procedure SelectAll; {$IFDEF COMPILER6_UP} override; {$ENDIF}
procedure UnselectAll;
procedure InvertSelection;
procedure MoveSelectedUp; virtual;
procedure MoveSelectedDown; virtual;
procedure DeleteSelected; {$IFDEF COMPILER6_UP} override; {$ELSE} virtual; {$ENDIF}
procedure DeleteAllButSelected;
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer;
AHeight: Integer); override;
protected
property MultiLine: Boolean read FMultiline write SetMultiline default False;
property SelectedColor: TColor read FSelectedColor write SetSelectedColor default clHighlight;
property SelectedTextColor: TColor read FSelectedTextColor write SetSelectedTextColor default clHighlightText;
property DisabledTextColor: TColor read FDisabledTextColor write SetDisabledTextColor default clGrayText;
property ShowFocusRect: Boolean read FShowFocusRect write SetShowFocusRect default True;
property Background: TJvListBoxBackground read FBackground write SetBackground;
property Flat: Boolean read GetFlat write SetFlat default False;
property ParentFlat: Boolean read GetParentFlat write SetParentFlat default True;
end;
TJvListBox = class(TJvCustomListBox)
public
{$IFDEF COMPILER6_UP}
property Count;
{$ENDIF COMPILER6_UP}
published
property Align;
property Anchors;
property BiDiMode;
property BorderStyle;
property Color;
property Columns;
property Constraints;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property ExtendedSelect;
property Font;
property ImeMode;
property ImeName;
property IntegralHeight;
property ItemHeight;
property Items;
property MultiLine;
property SelectedColor;
property SelectedTextColor;
property DisabledTextColor;
property ShowFocusRect;
property Background;
property Flat;
property ParentFlat;
property MultiSelect;
property ParentBiDiMode;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
{$IFNDEF CLR}
property Provider;
{$ENDIF !CLR}
property ScrollBars;
property ShowHint;
property Sorted;
property Style;
property TabOrder;
property TabStop;
property TabWidth;
property Visible;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnDrawItem;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnGetText;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMeasureItem;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDock;
property OnStartDrag;
property Alignment;
property HotTrack;
property HintColor;
property OnMouseEnter;
property OnMouseLeave;
property OnParentColorChange;
property OnSelectCancel;
property OnChange;
property OnDeleteString;
property OnAddString;
property OnVerticalScroll;
property OnHorizontalScroll;
end;
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/branches/JVCL3_36_PREPARATION/run/JvListBox.pas $';
Revision: '$Revision: 11893 $';
Date: '$Date: 2008-09-09 22:45:14 +0200 (mar., 09 sept. 2008) $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
implementation
uses
Consts, TypInfo,
{$IFDEF COMPILER10_UP}
Types,
{$ENDIF COMPILER10_UP}
{$IFDEF HAS_UNIT_RTLCONSTS}
RTLConsts,
{$ENDIF HAS_UNIT_RTLCONSTS}
JclBase,
JvJCLUtils, JvJVCLUtils, JvConsts, JvCtrls, JvResources;
const
AlignFlags: array [TAlignment] of DWORD = (DT_LEFT, DT_RIGHT, DT_CENTER);
type
PStrings = ^TStrings;
//=== { TJvListBoxStrings } ==================================================
constructor TJvListBoxStrings.Create;
begin
inherited Create;
FInternalList := TStringList.Create;
end;
destructor TJvListBoxStrings.Destroy;
begin
FreeAndNil(FInternalList);
inherited Destroy;
end;
function TJvListBoxStrings.Get(Index: Integer): string;
var
Len: Integer;
begin
if UseInternal then
Result := InternalList[Index]
else
{$IFDEF COMPILER6_UP}
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then
Result := ListBox.DoGetData(Index)
else
{$ENDIF COMPILER6_UP}
begin
Len := SendMessage(ListBox.Handle, LB_GETTEXTLEN, Index, 0);
if Len = LB_ERR then
Error(SListIndexError, Index);
SetLength(Result, Len);
if Len <> 0 then
begin
{$IFDEF CLR}
SendGetTextMessage(ListBox.Handle, LB_GETTEXT, Index, Result, Len);
{$ELSE}
Len := SendMessage(ListBox.Handle, LB_GETTEXT, Index, Longint(PChar(Result)));
SetLength(Result, Len);
{$ENDIF CLR}
end;
end;
end;
function TJvListBoxStrings.GetCount: Integer;
begin
if (DestroyCount > 0) and UseInternal then
Result := 0
else
begin
if UseInternal then
Result := InternalList.Count
else
Result := SendMessage(ListBox.Handle, LB_GETCOUNT, 0, 0);
end;
end;
function TJvListBoxStrings.GetObject(Index: Integer): TObject;
begin
if UseInternal then
Result := InternalList.Objects[Index]
else
{$IFDEF COMPILER6_UP}
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then
Result := ListBox.DoGetDataObject(Index)
else
{$ENDIF COMPILER6_UP}
begin
Result := TObject(ListBox.GetItemData(Index));
if Longint(Result) = LB_ERR then
Error(SListIndexError, Index);
end;
end;
procedure TJvListBoxStrings.Put(Index: Integer; const S: string);
var
I: Integer;
{$IFDEF CLR}
TempData: TObject;
{$ELSE}
TempData: Longint;
{$ENDIF CLR}
begin
if UseInternal then
InternalList[Index] := S
else
begin
ListBox.DeselectProvider;
I := ListBox.ItemIndex;
TempData := ListBox.InternalGetItemData(Index);
// Set the Item to 0 in case it is an object that gets freed during Delete
ListBox.InternalSetItemData(Index, {$IFDEF CLR} nil {$ELSE} 0 {$ENDIF});
Delete(Index);
InsertObject(Index, S, nil);
ListBox.InternalSetItemData(Index, TempData);
ListBox.ItemIndex := I;
end;
end;
procedure TJvListBoxStrings.PutObject(Index: Integer; AObject: TObject);
begin
if UseInternal then
InternalList.Objects[Index] := AObject
else
begin
if (Index <> -1) {$IFDEF COMPILER6_UP} and not (ListBox.Style in [lbVirtual, lbVirtualOwnerDraw]) {$ENDIF} then
begin
ListBox.DeselectProvider;
{$IFDEF CLR}
ListBox.SetItemData(Index, AObject);
{$ELSE}
ListBox.SetItemData(Index, Longint(AObject));
{$ENDIF CLR}
end;
end;
end;
procedure TJvListBoxStrings.SetUpdateState(Updating: Boolean);
begin
FUpdating := Updating;
if ListBox.HandleAllocated then
begin
SendMessage(ListBox.Handle, WM_SETREDRAW, Ord(not Updating), 0);
if not Updating then
ListBox.Refresh;
end;
end;
procedure TJvListBoxStrings.SetWndDestroying(Destroying: Boolean);
begin
if Destroying then
Inc(FDestroyCnt)
else
if FDestroyCnt > 0 then
Dec(FDestroyCnt);
end;
function TJvListBoxStrings.GetListBox: TJvCustomListBox;
begin
Result := FListBox;
end;
procedure TJvListBoxStrings.SetListBox(Value: TJvCustomListBox);
begin
FListBox := Value;
end;
function TJvListBoxStrings.GetInternalList: TStrings;
begin
Result := FInternalList;
end;
function TJvListBoxStrings.Add(const S: string): Integer;
begin
if (csLoading in ListBox.ComponentState) and UseInternal then
Result := InternalList.Add(S)
else
begin
{$IFDEF COMPILER6_UP}
Result := -1;
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then
Exit;
{$ENDIF COMPILER6_UP}
ListBox.DeselectProvider;
{$IFDEF CLR}
Result := SendTextMessage(ListBox.Handle, LB_ADDSTRING, 0, S);
if Result < 0 then
raise EOutOfResources.Create(SInsertLineError);
{$ELSE}
Result := SendMessage(ListBox.Handle, LB_ADDSTRING, 0, Longint(PChar(S)));
if Result < 0 then
raise EOutOfResources.CreateRes(@SInsertLineError);
{$ENDIF CLR}
end;
end;
procedure TJvListBoxStrings.Clear;
begin
if (FDestroyCnt <> 0) and UseInternal then
Exit;
if (csLoading in ListBox.ComponentState) and UseInternal then
InternalList.Clear
else
begin
ListBox.DeselectProvider;
ListBox.ResetContent;
end;
end;
procedure TJvListBoxStrings.Delete(Index: Integer);
begin
if (csLoading in ListBox.ComponentState) and UseInternal then
InternalList.Delete(Index)
else
begin
ListBox.DeselectProvider;
ListBox.DeleteString(Index);
end;
end;
function TJvListBoxStrings.IndexOf(const S: string): Integer;
begin
if UseInternal then
Result := InternalList.IndexOf(S)
else
{$IFDEF COMPILER6_UP}
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then
Result := ListBox.DoFindData(S)
else
{$ENDIF COMPILER6_UP}
{$IFDEF CLR}
Result := SendTextMessage(ListBox.Handle, LB_FINDSTRINGEXACT, -1, S);
{$ELSE}
Result := SendMessage(ListBox.Handle, LB_FINDSTRINGEXACT, -1, Longint(PChar(S)));
{$ENDIF CLR}
end;
procedure TJvListBoxStrings.Insert(Index: Integer; const S: string);
begin
if (csLoading in ListBox.ComponentState) and UseInternal then
InternalList.Insert(Index, S)
else
begin
ListBox.DeselectProvider;
{$IFDEF COMPILER6_UP}
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then
Exit;
{$ENDIF COMPILER6_UP}
{$IFDEF CLR}
if SendTextMessage(ListBox.Handle, LB_INSERTSTRING, Index, S) < 0 then
raise EOutOfResources.Create(SInsertLineError);
{$ELSE}
if SendMessage(ListBox.Handle, LB_INSERTSTRING, Index, Longint(PChar(S))) < 0 then
raise EOutOfResources.CreateRes(@SInsertLineError);
{$ENDIF CLR}
end;
end;
procedure TJvListBoxStrings.Move(CurIndex, NewIndex: Integer);
var
TempString: string;
{$IFDEF CLR}
TempData: TObject;
{$ELSE}
TempData: Longint;
{$ENDIF CLR}
begin
if (csLoading in ListBox.ComponentState) and UseInternal then
InternalList.Move(CurIndex, NewIndex)
else
begin
{$IFDEF COMPILER6_UP}
if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then
Exit;
{$ENDIF COMPILER6_UP}
BeginUpdate;
ListBox.Moving := True;
try
if CurIndex <> NewIndex then
begin
TempString := Get(CurIndex);
TempData := ListBox.InternalGetItemData(CurIndex);
ListBox.InternalSetItemData(CurIndex, {$IFDEF CLR} nil {$ELSE} 0 {$ENDIF});
Delete(CurIndex);
Insert(NewIndex, TempString);
ListBox.InternalSetItemData(NewIndex, TempData);
end;
finally
ListBox.Moving := False;
EndUpdate;
end;
end;
end;
{ Copies the strings at the list box to the FInternalList. To minimize the memory usage when a
large list is used, each item copied is immediately removed from the list box list. }
procedure TJvListBoxStrings.MakeListInternal;
var
Cnt: Integer;
{$IFNDEF CLR}
Text: array [0..4095] of Char;
Len: Integer;
{$ENDIF !CLR}
S: string;
Obj: TObject;
begin
if ListBox.HandleAllocated then
SendMessage(ListBox.Handle, WM_SETREDRAW, Ord(False), 0);
try
InternalList.Clear;
if ListBox.HandleAllocated then
Cnt := SendMessage(ListBox.Handle, LB_GETCOUNT, 0, 0)
else
Cnt := 0;
while Cnt > 0 do
begin
{$IFDEF CLR}
SendGetTextMessage(ListBox.Handle, LB_GETTEXT, 0, S, 4096);
Obj := ListBox.GetItemData(0);
{$ELSE}
Len := SendMessage(ListBox.Handle, LB_GETTEXT, 0, Longint(@Text));
SetString(S, Text, Len);
Obj := TObject(SendMessage(ListBox.Handle, LB_GETITEMDATA, 0, 0));
{$ENDIF CLR}
SendMessage(ListBox.Handle, LB_DELETESTRING, 0, 0);
InternalList.AddObject(S, Obj);
Dec(Cnt);
end;
finally
UseInternal := True;
if not Updating and ListBox.HandleAllocated then
SendMessage(ListBox.Handle, WM_SETREDRAW, Ord(True), 0);
end;
end;
procedure TJvListBoxStrings.ActivateInternal;
var
S: string;
Obj: TObject;
{$IFNDEF CLR}
Index: Integer;
{$ENDIF !CLR}
begin
SendMessage(ListBox.Handle, WM_SETREDRAW, Ord(False), 0);
try
InternalList.BeginUpdate;
try
SendMessage(ListBox.Handle, LB_RESETCONTENT, 0, 0);
while InternalList.Count > 0 do
begin
S := InternalList[0];
Obj := InternalList.Objects[0];
{$IFDEF CLR}
ListBox.AddItem(S, Obj);
{$ELSE}
Index := SendMessage(ListBox.Handle, LB_ADDSTRING, 0, Longint(PChar(S)));
if Index < 0 then
raise EOutOfResources.CreateRes(@SInsertLineError);
SendMessage(ListBox.Handle, LB_SETITEMDATA, Index, Longint(Obj));
{$ENDIF CLR}
InternalList.Delete(0);
end;
finally
InternalList.EndUpdate;
end;
finally
if not Updating then
SendMessage(ListBox.Handle, WM_SETREDRAW, Ord(True), 0);
UseInternal := False;
end;
end;
//=== { TJvCustomListBox } ===================================================
constructor TJvCustomListBox.Create(AOwner: TComponent);
{$IFNDEF CLR}
var
PI: PPropInfo;
PStringsAddr: PStrings;
{$ENDIF !CLR}
begin
inherited Create(AOwner);
// JvBMPListBox:
// Style := lbOwnerDrawFixed;
{$IFNDEF CLR}
FConsumerSvc := TJvDataConsumer.Create(Self, [DPA_RenderDisabledAsGrayed,
DPA_ConsumerDisplaysList]);
FConsumerSvc.OnChanging := ConsumerServiceChanging;
FConsumerSvc.OnChanged := ConsumerServiceChanged;
FConsumerSvc.AfterCreateSubSvc := ConsumerSubServiceCreated;
FConsumerStrings := TJvConsumerStrings.Create(FConsumerSvc);
{ The following hack assumes that TJvListBox.Items reads directly from the private FItems field
of TCustomListBox and that TJvListBox.Items is actually published.
What we do here is remove the original string list used and place our own version in it's place.
This would give us the benefit of keeping the list of strings (and objects) even if a provider
is active and the list box windows has no strings at all. }
PI := GetPropInfo(TJvListBox, 'Items');
PStringsAddr := Pointer(Integer(PI.GetProc) and $00FFFFFF + Integer(Self));
Items.Free; // remove original item list (TListBoxStrings instance)
PStringsAddr^ := GetItemsClass.Create; // create our own implementation and put it in place.
{$ELSE} // CLR=True
Items.Free; // remove original item list (TListBoxStrings instance)
SetNonPublicField(Self, 'FItems', GetItemsClass.Create); // create our own implementation and put it in place.
{$ENDIF !CLR}
TJvListBoxStrings(Items).ListBox := Self; // link it to the list box.
FBackground := TJvListBoxBackground.Create;
FBackground.OnChange := DoBackgroundChange;
FScrollBars := ssBoth;
FAlignment := taLeftJustify;
FMultiline := False;
FSelectedColor := clHighlight;
FSelectedTextColor := clHighlightText;
FDisabledTextColor := clGrayText;
FShowFocusRect := True;
// Style := lbOwnerDrawVariable;
FMaxWidth := 0;
FHotTrack := False;
// ControlStyle := ControlStyle + [csAcceptsControls];
end;
destructor TJvCustomListBox.Destroy;
begin
FreeAndNil(FBackground);
{$IFNDEF CLR}
FreeAndNil(FConsumerStrings);
FreeAndNil(FConsumerSvc);
{$ENDIF !CLR}
inherited Destroy;
end;
function TJvCustomListBox.GetItemsClass: TJvListBoxStringsClass;
begin
Result := TJvListBoxStrings;
end;
{$IFDEF CLR}
function TJvCustomListBox.DoGetData(const Index: Integer): string;
begin
Result := inherited DoGetData(Index);
end;
function TJvCustomListBox.DoGetDataObject(const Index: Integer): TObject;
begin
Result := inherited DoGetDataObject(Index);
end;
function TJvCustomListBox.GetItemData(Index: Integer): TObject;
begin
Result := inherited GetItemData(Index);
end;
function TJvCustomListBox.InternalGetItemData(Index: Integer): TObject;
begin
Result := inherited InternalGetItemData(Index);
end;
procedure TJvCustomListBox.InternalSetItemData(Index: Integer; AData: TObject);
begin
inherited InternalSetItemData(Index, AData);
end;
procedure TJvCustomListBox.SetItemData(Index: Integer; AData: TObject);
begin
inherited SetItemData(Index, AData);
end;
procedure TJvCustomListBox.ResetContent;
begin
inherited ResetContent;
end;
procedure TJvCustomListBox.DeleteString(Index: Integer);
begin
inherited DeleteString(Index);
end;
function TJvCustomListBox.DoFindData(const Data: String): Integer;
begin
Result := inherited DoFindData(Data);
end;
{$ENDIF CLR}
procedure TJvCustomListBox.BeginRedraw;
begin
SendMessage(Handle, WM_SETREDRAW, Ord(False), 0);
end;
procedure TJvCustomListBox.Changed;
begin
// (rom) TODO?
inherited Changed; // (marcelb): I added this, 'caus I assume it needs to be called.
end;
procedure TJvCustomListBox.FontChanged;
const
CShowFocusRect: array [Boolean] of Integer = (0, 2);
begin
inherited FontChanged;
Canvas.Font := Font;
if Style <> lbStandard then
ItemHeight := CanvasMaxTextHeight(Canvas) + CShowFocusRect[ShowFocusRect];
RemeasureAll;
end;
procedure TJvCustomListBox.MouseEnter(Control: TControl);
begin
if csDesigning in ComponentState then
Exit;
if not MouseOver then
begin
if FHotTrack then
Ctl3D := True;
inherited MouseEnter(Control);
end;
end;
procedure TJvCustomListBox.MouseLeave(Control: TControl);
begin
if MouseOver then
begin
if FHotTrack then
Ctl3D := False;
inherited MouseLeave(Control);
end;
end;
{ This routine is copied mostly from TCustomListbox.CNDrawItem.
The setting of colors is modified.
Drawing of the focus rectangle is delegated to DrawItem.}
procedure TJvCustomListBox.CNDrawItem(var Msg: TWMDrawItem);
var
State: TOwnerDrawState;
begin
with Msg.DrawItemStruct{$IFNDEF CLR}^{$ENDIF} do
begin
State := TOwnerDrawState(Word(itemState and $FFFF));
Canvas.Handle := hDC;
Canvas.Font := Font;
Canvas.Brush := Brush;
if Integer(itemID) >= 0 then
begin
if odSelected in State then
begin
Canvas.Brush.Color := FSelectedColor;
Canvas.Font.Color := FSelectedTextColor;
end;
if (([odDisabled, odGrayed] * State) <> []) or not Enabled then
Canvas.Font.Color := FDisabledTextColor;
end;
if Integer(itemID) >= 0 then
DrawItem(itemID, rcItem, State)
else
begin
if Background.DoDraw then
begin
Perform(WM_ERASEBKGND, Canvas.Handle, 0);
if odFocused in State then
DrawFocusRect(hDC, rcItem);
end
else
begin
Canvas.FillRect(rcItem);
if odFocused in State then
DrawFocusRect(hDC, rcItem);
end;
end;
Canvas.Handle := 0;
end;
end;
procedure TJvCustomListBox.CNKeyDown(var Msg: TWMKeyDown);
begin
if Background.DoDraw and (Msg.Result = 0) and
(Msg.CharCode in [VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN]) then
begin
BeginRedraw;
try
inherited;
finally
EndRedraw;
end;
end
else
inherited;
end;
procedure TJvCustomListBox.CreateDragImage(const S: string);
const
CLeftMargin = 15;
var
Size: TSize;
Bmp: TBitmap;
SizeRect: TRect;
begin
if not Assigned(FDragImage) then
FDragImage := TDragImageList.Create(Self)
else
FDragImage.Clear;
Canvas.Font := Font;
if MultiLine then
begin
SizeRect := Rect(0, 0, MaxInt, 0);
DrawText(Canvas.Handle, {$IFDEF CLR} S {$ELSE} PChar(S) {$ENDIF}, -1, SizeRect, DT_CALCRECT or
DrawTextBiDiModeFlags(DT_WORDBREAK or DT_NOPREFIX or AlignFlags[FAlignment]));
Size.cx := SizeRect.Right;
Size.cy := SizeRect.Bottom;
end
else
Size := Canvas.TextExtent(S);
{$IFDEF CLR}
Inc(Size.Width, CLeftMargin);
{$ELSE}
Inc(Size.cx, CLeftMargin);
{$ENDIF CLR}
FDragImage.Width := Size.cx;
FDragImage.Height := Size.cy;
Bmp := TBitmap.Create;
try
Bmp.Width := Size.cx;
Bmp.Height := Size.cy;
Bmp.Canvas.Font := Font;
Bmp.Canvas.Font.Color := clBlack;
Bmp.Canvas.Brush.Color := clWhite;
Bmp.Canvas.Brush.Style := bsSolid;
if MultiLine then
begin
Inc(SizeRect.Right, CLeftMargin);
Bmp.Canvas.FillRect(SizeRect);
Inc(SizeRect.Left, CLeftMargin);
DrawText(Bmp.Canvas.Handle, {$IFDEF CLR} S {$ELSE} PChar(S) {$ENDIF}, -1, SizeRect,
DrawTextBiDiModeFlags(DT_WORDBREAK or DT_NOPREFIX or AlignFlags[FAlignment]));
end
else
Bmp.Canvas.TextOut(CLeftMargin, 0, S);
FDragImage.AddMasked(Bmp, clWhite);
finally
Bmp.Free;
end;
ControlStyle := ControlStyle + [csDisplayDragImage];
end;
procedure TJvCustomListBox.CreateParams(var Params: TCreateParams);
const
ScrollBar: array [TScrollStyle] of DWORD =
(0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL or WS_VSCROLL);
Sorted: array [Boolean] of DWORD =
(0, LBS_SORT);
begin
inherited CreateParams(Params);
with Params do
begin
Style := Style and not (WS_HSCROLL or WS_VSCROLL) or ScrollBar[FScrollBars] or
Sorted[FSorted];
end;
if IsProviderSelected then
begin
Params.Style := Params.Style and not (LBS_SORT or LBS_HASSTRINGS or LBS_NODATA);
if Params.Style and (LBS_OWNERDRAWVARIABLE or LBS_OWNERDRAWFIXED) = 0 then
Params.Style := Params.Style or LBS_OWNERDRAWFIXED;
end;
end;
procedure TJvCustomListBox.CreateWnd;
begin
if not (csLoading in ComponentState) then
begin
FMultiline := MultiLine and (Style = lbOwnerDrawVariable);
if not (Style in [lbOwnerDrawVariable, lbOwnerDrawFixed]) then
FAlignment := taLeftJustify;
end;
FLeftPosition := 0;
inherited CreateWnd;
UpdateItemCount;
UpdateHorizontalExtent;
end;
procedure TJvCustomListBox.DestroyWnd;
begin
if IsProviderSelected then
TJvListBoxStrings(Items).SetWndDestroying(True);
try
inherited DestroyWnd;
finally
if IsProviderSelected then
TJvListBoxStrings(Items).SetWndDestroying(False);
end;
end;
procedure TJvCustomListBox.DefaultDragDrop(Source: TObject;
X, Y: Integer);
var
DropIndex, Ti: Integer;
S: string;
Obj: TObject;
begin
if not IsProviderSelected and (Source = Self) then
begin
S := Items[FDragIndex];
Obj := Items.Objects[FDragIndex];
DropIndex := ItemAtPos(Point(X, Y), True);
Ti := TopIndex;
if DropIndex > FDragIndex then
Dec(DropIndex);
Items.Delete(FDragIndex);
if DropIndex < 0 then
Items.AddObject(S, Obj)
else
Items.InsertObject(DropIndex, S, Obj);
TopIndex := Ti;
end;
end;
procedure TJvCustomListBox.DefaultDragOver(Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := not IsProviderSelected and (Source = Self);
if Accept then
begin
// Handle autoscroll in the "hot zone" 5 pixels from top or bottom of
// client area
if (Y < 5) or ((ClientHeight - Y) <= 5) then
begin
FDragImage.HideDragImage;
try
if Y < 5 then
begin
Perform(WM_VSCROLL, SB_LINEUP, 0);
Perform(WM_VSCROLL, SB_ENDSCROLL, 0);
end
else
if (ClientHeight - Y) <= 5 then
begin
Perform(WM_VSCROLL, SB_LINEDOWN, 0);
Perform(WM_VSCROLL, SB_ENDSCROLL, 0);
end
finally
FDragImage.ShowDragImage;
end;
end;
// i := ItemAtPos(Point(X,Y),true);
// if i > -1 then ItemIndex := i;
end;
end;
{ This procedure is a slightly modified version of TCustomListbox.DrawItem! }
procedure TJvCustomListBox.DefaultDrawItem(Index: Integer; ARect: TRect;
State: TOwnerDrawState);
const
AlignFlags: array [TAlignment] of DWORD =
(DT_LEFT, DT_RIGHT, DT_CENTER);
var
Flags: Longint;
ActualRect: TRect;
AText: string;
begin
if csDestroying in ComponentState then
Exit;
// JvBMPListBox:
// draw text transparently
if ScrollBars in [ssHorizontal, ssBoth] then
begin
if FMaxWidth < ClientWidth then
ActualRect := Rect(0, ARect.Top, ClientWidth, ARect.Bottom)
else
ActualRect := Rect(0, ARect.Top, FMaxWidth, ARect.Bottom);
end
else
ActualRect := ARect;
if Background.DoDraw then
begin
Canvas.Brush.Style := bsClear;
// always use font color, CNDrawItem sets it to clHighlitetext for
// selected items.
Canvas.Font.Color := Font.Color;
// The listbox does not erase the background for the item before
// sending the WM_DRAWITEM message! We have to do that here manually.
SaveDC(Canvas.Handle);
IntersectClipRect(Canvas.Handle, ActualRect.Left, ActualRect.Top, ActualRect.Right, ActualRect.Bottom);
DrawBackGround(Canvas.Handle, True);
RestoreDC(Canvas.Handle, -1);
end;
if Index < ItemsShowing.Count then
begin
if not Background.DoDraw then
Canvas.FillRect(ActualRect);
if FMultiline then
Flags := DrawTextBiDiModeFlags(DT_WORDBREAK or DT_NOPREFIX or
AlignFlags[FAlignment])
else
Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX or
AlignFlags[FAlignment]);
if not UseRightToLeftAlignment then
Inc(ActualRect.Left, 2)
else
Dec(ActualRect.Right, 2);
if IsProviderSelected then
{$IFNDEF CLR}
DrawProviderItem(Canvas, ActualRect, Index, State)
{$ENDIF !CLR}
else
begin
AText := ItemsShowing[Index];
DoGetText(Index, AText);
DrawText(Canvas.Handle, {$IFDEF CLR} AText {$ELSE} PChar(AText) {$ENDIF},
Length(AText), ActualRect, Flags);
end;
//if (Index >= 0) and (Index < Items.Count) then
// Canvas.TextOut(ActualRect.Left + 2, ActualRect.Top, Items[Index]);
// invert the item if selected
if Background.DoDraw and (odSelected in State) then
InvertRect(Canvas.Handle, ActualRect);
// no need to draw focus rect, CNDrawItem does that for us
end;
end;
procedure TJvCustomListBox.DefaultStartDrag(var DragObject: TDragObject);
begin
FDragIndex := ItemIndex;
if FDragIndex >= Items.Count then
FDragIndex := Items.Count-1;
if not IsProviderSelected and (FDragIndex >= 0) then
CreateDragImage(Items[FDragIndex])
else
CancelDrag;
end;
procedure TJvCustomListBox.DeleteAllButSelected;
var
I: Integer;
begin
if not IsProviderSelected and MultiSelect then
begin
I := 0;
while I < Items.Count do
if not Selected[I] then
Items.Delete(I)
else
Inc(I);
Changed;
end;
end;
function TJvCustomListBox.DeleteExactString(const Value: string; All: Boolean;
CaseSensitive: Boolean): Integer;
begin
if not IsProviderSelected then
begin
Result := TJvItemsSearchs.DeleteExactString(Items, Value, CaseSensitive);
Changed;
end
else
Result := 0;
end;
procedure TJvCustomListBox.DeleteSelected;
var
I: Integer;
begin
if not IsProviderSelected then
begin
if MultiSelect then
begin
for I := Items.Count - 1 downto 0 do
if Selected[I] then
Items.Delete(I);
end
else
if ItemIndex <> -1 then
begin
I := ItemIndex;
Items.Delete(I);
if I > 0 then
Dec(I);
if Items.Count > 0 then
ItemIndex := I;
end;
Changed;
end;
end;
procedure TJvCustomListBox.DoBackgroundChange(Sender: TObject);
begin
UpdateStyle;
Invalidate;
end;
procedure TJvCustomListBox.DoStartDrag(var DragObject: TDragObject);
begin
if Assigned(OnStartDrag) then
inherited DoStartDrag(DragObject)
else
DefaultStartDrag(DragObject);
end;
procedure TJvCustomListBox.DragDrop(Source: TObject; X, Y: Integer);
begin
if Assigned(OnDragDrop) then
inherited DragDrop(Source, X, Y)
else
DefaultDragDrop(Source, X, Y);
end;
procedure TJvCustomListBox.DragOver(Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if Assigned(OnDragOver) then
inherited DragOver(Source, X, Y, State, Accept)
else
DefaultDragOver(Source, X, Y, State, Accept);
end;
procedure TJvCustomListBox.DrawBackGround(ADC: HDC; const DoOffSet: Boolean);
var
ImageRect, ClipBox, ClientRect, Temp: TRect;
Canvas: TCanvas;
ClipComplexity: Integer;
begin
if (ADC = 0) or not Background.DoDraw or (csDestroying in ComponentState) then
Exit;
ClientRect := Self.ClientRect;
ClipComplexity := GetClipBox(ADC, ClipBox);
if ClipComplexity = NULLREGION then
Exit; // nothing to paint
if ClipComplexity = Windows.ERROR then
ClipBox := ClientRect;
if DoOffSet then
OffsetRect(ClientRect, FLeftPosition, 0);
Canvas := TCanvas.Create;
try
Canvas.Handle := ADC;
if Canvas.Handle = 0 then
Exit;
if Background.FillMode = bfmStretch then
Canvas.StretchDraw(ClientRect, Background.Image)
else
begin
ImageRect := Background.Image.Canvas.ClipRect;
while ImageRect.Top < ClientRect.Bottom do
begin
while ImageRect.Left < ClientRect.Right do
begin
if IntersectRect(Temp, ClipBox, ImageRect) then
Canvas.Draw(ImageRect.Left, ImageRect.Top, Background.Image);
OffsetRect(ImageRect, ImageRect.Right - ImageRect.Left, 0);
end;
OffsetRect(ImageRect, -ImageRect.Left,
ImageRect.Bottom - ImageRect.Top);
end;
end;
finally
Canvas.Handle := 0;
Canvas.Free;
end;
end;
procedure TJvCustomListBox.DrawItem(Index: Integer; Rect: TRect;
State: TOwnerDrawState);
begin
if csDestroying in ComponentState then
Exit;
if Assigned(OnDrawItem) then
inherited DrawItem(Index, Rect, State)
else
begin
{ Call the drawing code. This is isolated in its own public routine
so a OnDrawItem handler can use it, too. }
DefaultDrawItem(Index, Rect, State);
if FShowFocusRect and (odFocused in State) then
Canvas.DrawFocusRect(Rect);
end;
end;
procedure TJvCustomListBox.EndRedraw;
var
R: TRect;
begin
SendMessage(Handle, WM_SETREDRAW, Ord(True), 0);
R := Rect(0, 0, Width, Height);
Windows.InvalidateRect(Handle, {$IFNDEF CLR}@{$ENDIF}R, True);
end;
{$IFNDEF CLR}
procedure TJvCustomListBox.SetConsumerService(Value: TJvDataConsumer);
begin
end;
procedure TJvCustomListBox.ConsumerServiceChanging(Sender: TJvDataConsumer;
Reason: TJvDataConsumerChangeReason);
begin
{ If we're changing providers, make sure a list box is created; this will post the saved list back
now instead of after a provider is assigned (which will then be deselected again as the string
list is changed). }
if (Reason = ccrProviderSelect) and not (csDestroying in ComponentState) then
HandleNeeded;
if (Reason = ccrProviderSelect) and IsProviderSelected and not FProviderToggle then
begin
FProviderIsActive := False;
FProviderToggle := True;
end
else
if (Reason = ccrProviderSelect) and not IsProviderSelected and not FProviderToggle and
not TJvListBoxStrings(Items).UseInternal then
TJvListBoxStrings(Items).MakeListInternal;
end;
procedure TJvCustomListBox.ConsumerServiceChanged(Sender: TJvDataConsumer;
Reason: TJvDataConsumerChangeReason);
begin
if (Reason = ccrProviderSelect) and not IsProviderSelected and not FProviderToggle then
begin
FProviderToggle := True;
FProviderIsActive := True;
RecreateWnd;
{ if not TJvListBoxStrings(Items).UseInternal then
begin
TJvListBoxStrings(Items).MakeListInternal;
RecreateWnd;
end;}
end
else
if (Reason = ccrProviderSelect) and not IsProviderSelected and FProviderToggle and
TJvListBoxStrings(Items).UseInternal then
begin
RecreateWnd;
TJvListBoxStrings(Items).ActivateInternal; // apply internal string list to list box
{ end
else
if (Reason = ccrProviderSelect) and IsProviderSelected and not FProviderToggle then
begin
FProviderIsActive := False;
FProviderToggle := True;
TJvListBoxStrings(Items).ActivateInternal; // apply internal string list to list box
RecreateWnd;}
end;
if (not FProviderToggle or (Reason = ccrProviderSelect)) and IsProviderSelected then
begin
UpdateItemCount;
Refresh;
end;
if FProviderToggle and (Reason = ccrProviderSelect) then
FProviderToggle := False;
end;
procedure TJvCustomListBox.ConsumerSubServiceCreated(Sender: TJvDataConsumer;
SubSvc: TJvDataConsumerAggregatedObject);
var
VL: IJvDataConsumerViewList;
begin
if SubSvc.GetInterface(IJvDataConsumerViewList, VL) then
begin
VL.ExpandOnNewItem := True;
VL.AutoExpandLevel := -1;
VL.RebuildView;
end;
end;
{$ENDIF !CLR}
function TJvCustomListBox.IsProviderSelected: Boolean;
begin
Result := FProviderIsActive;
end;
function TJvCustomListBox.IsProviderToggle: Boolean;
begin
Result := FProviderToggle;
end;
procedure TJvCustomListBox.DeselectProvider;
begin
{$IFNDEF CLR}
Provider.Provider := nil;
{$ENDIF !CLR}
end;
procedure TJvCustomListBox.UpdateItemCount;
var
VL: IJvDataConsumerViewList;
Cnt: Integer;
EmptyChr: Char;
begin
if HandleAllocated and IsProviderSelected
{$IFNDEF CLR} and Supports(Provider as IJvDataConsumer, IJvDataConsumerViewList, VL) {$ENDIF} then
begin
Cnt := VL.Count - SendMessage(Handle, LB_GETCOUNT, 0, 0);
EmptyChr := #0;
while Cnt > 0 do
begin
{$IFDEF CLR}
SendTextMessage(Handle, LB_ADDSTRING, 0, EmptyChr);
{$ELSE}
SendMessage(Handle, LB_ADDSTRING, 0, LParam(@EmptyChr));
{$ENDIF CLR}
Dec(Cnt);
end;
while Cnt < 0 do
begin
SendMessage(Handle, LB_DELETESTRING, 0, 0);
Inc(Cnt);
end;
end;
end;
procedure TJvCustomListBox.LBFindString(var Msg: TMessage);
begin
if IsProviderSelected then
{$IFDEF CLR}
Msg.Result := SearchPrefix(TWMSetText.Create(Msg).Text, False, Msg.WParam)
{$ELSE}
Msg.Result := SearchPrefix(PChar(Msg.LParam), False, Msg.WParam)
{$ENDIF CLR}
else
inherited;
end;
procedure TJvCustomListBox.LBFindStringExact(var Msg: TMessage);
begin
if IsProviderSelected then
{$IFDEF CLR}
Msg.Result := SearchExactString(TWMSetText.Create(Msg).Text, False, Msg.WParam)
{$ELSE}
Msg.Result := SearchExactString(PChar(Msg.LParam), False, Msg.WParam)
{$ENDIF CLR}
else
inherited;
end;
procedure TJvCustomListBox.LBSelectString(var Msg: TMessage);
begin
if IsProviderSelected then
begin
{$IFDEF CLR}
Msg.Result := SearchExactString(TWMSetText.Create(Msg).Text, False, Msg.WParam);
{$ELSE}
Msg.Result := SearchExactString(PChar(Msg.LParam), False, Msg.WParam);
{$ENDIF CLR}
if Msg.Result > 0 then
Perform(LB_SETCURSEL, Msg.Result, 0);
end
else
inherited;
end;
procedure TJvCustomListBox.LBGetText(var Msg: TMessage);
begin
{$IFNDEF CLR}
if IsProviderSelected then
begin
if (Msg.WParam >= 0) and (Msg.WParam < ConsumerStrings.Count) then
begin
StrCopy(PChar(Msg.LParam), PChar(ConsumerStrings[Msg.WParam]));
Msg.Result := StrLen(PChar(Msg.LParam));
end
else
Msg.Result := LB_ERR;
end
else
{$ENDIF !CLR}
inherited;
end;
procedure TJvCustomListBox.LBGetTextLen(var Msg: TMessage);
begin
{$IFNDEF CLR}
if IsProviderSelected then
begin
if (Msg.WParam >= 0) and (Msg.WParam < ConsumerStrings.Count) then
Msg.Result := Length(ConsumerStrings[Msg.WParam])
else
Msg.Result := LB_ERR;
end
else
{$ENDIF !CLR}
inherited;
end;
function TJvCustomListBox.GetDragImages: TDragImageList;
begin
Result := FDragImage;
end;
function TJvCustomListBox.GetFlat: Boolean;
begin
Result := not Ctl3D;
end;
function TJvCustomListBox.GetLimitToClientWidth: Boolean;
begin
Result := FMultiline and (ScrollBars in [ssNone, ssVertical]);
end;
function TJvCustomListBox.GetParentFlat: Boolean;
begin
Result := ParentCtl3D;
end;
procedure TJvCustomListBox.InvertSelection;
var
I: Integer;
begin
if MultiSelect then
begin
ItemsShowing.BeginUpdate;
for I := 0 to ItemsShowing.Count - 1 do
Selected[I] := not Selected[I];
ItemsShowing.EndUpdate;
end;
end;
procedure TJvCustomListBox.LBAddString(var Msg: TMessage);
var
LSize: TSize;
begin
{ (rb) Because TJvDirectoryListBox displays shorter strings than it stores in
it's Items property - ie it stores the complete path, displays only
the last part of a directory - the following code will cause the
TJvCustomListBox think that the size of the strings are bigger than
they really are (thus you probably will see a horizontal scroll bar)
}
if not LimitToClientWidth then
begin
{$IFDEF CLR}
MeasureString(TWMSetText.Create(Msg).Text, 0, LSize);
{$ELSE}
MeasureString(PChar(Msg.LParam), 0, LSize);
{$ENDIF CLR}
if LSize.cx > FMaxWidth then
SetMaxWidth(LSize.cx);
end;
inherited;
if Assigned(FOnAddString) then
{$IFDEF CLR}
FOnAddString(Self, TWMSetText.Create(Msg).Text);
{$ELSE}
FOnAddString(Self, StrPas(PChar(Msg.LParam)));
{$ENDIF CLR}
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TJvCustomListBox.LBDeleteString(var Msg: TMessage);
var
LSize: TSize;
InheritedCalled: Boolean;
begin
InheritedCalled := False;
if not LimitToClientWidth then
begin
if Msg.WParam < ItemsShowing.Count then
MeasureString(ItemsShowing[Msg.WParam], 0, LSize)
else
LSize.cx := FMaxWidth;
InheritedCalled := LSize.cx = FMaxWidth;
if InheritedCalled then
begin
inherited;
RemeasureAll;
end;
end;
if (Msg.WParam < ItemsShowing.Count) and Assigned(FOnDeleteString) then
FOnDeleteString(Self, ItemsShowing.Strings[Msg.WParam]);
if not InheritedCalled then
inherited;
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TJvCustomListBox.LBInsertString(var Msg: TMessage);
var
LSize: TSize;
begin
if not LimitToClientWidth then
begin
{$IFDEF CLR}
MeasureString(TWMSetText.Create(Msg).Text, 0, LSize);
{$ELSE}
MeasureString(PChar(Msg.LParam), 0, LSize);
{$ENDIF CLR}
if LSize.cx > FMaxWidth then
SetMaxWidth(LSize.cx);
end;
inherited;
end;
procedure TJvCustomListBox.Loaded;
begin
inherited Loaded;
UpdateStyle;
end;
{$IFNDEF CLR}
procedure TJvCustomListBox.DrawProviderItem(Canvas: TCanvas; Rect: TRect; Index: Integer;
State: TOwnerDrawState);
var
DrawState: TProviderDrawStates;
VL: IJvDataConsumerViewList;
Item: IJvDataItem;
ItemsRenderer: IJvDataItemsRenderer;
ItemRenderer: IJvDataItemRenderer;
ItemText: IJvDataItemText;
AText: string;
begin
DrawState := DP_OwnerDrawStateToProviderDrawState(State);
if not Enabled then
DrawState := DrawState + [pdsDisabled, pdsGrayed];
Provider.Enter;
try
if Supports(Provider as IJvDataConsumer, IJvDataConsumerViewList, VL) then
begin
Item := VL.Item(Index);
if Item <> nil then
begin
Inc(Rect.Left, VL.ItemLevel(Index) * VL.LevelIndent);
if Supports(Item, IJvDataItemRenderer, ItemRenderer) then
ItemRenderer.Draw(Canvas, Rect, DrawState)
else
if DP_FindItemsRenderer(Item, ItemsRenderer) then
ItemsRenderer.DrawItem(Canvas, Rect, Item, DrawState)
else
if Supports(Item, IJvDataItemText, ItemText) then
begin
AText := ItemText.Text;
DoGetText(Index,AText);
Canvas.TextRect(Rect, Rect.Left, Rect.Top, AText);
end
else
begin
AText := RsDataItemRenderHasNoText;
DoGetText(Index,AText);
Canvas.TextRect(Rect, Rect.Left, Rect.Top, AText);
end;
end;
end;
finally
Provider.Leave;
end;
end;
{$ENDIF !CLR}
procedure TJvCustomListBox.DoGetText(Index: Integer; var AText: string);
begin
if Assigned(FOnGetText) then
FOnGetText(Self, Index, AText);
end;
procedure TJvCustomListBox.MeasureItem(Index: Integer;
var Height: Integer);
var
AvailWidth: Integer;
LSize: TSize;
begin
if Assigned(OnMeasureItem) or (not MultiLine and not IsProviderSelected) or
(Index < 0) or (Index >= ItemsShowing.Count) then
inherited MeasureItem(Index, Height)
else
begin
if LimitToClientWidth then
AvailWidth := ClientWidth
else
AvailWidth := MaxInt;
{$IFNDEF CLR}
if IsProviderSelected then
MeasureProviderItem(Index, AvailWidth, LSize)
else
{$ENDIF !CLR}
MeasureString(ItemsShowing[Index], AvailWidth, LSize);
Height := LSize.cy;
end;
end;
{$IFNDEF CLR}
procedure TJvCustomListBox.MeasureProviderItem(Index, WidthAvail: Integer; var ASize: TSize);
var
VL: IJvDataConsumerViewList;
Item: IJvDataItem;
ItemsRenderer: IJvDataItemsRenderer;
ItemRenderer: IJvDataItemRenderer;
ItemText: IJvDataItemText;
begin
Canvas.Font := Font;
{ Note: doing the TextHeight unconditionally makes sure the font is properly
selected into the device context. }
ASize.cy := CanvasMaxTextHeight(Canvas);
ASize.cx := ClientWidth - 4;
Provider.Enter;
try
if Supports(Provider as IJvDataConsumer, IJvDataConsumerViewList, VL) then
begin
Item := VL.Item(Index);
if Item <> nil then
begin
if Supports(Item, IJvDataItemRenderer, ItemRenderer) then
ASize := ItemRenderer.Measure(Canvas)
else
if DP_FindItemsRenderer(Item, ItemsRenderer) then
ASize := ItemsRenderer.MeasureItem(Canvas, Item)
else
if Supports(Item, IJvDataItemText, ItemText) then
ASize := Canvas.TextExtent(ItemText.Text)
else
ASize := Canvas.TextExtent(RsDataItemRenderHasNoText);
Inc(ASize.cx, VL.ItemLevel(Index) * VL.LevelIndent);
end;
end;
finally
Provider.Leave;
end;
{ Note: item height in a listbox is limited to 255 pixels since Windows
stores the height in a single byte.}
if ASize.cy > 255 then
ASize.cy := 255;
if ASize.cy < ItemHeight then
ASize.cy := ItemHeight;
end;
{$ENDIF !CLR}
procedure TJvCustomListBox.MeasureString(const S: string; WidthAvail: Integer; var ASize: TSize);
var
Flags: Longint;
R: TRect;
begin
Canvas.Font := Font;
{ Note: doing the TextHeight unconditionally makes sure the font is properly
selected into the device context. }
ASize.cx := Canvas.TextHeight(S);
Flags := DrawTextBiDiModeFlags(
DT_WORDBREAK or DT_NOPREFIX or DT_CALCRECT or AlignFlags[FAlignment]);
if WidthAvail = 0 then
WidthAvail := MaxInt
else
Dec(WidthAvail, 2);
R := Rect(0, 0, WidthAvail, 1);
DrawText(Canvas.Handle, {$IFDEF CLR} S {$ELSE} PChar(S) {$ENDIF}, Length(S), R, Flags);
ASize.cx := R.Right + 4;
ASize.cy := R.Bottom;
{ Note: item height in a listbox is limited to 255 pixels since Windows
stores the height in a single byte.}
if ASize.cy > 255 then
ASize.cy := 255;
if ASize.cy < ItemHeight then
ASize.cy := ItemHeight;
end;
procedure TJvCustomListBox.MoveSelectedDown;
var
I: Integer;
begin
if not IsProviderSelected then
begin
if not MultiSelect then
begin
if (ItemIndex <> -1) and (ItemIndex < Items.Count - 1) then
begin
Items.Exchange(ItemIndex, ItemIndex + 1);
ItemIndex := ItemIndex + 1;
end;
Exit;
end;
if (Items.Count > 0) and (SelCount > 0) and (not Selected[Items.Count - 1]) then
begin
I := Items.Count - 2;
while I >= 0 do
begin
if Selected[I] then
begin
Items.Exchange(I, I + 1);
Selected[I + 1] := True;
end;
Dec(I);
end;
end;
end;
end;
procedure TJvCustomListBox.MoveSelectedUp;
var
I: Integer;
begin
if not IsProviderSelected then
begin
if not MultiSelect then
begin
if ItemIndex > 0 then
begin
Items.Exchange(ItemIndex, ItemIndex - 1);
ItemIndex := ItemIndex - 1;
end;
Exit;
end;
if (Items.Count > 0) and (SelCount > 0) and not Selected[0] then
begin
I := 1;
while I < Items.Count do
begin
if Selected[I] then
begin
Items.Exchange(I, I - 1);
Selected[I - 1] := True;
end;
Inc(I);
end;
end;
end;
end;
procedure TJvCustomListBox.RemeasureAll;
var
I: Integer;
LMaxWidth, cx: Integer;
LItemSize: TSize;
begin
LMaxWidth := 0;
if LimitToClientWidth then
cx := ClientWidth
else
cx := 0;
for I := 0 to ItemsShowing.Count - 1 do
begin
MeasureString(ItemsShowing[I], cx, LItemSize);
if MultiLine then
Perform(LB_SETITEMHEIGHT, I, LItemSize.cy);
if not LimitToClientWidth and (LItemSize.cx > LMaxWidth) then
LMaxWidth := LItemSize.cx;
end;
if not LimitToClientWidth then
MaxWidth := LMaxWidth;
end;
function TJvCustomListBox.SearchExactString(const Value: string;
CaseSensitive: Boolean; StartIndex: Integer): Integer;
begin
Result := TJvItemsSearchs.SearchExactString(ItemsShowing, Value, CaseSensitive, StartIndex);
end;
function TJvCustomListBox.SearchPrefix(const Value: string;
CaseSensitive: Boolean; StartIndex: Integer): Integer;
begin
Result := TJvItemsSearchs.SearchPrefix(ItemsShowing, Value, CaseSensitive, StartIndex);
end;
function TJvCustomListBox.SearchSubString(const Value: string;
CaseSensitive: Boolean; StartIndex: Integer): Integer;
begin
Result := TJvItemsSearchs.SearchSubString(ItemsShowing, Value, CaseSensitive, StartIndex);
end;
procedure TJvCustomListBox.SelectAll;
var
I: Integer;
begin
if MultiSelect then
begin
ItemsShowing.BeginUpdate;
for I := 0 to ItemsShowing.Count - 1 do
Selected[I] := True;
ItemsShowing.EndUpdate;
end;
end;
procedure TJvCustomListBox.SelectCancel(var Msg: TMessage);
begin
if Assigned(FOnSelectCancel) then
FOnSelectCancel(Self);
end;
procedure TJvCustomListBox.SetAlignment(const Value: TAlignment);
begin
if FAlignment <> Value then
begin
FAlignment := Value;
UpdateStyle;
Invalidate;
end;
end;
procedure TJvCustomListBox.SetBackground(const Value: TJvListBoxBackground);
begin
FBackground.Assign(Value);
end;
procedure TJvCustomListBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
if Alignment <> taLeftJustify then
Repaint;
end;
procedure TJvCustomListBox.SetDisabledTextColor(const Value: TColor);
begin
if FDisabledTextColor <> Value then
begin
FDisabledTextColor := Value;
Invalidate;
end;
end;
procedure TJvCustomListBox.SetFlat(const Value: Boolean);
begin
Ctl3D := not Value;
end;
procedure TJvCustomListBox.SetHotTrack(const Value: Boolean);
begin
if FHotTrack <> Value then
begin
FHotTrack := Value;
Ctl3D := not FHotTrack;
end;
end;
procedure TJvCustomListBox.SetMaxWidth(const Value: Integer);
begin
if not LimitToClientWidth and (FMaxWidth <> Value) then
begin
FMaxWidth := Value;
Perform(LB_SETHORIZONTALEXTENT, Value, 0);
end;
end;
procedure TJvCustomListBox.SetMultiline(const Value: Boolean);
begin
if FMultiline <> Value then
begin
FMultiline := Value;
UpdateStyle;
if FMultiline then
begin
// make sure scrollbars matches
if ScrollBars = ssBoth then
ScrollBars := ssVertical;
if ScrollBars = ssHorizontal then
ScrollBars := ssNone;
FMaxWidth := 0;
Perform(LB_SETHORIZONTALEXTENT, 0, 0);
end
else
RemeasureAll;
end;
end;
procedure TJvCustomListBox.SetParentFlat(const Value: Boolean);
begin
ParentCtl3D := Value;
end;
procedure TJvCustomListBox.SetScrollBars(const Value: TScrollStyle);
begin
if FScrollBars <> Value then
begin
FScrollBars := Value;
RecreateWnd;
end;
end;
procedure TJvCustomListBox.SetSelectedColor(const Value: TColor);
begin
if FSelectedColor <> Value then
begin
FSelectedColor := Value;
Invalidate;
end;
end;
procedure TJvCustomListBox.SetSelectedTextColor(const Value: TColor);
begin
if FSelectedTextColor <> Value then
begin
FSelectedTextColor := Value;
Invalidate;
end;
end;
procedure TJvCustomListBox.SetShowFocusRect(const Value: Boolean);
const
CShowFocusRect: array [Boolean] of Integer = (0, 2);
begin
if FShowFocusRect <> Value then
begin
FShowFocusRect := Value;
ItemHeight := CanvasMaxTextHeight(Canvas) + CShowFocusRect[ShowFocusRect];
RemeasureAll;
if Focused then
Invalidate;
end;
end;
procedure TJvCustomListBox.SetSorted(const Value: Boolean);
begin
if FSorted <> Value then
begin
FSorted := Value;
RecreateWnd;
end;
end;
procedure TJvCustomListBox.UnselectAll;
var
I: Integer;
begin
if MultiSelect then
begin
ItemsShowing.BeginUpdate;
for I := 0 to ItemsShowing.Count - 1 do
Selected[I] := False;
ItemsShowing.EndUpdate;
end
else
ItemIndex := -1;
end;
procedure TJvCustomListBox.UpdateHorizontalExtent;
begin
if HandleAllocated and (FScrollBars in [ssHorizontal, ssBoth]) then
RemeasureAll;
// SendMessage(Handle, LB_SETHORIZONTALEXTENT, FHorizontalExtent, 0);
end;
procedure TJvCustomListBox.UpdateStyle;
const
CShowFocusRect: array [Boolean] of Integer = (0, 2);
var
PreviousStyle: TListBoxStyle;
begin
if csLoading in ComponentState then
Exit;
PreviousStyle := Style;
if MultiLine then
Style := lbOwnerDrawVariable
else
if Alignment <> taLeftJustify then
Style := lbOwnerDrawFixed;
// Mantis 3477: Background requires the list to be ownerdrawn
if Background.Visible and Assigned(Background.Image) and
not (Style in [lbOwnerDrawVariable, lbOwnerDrawFixed]) then
Style := lbOwnerDrawFixed;
if (PreviousStyle = lbStandard) and (Style <> lbStandard) then
begin
ItemHeight := CanvasMaxTextHeight(Canvas) + CShowFocusRect[ShowFocusRect];
RemeasureAll;
end;
end;
function TJvCustomListBox.DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean;
begin
if not Background.DoDraw then
Result := inherited DoEraseBackground(Canvas, Param)
else
begin
Result := True;
DrawBackGround(Canvas.Handle, False);
end;
end;
procedure TJvCustomListBox.WMHScroll(var Msg: TWMHScroll);
var
DontScroll: Boolean;
DoUpdate: Boolean;
ScrollInfo: TScrollInfo;
begin
DoUpdate := Background.DoDraw;
if DoUpdate then
BeginRedraw;
try
if Assigned(FOnHorizontalScroll) then
begin
DontScroll := False;
FOnHorizontalScroll(Self, Msg, DontScroll);
if DontScroll then
Exit;
end;
inherited;
if DoUpdate and (FMaxWidth > 0) then
begin
with ScrollInfo do
begin
cbSize := SizeOf(ScrollInfo);
fMask := SIF_ALL;
if GetScrollInfo(Handle, SB_HORZ, ScrollInfo) then
FLeftPosition := Round((FMaxWidth / nMax) * nPos);
end;
end
else
FLeftPosition := 0;
//if DoUpdate then
// Invalidate;
finally
if DoUpdate then
EndRedraw;
end;
end;
procedure TJvCustomListBox.WMVScroll(var Msg: TWMVScroll);
var
DontScroll: Boolean;
DoUpdate: Boolean;
begin
DoUpdate := Background.DoDraw;
if DoUpdate then
BeginRedraw;
try
if Assigned(FOnVerticalScroll) then
begin
DontScroll := False;
FOnVerticalScroll(Self, Msg, DontScroll);
if DontScroll then
Exit;
end;
inherited;
//if DoUpdate then
// Invalidate;
finally
if DoUpdate then
EndRedraw;
end;
end;
function TJvCustomListBox.ItemRect(Index: Integer): TRect;
var
Count: Integer;
begin
Count := ItemsShowing.Count;
{$IFDEF CLR}
if (Index >= 0) and (Index < Count) then
Perform(LB_GETITEMRECT, Index, Result)
else
if Index = Count then
begin
Perform(LB_GETITEMRECT, Index - 1, Result);
OffsetRect(Result, 0, Result.Bottom - Result.Top);
end
else
Result := Rect(0, 0, 0, 0);
{$ELSE}
if (Index >= 0) and (Index < Count) then
Perform(LB_GETITEMRECT, Index, Longint(@Result))
else
if Index = Count then
begin
Perform(LB_GETITEMRECT, Index - 1, Longint(@Result));
OffsetRect(Result, 0, Result.Bottom - Result.Top);
end
else
FillChar(Result, SizeOf(Result), 0);
{$ENDIF CLR}
end;
function TJvCustomListBox.ItemsShowing: TStrings;
begin
{$IFNDEF CLR}
if IsProviderSelected then
Result := ConsumerStrings
else
{$ENDIF !CLR}
Result := Items;
end;
procedure TJvCustomListBox.WndProc(var Msg: TMessage);
var
ItemWidth: Word;
begin
case Msg.Msg of
LB_ADDSTRING, LB_INSERTSTRING:
begin
{$IFDEF CLR}
ItemWidth := Canvas.TextWidth(TWMSetText.Create(Msg).Text + ' ');
{$ELSE}
ItemWidth := Canvas.TextWidth(StrPas(PChar(Msg.LParam)) + ' ');
{$ENDIF CLR}
if FMaxWidth < ItemWidth then
FMaxWidth := ItemWidth;
SendMessage(Handle, LB_SETHORIZONTALEXTENT, FMaxWidth, 0);
end;
LB_DELETESTRING:
begin
if Msg.WParam < ItemsShowing.Count then
ItemWidth := Canvas.TextWidth(ItemsShowing[Msg.WParam] + ' ')
else
ItemWidth := FMaxWidth;
if ItemWidth = FMaxWidth then
begin
inherited WndProc(Msg);
UpdateHorizontalExtent;
Exit;
end;
end;
LB_RESETCONTENT:
SendMessage(Handle, LB_SETHORIZONTALEXTENT, 0, 0);
WM_SETFONT:
begin
inherited WndProc(Msg);
Canvas.Font.Assign(Font);
UpdateHorizontalExtent;
Exit;
end;
end;
inherited WndProc(Msg);
end;
//=== { TJvListBoxBackground } ===============================================
constructor TJvListBoxBackground.Create;
begin
inherited Create;
FImage := TBitmap.Create;
end;
destructor TJvListBoxBackground.Destroy;
begin
FImage.Free;
inherited Destroy;
end;
procedure TJvListBoxBackground.Assign(Source: TPersistent);
begin
if Source is TJvListBoxBackground then
begin
FImage.Assign(TJvListBoxBackground(Source).Image);
FFillMode := TJvListBoxBackground(Source).FillMode;
FVisible := TJvListBoxBackground(Source).Visible;
end
else
inherited Assign(Source);
end;
procedure TJvListBoxBackground.Change;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
function TJvListBoxBackground.GetDoDraw: Boolean;
begin
Result := Visible and not Image.Empty;
end;
procedure TJvListBoxBackground.SetFillMode(const Value: TJvListboxFillMode);
begin
if FFillMode <> Value then
begin
FFillMode := Value;
Change;
end;
end;
procedure TJvListBoxBackground.SetImage(const Value: TBitmap);
begin
FImage.Assign(Value);
Change;
end;
procedure TJvListBoxBackground.SetVisible(const Value: Boolean);
begin
if FVisible <> Value then
begin
FVisible := Value;
Change;
end;
end;
{$IFDEF UNITVERSIONING}
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.