Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
Je kan je listbox.canvas gebruiken om op te tekenen. In de ondrawitem krijg je een rect mee. Deze rect bevat de coordinaten die je kan gebruiken om je item te tekenen.
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
[ Voor 6% gewijzigd door alienfruit op 01-01-2006 08:58 ]
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
Maar goed zo'n component ziet gewoon standaard in JVCL. bij mijn weten. Verder zijn er zat te vinden op Torry.
[ Voor 17% gewijzigd door alienfruit op 01-01-2006 16:19 ]
edit:
ik kan zo'n component nergens vinden, ben wel veel andere handige dingen tegengekomen.
en bovendien vind ik het leuk om zelf zoiets te maken.
edit2:
na nog wat graven in de help, vond ik dit:
"Use Style to specify whether the list box is a standard list box that displays text strings, or an owner-draw list box that can display graphical images. Owner-draw list boxes let you display items in some nonstandard way. In this case, you must write the code to paint items in the list box."
hieruit concludeer ik dus dat je alleen plaatjes kan laten zien op de standaar manier, en geen objecten die zelf allerlei zaken afhandelen. dan is mijn volgende vraag, moet ik die functionaliteit die ik wil dan helemaal zelf implementeren (vanuit een TCustomListBox). of zijn er nog andere/eenvoudigere wegen te bewandelen? (behalve componenten die ergens op het net rondzwerven)
[ Voor 35% gewijzigd door tombo_inc op 01-01-2006 17:21 ]
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
Maar probeer eerst eens als eerste stap een owner draw listbox aan de praat te krijgen zodat ie er uitziet als een normale listbox. Als je dat helemaal door hebt kan je naar de volgende stap gaan en er een edit in zetten.
We adore chaos because we like to restore order - M.C. Escher
en ik ben ook tot de conclusie gekomen dat je die items die erin staan alleen op maar de canvas van de listbox kan tekenen. en dat er niet (zoals ik eerst dacht) gewoon een lijst met controls verschijnt die zelf hun painting afhandelen.
ik heb nog eens wat gezocht en ben toen dit http://www.shorterpath.co...articles/VisualStyles.asp tegengekomen. erg handig en leuk allemaal, behalve dat mijn delphi (personal 7) weigerd om de DrawFrameControl() functie te herkennen. ik ben dus tot de volgende conclusie gekomen, namelijk dat ik gewoon alles zelf (inclusief controls als een checkbox of edit veld) op de canvas van mijn listbox moet tekenen. nu nog uitvissen hoe
edit:
hum, ik heb nu wel wat verbetering. ik heb um nu zo ver dat mijn eigen control getekend word in de lijst. maar nu is het zo dat je geen items meer kan selecteren uit de lijst omdat mijn control even groot is als de Rect van het item. je ziet dus niet meer dat het item geselecteerd is. en ik neem aan dat ie dan ook niet als geselecteerd word gezien in het programma.
[ Voor 19% gewijzigd door tombo_inc op 01-01-2006 18:40 ]
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
Ja, bij Owner draw moet je alles zelf tekenen. Maar aangezien een edit weet hoe het zichzelf moet tekenen kan je gewoon een edit op de plaats zetten waar je wat wilde tekenen en klaar is klara.
/edit
Een heel simpel voorbeeld van een Form met daarop een ListBox1 die OwnerDraw aan heeft staan en designtime enkele items heeft ingevuld.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| TForm2 = class(TForm) Edits: array of TEdit; ... procedure TForm2.FormCreate(Sender: TObject); var I: Integer; begin SetLength(Edits, ListBox1.Items.Count); for I := 0 to ListBox1.Items.Count - 1 do begin Edits[I] := TEdit.Create(Self); Edits[I].Parent := ListBox1; Edits[I].Text := ListBox1.Items[I]; end; end; procedure TForm2.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin Edits[Index].BoundsRect := Rect; end; |
[ Voor 61% gewijzigd door LordLarry op 01-01-2006 18:52 ]
We adore chaos because we like to restore order - M.C. Escher
dit is ongeveer wat ik ook inmiddels klaargestoomt heb. ik heb nu hetvolgende, net iets anders namelijk. ik heb een eigen object afgeleid van TCustomControl. dit object bevat onder andere een TEdit.
op het moment dat ik op mijn button op mijn form klik dan word er een nieuw eigen object geinstantieerd en word de listbox als parent toegewezen. dan zeg ik vervolgens in de listboxdrawitem dat de boundsrect van mijn eigen control gelijk is aan rect die meegeven word als argument. nu word alles netjes getekend. mijn eigen control met daarop de edit etc. das dus zeer zeker mooi. maar...
het volgende probleem waar ik wat advies voor nodig heb, doet zich dan voor. omdat mijn object even groot is als de Rect van een listitem, en omdat mijn object op de canvas van de listbox word geplaatst en dus over de listboxitem(s) heen valt (in feite). werkt het selecteren van de listboxitems niet meer (want er staat iets over de items heen). nu moet daar dus een oplossing voor bedacht worden. en ik zelf heb het volgende in gedachte. ik implementeer een onclick event in mijn eigen object en zeg daarin dat het juiste listitem geselecteerd moet zijn/worden.
nu wil ik graag weten of deze aanpak die ik hierboven beschrijf juist is. of dat er een andere methode voor is. en of ik de rest nu ook goed heb geimplementeerd. alvast bedankt voor de info/voorbeeld(en)
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
We adore chaos because we like to restore order - M.C. Escher
dan ga ik weer aan de slag, om alles even goed te implementeren
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| type TUserComboBoxStrings = class(TCustomComboBoxStrings); TUserComboBox = class(TComboBox) private function GetItems: TUserComboBoxStrings; protected function GetItemsClass: TCustomComboBoxStringsClass; override; procedure SetItems(Value: TUserComboBoxStrings); reintroduce; procedure CreateParams(var Params: TCreateParams); override; procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override; public constructor Create(AOwner: TComponent); override; published property Items: TUserComboBoxStrings read GetItems write SetItems; property LinePos: Integer read FLinePos write FLinePos default 100; end; implementation function TUserComboBox.GetItems: TUserComboBoxStrings; begin Result := TUserComboBoxStrings(inherited Items); end; function TUserComboBox.GetItemsClass: TCustomComboBoxStringsClass; begin Result := TUserComboBoxStrings; end; procedure TUserComboBox.SetItems(Value: TUserComboBoxStrings); begin if Assigned(inherited Items) then inherited Items.Assign(Value) else inherited Items := Value; end; procedure TUserComboBox.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); Params.Style := CBS_OWNERDRAWFIXED; end; procedure TUserComboBox.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); var ClipRect: TRect; begin TControlCanvas(Canvas).UpdateTextFlags; if Assigned(OnDrawItem) then OnDrawItem(Self, Index, Rect, State) else begin Canvas.FillRect(Rect); if Index >= 0 then if odComboBoxEdit in State then Canvas.TextOut(Rect.Left + 2, Rect.Top, Items[Index]) else begin ClipRect := Rect; ClipRect.Right := ClipRect.Left + FLinePos - 2; Canvas.TextRect(ClipRect, Rect.Left + 2, Rect.Top, Items[Index]); if ColorToRGB(Color) <> ColorToRGB(clBtnFace) then Canvas.Pen.Color := clBtnFace else Canvas.Pen.Color := clBtnShadow; Canvas.MoveTo(Rect.Left + FLinePos, Rect.Top); Canvas.LineTo(Rect.Left + FLinePos, Rect.Bottom); Canvas.TextOut(FLinePos + 3, Rect.Top, Format('This is user %d', [Index])); end; end; end; constructor TUserComboBox.Create(AOwner: TComponent); begin inherited Create(AOwner); FLinePos := 100; end; |
[ Voor 3% gewijzigd door Tomatoman op 03-01-2006 00:43 ]
Een goede grap mag vrienden kosten.
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
waarom gebruik je dit en zet je dit niet gewoon in de constructor?
1
2
3
4
5
| procedure TUserComboBox.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); Params.Style := CBS_OWNERDRAWFIXED; end; |
en ik vroeg me af wat je met die TControlCanvas doet in de DrawItem method.
verder denk ik dat het me wel duidelijk is.
ik heb er dit keer zelf voor gekozen om niet zelf een heel component te schrijven, maar om gewoon een bestaande listbox te nemen en die wat aan te passen. ik heb wel zelf de listitems gemaakt. ik heb nu het volgende en ik vroeg me af of ik dit op de juiste manier doe, of dat die listitems van mij te overdreven zijn zo of dat het makkelijker kan.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
| // mijn form met TListBox (LayerList) type TLagenBeheerForm = class(TForm) LayerList: TListBox; NewLayer: TAction; procedure NewLayerExecute(Sender: TObject); destructor Destroy; override; procedure LayerListDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); private { Private declarations } public { Public declarations } CurrentDocument: TDocumentContainerForm; end; var LagenBeheerForm: TLagenBeheerForm; implementation {$R *.dfm} // hier word een nieuwe laag aangemaakt. procedure TLagenBeheerForm.NewLayerExecute(Sender: TObject); var LayerListItem: TLayerListItem; // mijn eigen component Layer: TDrawLayer; //mijn eigen component nvt hier begin if ParentGUI.ActiveMDIChild <> nil then begin Layer := (ParentGUI.ActiveMDIChild as TDocumentContainerForm).Document.CreateNewLayer( true ); //maak daadwerkelijk nieuwe laag in document, nvt hier LayerListItem := TLayerListItem.Create( self ); LayerListItem.Parent := self.LayerList; LayerListItem.LayerID := Layer.ID; LayerListItem.Caption.Caption := Layer.Name; self.LayerList.AddItem('', LayerListItem); end; end; destructor TLagenBeheerForm.Destroy; begin self.LayerList.Free; inherited; end; procedure TLagenBeheerForm.LayerListDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin //TLayerListItem(self.ListBox1.Items.Objects[Index]).BoundsRect := Rect; {wat is het verschil tussen deze 2 methodes want er komt gewoon hetzelfde uit ?} (self.LayerList.Items.Objects[Index] as TLayerListItem).BoundsRect := Rect; end; |
en hier mijn eigen layerlistitem component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
| type TLayerListItem = class(TCustomControl) Edit: TEdit; Caption: TLabel; private public LayerID: Integer; constructor Create( AOwner: TComponent ); override; procedure Paint; override; procedure Click; override; procedure CaptionDblClick( Sender: TObject ); procedure EditKeyPress( Sender: TObject; var Key: Char ); destructor Destroy; override; end; implementation uses lagenbeheer.gui; constructor TLayerListItem.Create( AOwner: TComponent ); begin inherited; // self.Color := ff een mooie uitzoeken :p self.Cursor := crHandPoint; self.Caption := TLabel.Create( self ); self.Caption.Parent := self; self.Caption.Left := 20; self.Caption.Top := 15; self.Caption.OnDblClick := self.CaptionDblClick; self.Edit := TEdit.Create(self); self.Edit.Visible := false; self.Edit.Parent := self; self.Edit.Left := 20; self.Edit.Top := 15; self.Edit.OnKeyPress := self.EditKeyPress; end; procedure TLayerListItem.Paint; begin inherited; // hier komt eventueel wat tekenwerk end; procedure TLayerListItem.Click; var Layer: TDrawLayer; begin inherited; //self.Color := clHighLight; if self.Edit.Visible = true then begin Layer := LagenBeheerForm.CurrentDocument.Document.GetLayer( self.LayerID ); Layer.Name := self.Edit.Text; self.Edit.Visible := false; self.Caption.Caption := self.Edit.Text; self.Caption.Visible := true; end; end; procedure TLayerListItem.CaptionDblClick( Sender: TObject ); begin self.Caption.Visible := false; self.Edit.Text := self.Caption.Caption; self.Edit.Visible := true; end; procedure TLayerListItem.EditKeyPress( Sender: TObject; var Key: Char ); begin {ik hoor hier een irritante plong van mij os als ik op enter druk ??} if Key = #13 then begin self.Caption.Caption := self.Edit.Text; self.Edit.Visible := false; self.Caption.Visible := true; end; end; destructor TLayerListItem.Destroy; begin self.Edit.Free; self.Caption.Free; inherited; end; |
ik hoop dat mijn vragen en lappe codes niet vervelend zijn
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
1
2
3
| TLayerListItem(self.ListBox1.Items.Objects[Index]).BoundsRect := Rect; {wat is het verschil tussen deze 2 methodes want er komt gewoon hetzelfde uit ?} (self.LayerList.Items.Objects[Index] as TLayerListItem).BoundsRect := Rect; |
Als self.ListBox1.Items.Objects[Index] geen TLayerListItem is zal je in het eerste geval random fouten krijgen. In het 2e geval direct een exceptie dat het object op die manier niet gecast kan worden. De 2e manier is dus veiliger.
1
2
3
| {ik hoor hier een irritante plong van mij os als ik op enter druk ??} if Key = #13 then begin |
Voeg Key := #0; toe en je hoort het niet meer.
We adore chaos because we like to restore order - M.C. Escher
maar nog even over dat eerste. het zijn dus allebei typecasts?
Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition
We adore chaos because we like to restore order - M.C. Escher