Autor Beitrag
D. Annies
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Do 22.01.09 10:48 
Hi, Delpher,

kleine Spielerei, aber warum ist die Linie nicht (dauerhaft) sichtbar?

Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
  listbox6.clear;  n := 0;
  with Listbox6.Items do
  begin
    while n < klmax-1 do
    begin
      inc(n);
      if total[n] > 0 then
      begin
        Add(Format('Personen in R%2d  : %3d = %3d / %3d ',
             [n, total[n],  female[n],  male[n]])); Add(' ');
      end;
    end;
    Add('----------------------------------');
  end;
  listbox6.Canvas.MoveTo(Left,Top);
  listbox6.Canvas.LineTo(clientrect.Right, clientrect.Bottom);


Danke für eine Idee/Abhilfe,
Detlef

_________________
ut vires desint, tamen est laudanda voluntas
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Do 22.01.09 10:59 
Hallo,

wo steht der Code?

Wenn er in einer Routine ausgeführt wird, kann es nicht funktionieren.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Do 22.01.09 17:33 
Hi, Lannes,

ja, der Code steht in einer Prozedur.

Und jetzt?

_________________
ut vires desint, tamen est laudanda voluntas
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 22.01.09 17:41 
Naja, sobald die ListBox neu gezeichnet wird, ist die Linie auch wieder weg.

Da es kein OnPaint bei der ListBox gibt, wäre die sinnvollste Möglichkeit, eine eigene abgeleitete Klasse zu erstellen, die dies beinhaltet. Ich vermute wo etwas gibt es auch im Netz.

// EDIT:
Ach ja: was Lannes meinte:
Mit Left und Top usw. greifst du ja nicht auf die Werte der ListBox zu, sondern auf die des Formulars...

// EDIT2:
Was auch gehen müsste um das neu zeichnen in den Griff zu bekommen:
WndProc überschreiben und auf WM_PAINT reagieren. ;-)
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Do 22.01.09 18:11 
Ich haben verstanden - ich lassen es! :nut:
Gruß, Detlef

_________________
ut vires desint, tamen est laudanda voluntas
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Do 22.01.09 18:11 
Hallo,

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
// EDIT:
Ach ja: was Lannes meinte:
Mit Left und Top usw. greifst du ja nicht auf die Werte der ListBox zu, sondern auf die des Formulars...
so in etwa, oder auch nicht :wink:

jetzt weis ich immer noch nicht wo genau der Code steht
a.
Der Code steht in ListBoxDrawItem = dort sollte man keine Einträge schreiben die ein Neuzeichnen auslösen

b.
Der Code steht in einer anderen Prozedur = dort sollte man nicht auf das canvas der Listbox zeichnen, den das wird übermalt wenn die interne Zeichenprozedur durch etwas anderes aufgerufen wird. z.B. ein überdecken der Listbox durch ein anderes Fenster.

Du kannst den Vorschlag von jaenicke (WndProc etc.) nehmen, ich meine es ist einfacher die Linie in ListBoxDrawItem zu zeichnen.
Was soll denn die Linie bezwecken?

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Do 22.01.09 18:27 
Hi, Lannes,

der Code steht in "b".
Entscheidend ist ja auch deine Frage, was bewirkt werden soll. --> Nichts, VOID, es ist wirklich nur eine Spielerei, deshalb lasse ich es auch. Wenn es wichtig wäre, würde ich mehr "beißen".

Vielen Dank für deine "Nachsorge",
Detlef

_________________
ut vires desint, tamen est laudanda voluntas
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 22.01.09 19:19 
user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
Nichts, VOID, es ist wirklich nur eine Spielerei
Na dann spiele ich mal mit :D
ausblenden Delphi-Quelltext
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:
  TForm137 = class(TForm)
    ListBox1: TListBox;
  private
    { Private declarations }
  public
    { Public declarations }
    procedure WndProc(var message: TMessage); override;
  end;

var
  Form137: TForm137;

implementation

{$R *.dfm}

