source: trunk/Components/MultiColumnListBox.pas@ 15

Last change on this file since 15 was 15, checked in by RBRi, 19 years ago

+ components stuff

  • Property svn:eol-style set to native
File size: 19.6 KB
Line 
1unit MultiColumnListBox;
2
3interface
4
5uses
6 Messages, SysUtils, Classes, Graphics, Forms, Dialogs,
7 StdCtrls, ComCtrls, CustomHeaderControl; // menus for SPCC v2.5+
8
9const
10 mclbImageMarker = #11;
11
12type
13 TMultiColumnListBox = class(TControl)
14 protected
15 FHeader: TCustomHeaderControl;
16 FLIstBox: TListBox;
17 FImageList: TImageList;
18
19 FSavedSelectedObject: TObject;
20
21 FBorderStyle: TBorderStyle;
22 Procedure SetBorderStyle( NewValue: TBorderStyle );
23
24 function GetHeaderPenColor: TColor;
25 procedure SetHeaderPenColor( NewValue: TColor );
26 function GetListPenColor: TColor;
27 procedure SetListPenColor( NewValue: TColor );
28
29 function GetEnabled: boolean; //override;
30 function GetExtendedSelect: boolean;
31 function GetHeaderFont: TFont;
32 function GetHeaderHeight: integer;
33 function GetHeaderParentFont: boolean;
34 function GetItemHeight: integer;
35 function GetListFont: TFont;
36 function GetListParentFont: boolean;
37 function GetMultiSelect: boolean;
38 function GetParentColor: boolean;
39 function GetParentShowHint: boolean;
40 function GetThePopupMenu: TPopupMenu;
41 function GetShowHint: boolean;
42// procedure SetEnabled(NewState:Boolean); override;
43 procedure SetExtendedSelect(const Value: boolean);
44 procedure SetHeaderFont(const Value: TFont);
45 procedure SetHeaderHeight(const Value: integer);
46 procedure SetHeaderParentFont(const Value: boolean);
47 procedure SetItemHeight(const Value: integer);
48 procedure SetListFont(const Value: TFont);
49 procedure SetListParentFont(const Value: boolean);
50 procedure SetMultiSelect(const Value: boolean);
51 procedure SetParentShowHint(const Value: boolean);
52 procedure SetPopupMenu(const Value: TPopupMenu);
53 procedure SetShowHint(const Value: boolean);
54 procedure SetSelectedObject(const Value: TObject);
55 function GetOnClick: TNotifyEvent;
56 procedure SetOnClick(const Value: TNotifyEvent);
57 function GetOnDblClick: TNotifyEvent;
58 procedure SetOnDblClick(const Value: TNotifyEvent);
59 procedure SetSelectedItem(const Value: string);
60 function GetTopObject: TObject;
61 procedure SetTopObject(const Value: TObject);
62
63 function GetItems: TStrings;
64 procedure SetItems( Items: TStrings );
65 function GetHeaderSections: TCustomHeaderSections;
66 procedure SetHeaderSections( Sections: TCustomHeaderSections );
67 function GetSelectedItem: string;
68 function GetSelectedObject: TObject;
69 function GetItemIndex: integer;
70 procedure SetItemIndex( const Value: integer );
71 procedure SetImageList( ImageList: TImageList );
72 procedure Notification( AComponent: TComponent;
73 Operation: TOperation); override;
74
75 procedure SetOnItemFocus( Value: TItemFocusEvent );
76 function GetOnItemFocus: TItemFocusEvent;
77 function GetOnItemSelect: TItemSelectEvent;
78 procedure SetOnItemSelect( Value: TItemSelectEvent );
79
80 function GetOnEnter: TNotifyEvent;
81 procedure SetOnEnter( Value: TNotifyEvent );
82 function GetOnExit: TNotifyEvent;
83 procedure SetOnExit( Value: TNotifyEvent );
84
85 procedure SetSelected( Index: longint; Value: boolean );
86 function GetSelected( Index: longint ): boolean;
87
88 Procedure SetColor(NewColor:TColor); Override;
89
90 procedure Layout;
91 procedure DrawListBoxItem( Sender: TObject;
92 Index: longint;
93 Rect: TRect;
94 State: TOwnerDrawState );
95 procedure ChangeHeader( HeaderControl: TCustomHeaderControl;
96 Section: TCustomHeaderSection );
97 procedure Resize; override;
98 procedure SetupShow; override;
99 procedure SetupComponent; override;
100
101 Procedure ReadSCUResource(Const ResName:TResourceName;Var Data;DataLen:LongInt);Override;
102 Function WriteSCUResource(Stream:TResourceStream):Boolean;Override;
103
104 function GetTabStop:boolean;
105 procedure SetTabStop(Value:boolean);
106
107 procedure WMFocussing( Var Msg: TMessage ); message WM_FOCUSSING;
108 public
109 destructor Destroy; override;
110
111 property ItemIndex: integer read GetItemIndex write SetItemIndex;
112 property SelectedItem: string read GetSelectedItem write SetSelectedItem;
113 property SelectedObject: TObject read GetSelectedObject write SetSelectedObject;
114 property TopObject: TObject read GetTopObject write SetTopObject;
115
116 procedure SetSelectedItemTo( Text: string );
117 property Selected[ Index: longint ]: boolean read GetSelected write SetSelected;
118
119 property Parent;
120
121 published
122 property Items: TStrings
123 read GetItems
124 write SetItems;
125 property HeaderColumns: TCustomHeaderSections
126 read GetHeaderSections
127 write SetHeaderSections;
128 property ImageList: TImageList
129 read FImageList
130 write SetImageList;
131
132 Property BorderStyle:TBorderStyle read FBorderStyle write SetBorderStyle;
133
134 property ListPenColor: TColor read GetListPenColor write SetListPenColor;
135 property HeaderPenColor: TColor read GetHeaderPenColor write SetHeaderPenColor;
136
137 property ListFont: TFont read GetListFont write SetListFont;
138 property ListParentFont: boolean read GetListParentFont write SetListParentFont;
139
140 property HeaderFont: TFont read GetHeaderFont write SetHeaderFont;
141 property HeaderParentFont: boolean read GetHeaderParentFont write SetHeaderParentFont;
142
143 property ShowHint: boolean read GetShowHint write SetShowHint;
144 property ParentShowHint: boolean read GetParentShowHint write SetParentShowHint;
145
146 property PopupMenu: TPopupMenu read GetThePopupMenu write SetPopupMenu;
147
148 property HeaderHeight: integer read GetHeaderHeight write SetHeaderHeight;
149 property ItemHeight: integer read GetItemHeight write SetItemHeight;
150
151 property MultiSelect: boolean read GetMultiSelect write SetMultiSelect;
152 property ExtendedSelect: boolean read GetExtendedSelect write SetExtendedSelect;
153
154 property Enabled; //: boolean read GetEnabled write SetEnabled;
155
156 property Align;
157 property Color;
158 property ParentColor;
159 property TabStop: boolean read GetTabStop write SetTabStop;
160 property TabOrder;
161
162 // Events
163 property OnClick: TNotifyEvent read GetOnClick write SetOnClick;
164 property OnDblClick: TNotifyEvent read GetOnDblClick write SetOnDblClick;
165 property OnItemFocus: TItemFocusEvent read GetOnItemFocus write SetOnItemFocus;
166 property OnItemSelect: TItemSelectEvent read GetOnItemSelect write SetOnItemSelect;
167 property OnEnter: TNotifyEvent read GetOnEnter write SetOnEnter;
168 property OnExit: TNotifyEvent read GetOnExit write SetOnExit;
169 end;
170
171exports
172 TMultiColumnListBox, 'User', 'MultiColumnListBox.bmp';
173
174implementation
175
176uses
177 ACLStringUtility;
178
179{ TMultiColumnListBox }
180
181procedure TMultiColumnListBox.SetupComponent;
182var
183 Section: TCustomHeaderSection;
184begin
185 inherited SetupComponent;
186
187 Width := 100;
188 Height := 100;
189
190 ParentCOlor := true;
191
192 Name := 'MultiColumnListBox';
193
194 FTabStop := false;
195
196 FHeader := TCustomHeaderControl.Create( Self );
197 FHeader.Parent := self;
198 FHeader.Height := 22;
199 FHeader.BevelWidth := 1;
200 FHeader.TabStop := false;
201 Include( FHeader.ComponentState, csDetail );
202
203 // Create a couple of default header sections
204 // so it's obvious that it's there.
205 Section := FHeader.Sections.Add;
206 Section.Text := 'Column 1';
207 Section.AllowClick := false;
208 Section := FHeader.Sections.Add;
209 Section.Text := 'Column 2';
210
211 FListBox := TListBox.Create( Self );
212 FListBox.Parent := self;
213// FListBox.ItemHeight := 16;
214
215 FListBox.Style := lbOwnerDrawFixed;
216
217 FListBox.OnDrawItem := DrawListBoxItem;
218
219 FListBox.TabStop := true;
220 Include( FListBox.ComponentState, csDetail );
221 FListBox.ParentColor := true;
222
223// FListBox.BorderStyle := bsNone; // we draw it ourselves
224
225 FHeader.OnSectionResize := ChangeHeader;
226
227 FImageList := nil;
228
229// FAlwaysFocusChild := FListBox;
230
231 Layout;
232
233end;
234
235procedure TMultiColumnListBox.SetupShow;
236begin
237 Layout;
238end;
239
240destructor TMultiColumnListBox.Destroy;
241begin
242 inherited Destroy;
243end;
244
245Procedure TMultiColumnListBox.ReadSCUResource( Const ResName: TResourceName;
246 Var Data;DataLen: LongInt );
247begin
248 if ResName = rnHeaders then
249 FHeader.ReadSCUResource( ResName, Data, DataLen )
250 else
251 inherited ReadSCUResource( ResName, Data, DataLen );
252
253end;
254
255Function TMultiColumnListBox.WriteSCUResource( Stream: TResourceStream ): Boolean;
256begin
257 Result := Inherited WriteSCUResource(Stream);
258 If Not Result Then
259 Exit;
260 FHeader.WriteScuResource( Stream );
261end;
262
263procedure TMultiColumnListBox.WMFocussing( Var Msg: TMessage );
264begin
265 // focus listbox instead
266 Msg.Result := LONGWORD( FListBox );
267 msg.Handled := true;
268end;
269
270function TMultiColumnListBox.GetTabStop:boolean;
271begin
272 result:=FListBox.TabStop;
273end;
274
275procedure TMultiColumnListBox.SetTabStop(Value:boolean);
276begin
277 FListBox.TabStop:=Value;
278end;
279
280procedure TMultiColumnListBox.DrawListBoxItem( Sender: TObject;
281 Index: longint;
282 Rect: TRect;
283 State: TOwnerDrawState );
284var
285 ColumnIndex: integer;
286 X: integer;
287 ItemToDraw: string;
288 Line: string;
289 BitmapIndex: integer;
290 ColumnWidth: integer;
291 ItemRect: TRect;
292 Dest: TRect;
293 LineClipRect: TRect;
294begin
295 LineClipRect := FListBox.Canvas.ClipRect;
296
297 ColumnIndex := 0;
298
299 Dest := rect;
300 dec( Dest.top ); // minor adjustments since we seem to get a slightly
301 inc( Dest.left ); // incorrect area to draw on...
302
303 X := Dest.Left;
304 Line := FListBox.Items[ Index ];
305
306 with FListBox.Canvas do
307 begin
308 Pen.Color := FListBox.PenColor;
309 Brush.Color := FListBox.Color;
310 IF State * [odSelected] <> [] THEN
311 begin
312 Brush.Color := clHighLight;
313 Pen.Color := Color;
314 end;
315
316 FillRect( Dest, Brush.Color );
317 end;
318
319 while Line <> '' do
320 begin
321 ItemToDraw := ExtractNextValue( Line,
322 #9 );
323 if ColumnIndex < FHeader.Sections.Count then
324 ColumnWidth := FHeader.Sections[ ColumnIndex ].Width
325 else
326 ColumnWidth := 50;
327
328 ItemRect := Dest;
329 ItemRect.Left := X;
330 ItemRect.Right := X + ColumnWidth - 2;
331 FListBox.Canvas.ClipRect := IntersectRect( LineClipRect,
332 ItemRect );
333
334 if StrLeft( ItemToDraw, 1 ) = mclbImageMarker then
335 begin
336 Delete( ItemToDraw, 1, 1 );
337 try
338 BitmapIndex := StrToInt( ItemToDraw );
339 except
340 BitmapIndex := -1;
341 end;
342 if Assigned( FImageList ) then
343 if ( BitmapIndex >= 0 )
344 and ( BitmapIndex < FImageList.Count ) then
345 begin
346 FImageList.Draw( FListBox.Canvas,
347 X, Dest.Bottom,
348 BitmapIndex );
349 end
350 else
351 raise Exception.Create( 'Bitmap index out of range in MultiColumnListBox' )
352 else
353 raise Exception.Create( 'No imagelist assigned in MultiColumnListBox' );
354
355 end
356 else
357 begin
358 FListBox.Canvas.TextOut( X, Dest.Bottom,
359 ItemToDraw );
360 end;
361 inc( X, ColumnWidth );
362 inc( ColumnIndex );
363 end;
364end;
365
366procedure TMultiColumnListBox.SetItems( Items: TStrings );
367begin
368 FListBox.Items.Assign( Items );
369end;
370
371function TMultiColumnListBox.GetHeaderSections: TCustomHeaderSections;
372begin
373 Result := FHeader.Sections;
374end;
375
376function TMultiColumnListBox.GetItems: TStrings;
377begin
378 Result := FListBox.Items;
379end;
380
381procedure TMultiColumnListBox.Layout;
382var
383 LastSection: TCustomHeaderSection;
384begin
385 FHeader.Align := alTop;
386
387 //FListBox.Align := alClient;
388{
389 if FBorderStyle = bsNone then
390 begin
391}
392 FListBox.Left := 0;
393 FListBox.Width := Width;
394 FListBox.Bottom := 0;
395 FListBox.Height := Height - FHeader.Height + 2; // hide the top edge under header
396 FListBox.SendToBack;
397{
398 end
399 else
400 begin
401 FListBox.Left := 2;
402 FListBox.Width := Width - 4;
403 FListBox.Bottom := 2;
404 FListBox.Height := Height - FHeader.Height - 4;
405 end;
406}
407
408 if HeaderColumns.Count > 0 then
409 begin
410 // Resize the last column to fit, if possible
411 LastSection := HeaderColumns[ HeaderColumns.Count - 1 ];
412 if LastSection.Left < Width then
413 LastSection.Width := Width - LastSection.Left;
414 end;
415
416end;
417
418procedure TMultiColumnListBox.SetBorderStyle( NewValue: TBorderStyle );
419begin
420 if NewValue = FBorderStyle then
421 exit;
422 FBorderStyle := NewValue;
423 Layout;
424 Invalidate;
425end;
426
427procedure TMultiColumnListBox.SetImageList(ImageList: TImageList);
428begin
429 if FImageList <> nil then
430 // Tell the old imagelist not to inform us any more
431 FImageList.Notification( Self, opRemove );
432
433 FImageList := ImageList;
434
435 if FImageList <> nil then
436 begin
437 // request notification when other is freed
438 FImageList.FreeNotification( Self );
439 end;
440end;
441
442procedure TMultiColumnListBox.SetHeaderSections(Sections: TCustomHeaderSections);
443begin
444 FHeader.Sections.Assign( Sections );
445end;
446
447procedure TMultiColumnListBox.Notification( AComponent: TComponent;
448 Operation: TOperation);
449begin
450 inherited Notification( AComponent, Operation );
451 if AComponent = FImageList then
452 if Operation = opRemove then
453 // Image list is being destroyed
454 FImageList := nil;
455end;
456
457procedure TMultiColumnListBox.ChangeHeader(HeaderControl: TCustomHeaderControl;
458 Section: TCustomHeaderSection);
459begin
460 Layout;
461 FListBox.Invalidate;
462end;
463
464function TMultiColumnListBox.GetSelectedItem: string;
465begin
466 Result := '';
467 if FListBox.ItemIndex <> -1 then
468 Result := FListBox.Items[ FListBox.ItemIndex ];
469end;
470
471function TMultiColumnListBox.GetSelectedObject: TObject;
472begin
473 Result := nil;
474 if FListBox.ItemIndex <> -1 then
475 Result := FListBox.Items.Objects[ FListBox.ItemIndex ];
476
477end;
478
479procedure TMultiColumnListBox.SetItemIndex(const Value: integer );
480begin
481 FListBox.ItemIndex := Value;
482end;
483
484function TMultiColumnListBox.GetItemIndex: integer;
485begin
486 Result := FListBox.ItemIndex;
487end;
488
489function TMultiColumnListBox.GetHeaderPenColor: TColor;
490begin
491 Result := FHeader.PenColor;
492end;
493
494procedure TMultiColumnListBox.SetHeaderPenColor( NewValue: TColor );
495begin
496 FHeader.PenColor := NewValue;
497end;
498
499function TMultiColumnListBox.GetListPenColor: TColor;
500begin
501 Result := FListBox.PenColor;
502end;
503
504procedure TMultiColumnListBox.SetListPenColor( NewValue: TColor );
505begin
506 FListBox.PenColor := NewValue;
507end;
508
509function TMultiColumnListBox.GetEnabled: boolean;
510begin
511 Result := FListBox.Enabled;
512end;
513
514function TMultiColumnListBox.GetExtendedSelect: boolean;
515begin
516 Result := FListBox.ExtendedSelect;
517end;
518
519function TMultiColumnListBox.GetHeaderFont: TFont;
520begin
521 Result := FHeader.Font;
522end;
523
524function TMultiColumnListBox.GetHeaderHeight: integer;
525begin
526 Result := FHeader.Height;
527end;
528
529function TMultiColumnListBox.GetHeaderParentFont: boolean;
530begin
531 Result := FHeader.ParentFont;
532end;
533
534function TMultiColumnListBox.GetItemHeight: integer;
535begin
536 Result := FListBox.ItemHeight;
537end;
538
539function TMultiColumnListBox.GetListFont: TFont;
540begin
541 Result := FListBox.Font;
542end;
543
544function TMultiColumnListBox.GetListParentFont: boolean;
545begin
546 Result := FListBox.ParentFont;
547end;
548
549function TMultiColumnListBox.GetMultiSelect: boolean;
550begin
551 Result := FListBox.MultiSelect;
552end;
553
554function TMultiColumnListBox.GetParentColor: boolean;
555begin
556 Result := FListBox.ParentColor;
557end;
558
559function TMultiColumnListBox.GetParentShowHint: boolean;
560begin
561 Result := FListBox.ParentShowHint;
562end;
563
564function TMultiColumnListBox.GetThePopupMenu: TPopupMenu;
565begin
566 Result := FListBox.PopupMenu;
567end;
568
569function TMultiColumnListBox.GetShowHint: boolean;
570begin
571 Result := FListBox.ShowHint;
572end;
573
574{
575procedure TMultiColumnListBox.SetEnabled(NewState:Boolean);
576begin
577 FListBox.Enabled := NewState;
578 FHeader.Enabled := NewState;
579end;
580}
581
582procedure TMultiColumnListBox.SetExtendedSelect(const Value: boolean);
583begin
584 FListBox.ExtendedSelect := Value;
585end;
586
587procedure TMultiColumnListBox.SetHeaderFont(const Value: TFont);
588begin
589 FHeader.Font := Value;
590end;
591
592procedure TMultiColumnListBox.SetHeaderHeight(const Value: integer);
593begin
594 FHeader.Height := Value;
595end;
596
597procedure TMultiColumnListBox.SetHeaderParentFont(const Value: boolean);
598begin
599 FHeader.ParentFont := Value;
600end;
601
602procedure TMultiColumnListBox.SetItemHeight(const Value: integer);
603begin
604 FListBox.ItemHeight := Value;
605end;
606
607procedure TMultiColumnListBox.SetListFont(const Value: TFont);
608begin
609 FListBox.Font := Value;
610end;
611
612procedure TMultiColumnListBox.SetListParentFont(const Value: boolean);
613begin
614 FListBox.ParentFont := Value;
615end;
616
617procedure TMultiColumnListBox.SetMultiSelect(const Value: boolean);
618begin
619 FListBox.MultiSelect := Value;
620end;
621
622procedure TMultiColumnListBox.SetParentShowHint(const Value: boolean);
623begin
624 FListBox.ParentShowHint := Value;
625 FHeader.ParentShowHint := Value;
626end;
627
628procedure TMultiColumnListBox.SetPopupMenu(const Value: TPopupMenu);
629begin
630 FListBox.PopupMenu := Value;
631 FHeader.PopupMenu := Value;
632end;
633
634procedure TMultiColumnListBox.SetShowHint(const Value: boolean);
635begin
636 FListBox.ShowHint := Value;
637 FHeader.ShowHint := Value;
638end;
639
640procedure TMultiColumnListBox.SetSelectedObject(const Value: TObject);
641var
642 Index: integer;
643begin
644 Index := FListBox.Items.IndexOfObject( Value );
645 FListBox.ItemIndex := Index;
646end;
647
648function TMultiColumnListBox.GetOnClick: TNotifyEvent;
649begin
650 Result := FListBox.OnClick;
651end;
652
653procedure TMultiColumnListBox.SetOnClick(const Value: TNotifyEvent);
654begin
655 FListBox.OnClick := Value;
656end;
657
658function TMultiColumnListBox.GetOnDblClick: TNotifyEvent;
659begin
660 Result := FListBox.OnDblClick;
661end;
662
663procedure TMultiColumnListBox.SetOnDblClick(const Value: TNotifyEvent);
664begin
665 FListBox.OnDblClick := Value;
666end;
667
668procedure TMultiColumnListBox.SetSelectedItem(const Value: string);
669var
670 Index: integer;
671begin
672 Index := FListBox.Items.IndexOf( Value );
673 FListBox.ItemIndex := Index;
674end;
675
676procedure TMultiColumnListBox.SetSelectedItemTo(Text: string );
677begin
678 if ItemIndex = -1 then
679 raise Exception.Create( 'MultiColumnListBox: no item selected to set!' );
680
681 Items[ ItemIndex ] := Text;
682end;
683
684procedure TMultiColumnListBox.Resize;
685begin
686 Layout;
687end;
688
689
690function TMultiColumnListBox.GetTopObject: TObject;
691begin
692 Result := nil;
693 if ( FListBox.TopIndex >0 )
694 and ( FListBox.TopIndex < FListBox.Items.Count ) then
695 Result := FListBox.Items.Objects[ FLIstBox.TopIndex ];
696
697end;
698
699procedure TMultiColumnListBox.SetTopObject(const Value: TObject);
700var
701 Index: integer;
702begin
703 Index := FListBox.Items.IndexOfObject( Value );
704 if Index <> -1 then
705 FListBox.TopIndex := Index;
706end;
707
708procedure TMultiColumnListBox.SetOnItemFocus( Value: TItemFocusEvent );
709begin
710 FListBox.OnItemFocus := Value;
711end;
712
713function TMultiColumnListBox.GetOnItemFocus: TItemFocusEvent;
714begin
715 Result := FListBox.OnItemFocus;
716end;
717
718function TMultiColumnListBox.GetOnItemSelect: TItemSelectEvent;
719begin
720 Result := FListBox.OnItemSelect;
721end;
722
723procedure TMultiColumnListBox.SetOnItemSelect( Value: TItemSelectEvent );
724begin
725 FListBox.OnItemSelect := Value;
726end;
727
728function TMultiColumnListBox.GetOnEnter: TNotifyEvent;
729begin
730 Result := FListBox.OnEnter;
731end;
732
733procedure TMultiColumnListBox.SetOnEnter( Value: TNotifyEvent );
734begin
735 FListBox.OnEnter := Value;
736end;
737
738function TMultiColumnListBox.GetOnExit: TNotifyEvent;
739begin
740 Result := FListBox.OnExit;
741end;
742
743procedure TMultiColumnListBox.SetOnExit( Value: TNotifyEvent );
744begin
745 FListBox.OnExit := Value;
746end;
747
748procedure TMultiColumnListBox.SetSelected( Index: longint; Value: boolean );
749begin
750 FListBox.Selected[ Index ] := Value;
751end;
752
753function TMultiColumnListBox.GetSelected( Index: longint ): boolean;
754begin
755 Result := FListBox.Selected[ Index ];
756end;
757
758Procedure TMultiColumnListBox.SetColor(NewColor:TColor);
759begin
760 inherited SetColor( NewColor );
761end;
762
763Initialization
764 {Register classes}
765 RegisterClasses([TMultiColumnListBox]);
766end.
Note: See TracBrowser for help on using the repository browser.