procedure TForm137.WndProc(var message: TMessage);
begin
  inherited;
  if message.Msg = WM_PAINT then
  begin
    listbox1.Canvas.MoveTo(listbox1.Left,listbox1.Top);
    listbox1.Canvas.LineTo(listbox1.clientrect.Right, listbox1.clientrect.Bottom);
  end;
end;
Das funktioniert, wie ich schon vermutet hatte, wunderbar. ;-)

Durch das inherited an erster Stelle sorge ich dafür, dass die ListBox zuerst selbst ihre Sachen zeichnet und ich danach darüber zeichne.
D. Annies Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1843

windows 7
D6 Enterprise, D7 Pers und TD 2006
BeitragVerfasst: Do 22.01.09 20:41 
Sebastian, du bist "unmöglich" !!

Danke, Detlef

_________________
ut vires desint, tamen est laudanda voluntas
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 23.01.09 00:32 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das funktioniert, wie ich schon vermutet hatte, wunderbar. ;-)

Die Lösung ist leider trotzdem etwas schief geraten ;)

Du überschreibst die WndProc der MainForm, um darin ein Child-Control zu überzeichnen :O. Wieso das niemand so macht: ;)

- Um einzelne Messages abzufangen, würde man nicht die WndProc überschreiben, sondern eine message Prozedur definieren: procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

- Um das Neuzeichnen der MainForm abzufangen, würde man aber auch das nicht machen, sondern gleich das OnPaint-Event benutzen.

- Aber: Um das Neuzeichnen eines Child-Controls abzufangen, fängt man nicht die Paint-Message der MainForm ab, sondern wenn schon die des Child-Controls selbst, sofern das Child-Control natürlich kein eigenes Paint-Ereignis besitzt (was die TListBox ja tut, zu mindest für einzelne Items). Denn es kann sein, dass die MainForm gar nicht neugezeichnet werden muss, die ListBox aber schon.

- Bietet ein Control kein OnPaint an, sollte man das entsprechende Control erweitern, in dem man von ihr eine Ableitung macht, und dort entweder die Paint Methode überschreibt (sofern vorhanden), und falls nicht, eine message-Prozedur wie oben gezeigt definiert und von dort aus das selbstdefinierte OnPaint-Ereignis aufruft. Hier sollte man darauf achten, dass man die WinApi Doku beachtet.

- Wenn man "global" Messages abfangen muss, dann über Application.OnMessage. Dort würde man das Handle der Message überprüfen, ob es mit der der ListBox übereinstimmt, etc.. Die globale Lösung ist natürlich schlecht, aber so würde man es machen.


Zuletzt bearbeitet von delfiphan am Fr 23.01.09 00:39, insgesamt 1-mal bearbeitet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 00:37 
user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
- Bietet ein Control kein OnPaint an, sollte man das entsprechende Control erweitern, indem man entweder die Paint Methode überschreibt (sofern vorhanden), und falls nicht, eine message-Prozedur wie oben gezeigt definiert und von dort aus das selbstdefinierte OnPaint-Ereignis aufruft.
Das habe ich ja auch geschrieben, aber dann kann man eben keine Standard-ListBox verwenden. ;-)

Dass das in einem richtigen Anwendungsfall natürlich die bessere Lösung ist, ist klar.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 23.01.09 00:57 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das habe ich ja auch geschrieben, aber dann kann man eben keine Standard-ListBox verwenden. ;-)

Dass das in einem richtigen Anwendungsfall natürlich die bessere Lösung ist, ist klar.

Naja ;) Trotzdem hätte man ein korrektes Beispiel posten können...

Die ganze Paint-Geschichte über WM_PAINT ist genau genommen noch etwas komplizierter, da man den beim WM_PAINT übergebenen DC noch mit BeginPaint/EndPaint umgeben muss. Bei TWinControls übernimmt das PaintHandler, der dann PaintWindow aufruft. Einige dieser Methode sind virtual, können als überschrieben werden. Dort würde man dann dem Canvas das DC als Handle geben und das eigene Event aufrufen.

Und falls global, mit Original-Listbox und ohne VCL-Event, dann über Application.OnMessage. Dann muss man sich um die oben genannten Sachen jedoch selbst kümmern.