[delphi] tekenen op de canvas can de parent

Pagina: 1
Acties:
  • 172 views sinds 30-01-2008
  • Reageer

  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
beste mensen,

ik ben een programma aan het maken waarin je grafische modellen kan maken.
een kenmerk van zo'n programma is dat je erin moet kunnen tekenen :p.
nu heb ik zelf een object gemaakt (afgeleid van een TGraphicControl) die dienst doet als tekencanvas. en dat object (dus de grafische canvas) moet zichzelf tekenen op de parents canvas (die van het formulier), op het moment dat het object geinstantieerd wordt.

nu is mijn probleem dat ik vanuit de method van mijn canvasobject, de canvas van mijn formulier niet aan kan spreken.

mijn canvasclass staat in een losse unit. als ik dan refereer naar de unit van mijn formulier middels een uses clause, dan krijg ik een fout van een "circular reference". ik weet dus niet hoe ik mijn parent object aan kan spreken.

een mogelijke oplossing is om de parent zelf het object te laten tekenen door gewoon alle benodigde properties uit te lezen van zijn child. maar dat lijkt me niet echt een nette oplossing. ik wil dus dat het object zelf in staat is om zichzelf op de parents canvas te tekenen.

weet iemand hoe ik dit kan realiseren?

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


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:47

Tomatoman

Fulltime prutser

Dag Tombo_inc :w. Hier op GoT hoef je geen brieven te schrijven, de aanhef en ondertekening mag je achterwege laten. :)
nu is mijn probleem dat ik vanuit de method van mijn canvasobject, de canvas van mijn formulier niet aan kan spreken.

mijn canvasclass staat in een losse unit. als ik dan refereer naar de unit van mijn formulier middels een uses clause, dan krijg ik een fout van een "circular reference". ik weet dus niet hoe ik mijn parent object aan kan spreken.

een mogelijke oplossing is om de parent zelf het object te laten tekenen door gewoon alle benodigde properties uit te lezen van zijn child. maar dat lijkt me niet echt een nette oplossing. ik wil dus dat het object zelf in staat is om zichzelf op de parents canvas te tekenen.

weet iemand hoe ik dit kan realiseren?
Je zet unit A in de uses clause van unit B en wel in de interface sectie. Je zet unit B in de uses clause van unit A en wel in de implementation sectie.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unit A;

interface

uses
  B;

type
  TMijnButton = class(TButton);

var
  EenLabel: TMijnLabel;

implementation

end.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unit B;

interface

type
  TMijnLabel = class(TLabel);

implementation

uses A;

procedure Test(EenButton: TMijnButton);
begin
  EenLabel.Caption := EenButton.Caption;
end;

end.



De aanpak die je kiest lijkt me overigens nogal ingewikkeld. Als je op het canvas alle objecten moet tekenen, wat gebeurt er dan als er een object wordt verplaatst? Ga je dan alles opnieuw op je canvas tekenen? En wat doe je als het Form geresized wordt? Ga je dan ook alles opnieuw tekenen? Kun je niet veel beter ieder tekenobject in een eigen control gieten die je op het canvas plaatst?

[ Voor 6% gewijzigd door Tomatoman op 18-11-2005 22:43 ]

Een goede grap mag vrienden kosten.


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
ok, dus als je een uses clause opneemt in je implementatie dan kun je wel een mutual dependencie creeren. weer wat geleerd ;)

wat bedoel je precies met ieder object in een eigen control gieten?
ik hou nu gewoon een lijst bij met alle objecten die getekend moeten worden. en door middel van
het "invalidate" commando zorg ik dat het form steeds geupdate is/wordt. mis ik hier iets essentieels of kan het veel makkelijker/beter? (ik heb namelijk niet heel veel ervaring met tekenen in delphi)

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


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:47

Tomatoman

Fulltime prutser

Tombo_inc schreef op vrijdag 18 november 2005 @ 23:49:
wat bedoel je precies met ieder object in een eigen control gieten?
ik hou nu gewoon een lijst bij met alle objecten die getekend moeten worden. en door middel van
het "invalidate" commando zorg ik dat het form steeds geupdate is/wordt. mis ik hier iets essentieels of kan het veel makkelijker/beter? (ik heb namelijk niet heel veel ervaring met tekenen in delphi)
Wat jij doet werkt gewoon, het is zeker niet fout.

De performance kan echter problematisch worden als er veel getekend moet worden. Bovendien kan het heel complex worden. Stel dat je 100 vierkanten op je canvas wilt weergeven en dat je canvasgrootte afhankelijk is van de venstergrootte van het main form. Als de gebruiker het main form dan resizet, moeten die 100 vierkanten tijdens het resizen telkens opnieuw worden getekend (als je canvas een pixel breder of hoger wordt, leidt dat immers tot een OnPaint event). Dat is inefficiënt en leidt tot schermflikkering.

Een ander probleem kan zijn dat het allemaal moeilijk onderhoudbaar kan gaan worden. Straks wil je er misschien ook cirkels bij kunnen plaatsen. En nog wat later ook bitmaps. Of je wilt dat de de vierkanten ook rood en oranje kunnen worden, maar de cirkels alleen groen. Hoe ga je dat allemaal bijhouden in je tekenlijstje?

Een oplossing zou kunnen zijn dat je een descendant van TGraphicControl schrijft, die als base class geldt voor al jouw tekenobjecten. In TGraphicControl definieer je bijvoorbeeld een Color property. Daarna maak je een paar descendants van je TGraphicControl descendant, bijvoorbeeld TVierkant en TCirkel. Nu het eigenlijk tekenwerk. In plaats van allerlei dingen op een canvas te tekenen, plaats je een paar TVierkant en TCirkel objecten op het canvas. Als het canvas nu van maat wijzigt, regelt Delphi achter de schermen voor je dat alleen die objecten opnieuw getekend worden die ook daadwerkelijk veranderen door het resizen.

Een goede grap mag vrienden kosten.


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
ok dat snap ik. dat is dus bijna hetzelfde princiepe als wat ik nu heb. ik heb een baseclass voor alle grafische objecten. en iedere vorm is daar een afgeleide van. alle grafische objecten hou ik bij in een TList. en teken ik inderdaad met een onpaint.
het enige verschil met jouw oplossing is dus dat ik een TGraphicControl moet gebruiken als baseclass omdat delphi dan het tekenwerk voor me regelt. en dat ik op de canvas van die TGraphicControl mijn figuur moet tekenen. (correct me if i'm wrong)

nu is mijn vraag, hoe kan ik rechtstreeks een TGraphicControl op de Canvas van het forumlier plaatsen? (mssn een domme vraag maar ik kan het niet vinden)

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


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:47

Tomatoman

Fulltime prutser

Tombo_inc schreef op zaterdag 19 november 2005 @ 22:01:
ok dat snap ik. dat is dus bijna hetzelfde princiepe als wat ik nu heb. ik heb een baseclass voor alle grafische objecten. en iedere vorm is daar een afgeleide van. alle grafische objecten hou ik bij in een TList.
Aha, volgens het boekje. :)
[...] en teken ik inderdaad met een onpaint.
het enige verschil met jouw oplossing is dus dat ik een TGraphicControl moet gebruiken als baseclass omdat delphi dan het tekenwerk voor me regelt. en dat ik op de canvas van die TGraphicControl mijn figuur moet tekenen. (correct me if i'm wrong)
Correct.
nu is mijn vraag, hoe kan ik rechtstreeks een TGraphicControl op de Canvas van het forumlier plaatsen? (mssn een domme vraag maar ik kan het niet vinden)
Je plaatst de control niet op het canvas van het formulier, maar je plaatst de control op een andere control (via de Parent property). Je tekent vervolgens iedere control op zijn eigen canvas en laat het canvas van het formulier voor wat het is.

Als voorbeeld een eenvoudig stukje code. Op een form staan een TScrollBox - die ScrollBox heet - en een TButton. Telkens als op de button wordt geklikt, wordt er in de scrollbox een TPaintBox bijgeplaatst. Het tekenwerk van iedere paint box gebeurt met de OnPaint handler van de paint box. De scrollbox is een tamelijk willekeurig keuze om paint boxen in te plaatsen, je kunt net zo goed alles op het TForm gooien of op een TPanel. Alle paint boxen worden bijgehouden in een TComponentList (waar ik in dit voorbeeldje verder niets mee doe).
Delphi:
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
unit Unit1;

interface

uses
  Classes, Graphics, Controls, Forms, StdCtrls, ExtCtrls, Contnrs;

type
  TForm1 = class(TForm)
    ScrollBox: TScrollBox;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FPaintBoxList: TComponentList;
    procedure PaintBoxPaint(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  FPaintBoxList := TComponentList.Create(True);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  { Als FPaintBoxList vernietigd wordt, worden meteen alle PaintBoxes in de
    list vernietiegd. }
  FPaintBoxList.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Box: TPaintBox;
begin
  Box := TPaintBox.Create(nil);
  with Box do
  begin
    { Kleur van de brush kiezen en de OnPaint handler toewijzen }
    Tag := Random($FFFFFF); // Tag gebruiken voor de random te kiezen kleur
    OnPaint := PaintBoxPaint;

    { Ergens random in de scrollbox plaatsen }
    Left := Random(ScrollBox.ClientWidth - Width);
    Top := Random(ScrollBox.ClientHeight - Height);
    Parent := ScrollBox;
  end;
  FPaintBoxList.Add(Box);
end;

procedure TForm1.PaintBoxPaint(Sender: TObject);
var
  Box: TPaintBox;
begin
  Box := Sender as TPaintBox;
  with Box do
  begin
    Canvas.Brush.Color := TColor(Tag); // Kleur staat in de tag
    Canvas.FillRect(ClientRect);       // De complete paint box inkleuren
  end;
end;

end.
Overigens is TPaintBox een descendant van TGraphicControl. De reden om een TGraphicControl descendant te gebruiken is dat TGraphicControl een TCanvas introduceert.

Een goede grap mag vrienden kosten.


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
aha, ik denk het wel te snappen ja :P.
wat jij dus doet is onclick een nieuw object maken. die volproppen met wat waarden en waar het om gaat, hem een parent toewijzen. en dan zou het dus goed moeten zijn :) . verder maak je dus voor ieder object een eigen onpaint handler aan die beschrijft hoe het grafische object getekend moet worden. dus een onpaint voor een "TVierkant" is anders dan een onpaint voor een "TDriehoek" (concludeer ik uit je voorbeeld). dat is iets anders dan wat ik deed, maar wel veel efficienter. (stom dat ik daar zelf nooit opgekomen ben |:( )
hartstikke bedankt alvast, ik ga het meteen proberen. B)

er is nog een ding dat ik niet snap. en wel deze regel:
Delphi:
1
Box := Sender as TPaintBox;

zou je die eens uit kunnen leggen?

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


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 23:32

Creepy

Tactical Espionage Splatterer

die "as" is in feite hetzelfde als een cast. Echter zal er nu een Exception worden gegenereerd zodra de Sender niet een echte TPainBox is. Zonder cast of zonder as kan je de toekenning niet maken.

"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


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
aha weer wat geleerd, en je wil dus dat het object zelf zijn onpaint aanroept en dus maak je het object zelf de sender. of begrijp ik dat verkeerd?

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


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:47

Tomatoman

Fulltime prutser

In de Delphi helpfile kun je bij het onderwerp "Sender parameter" het volgende lezen:
In an event handler, the Sender parameter indicates which component received the event and therefore called the handler. Sometimes it is useful to have several components share an event handler that behaves differently depending on which component calls it. You can do this by using the Sender parameter in an if...then...else statement. For example, the following code displays the title of the application in the caption of a dialog box only if the OnClick event was received by Button1.

Delphi:
1
2
3
4
5
6
7
8
procedure TMainForm.Button1Click(Sender: TObject);
begin
  if Sender = Button1 then  
    AboutBox.Caption := 'About ' + Application.Title    
  else 
    AboutBox.Caption := ''; 
  AboutBox.ShowModal;
end;

Een goede grap mag vrienden kosten.


Verwijderd

tomatoman schreef op zaterdag 19 november 2005 @ 00:20:
[...]
De performance kan echter problematisch worden als er veel getekend moet worden. Bovendien kan het heel complex worden. Stel dat je 100 vierkanten op je canvas wilt weergeven en dat je canvasgrootte afhankelijk is van de venstergrootte van het main form. Als de gebruiker het main form dan resizet, moeten die 100 vierkanten tijdens het resizen telkens opnieuw worden getekend (als je canvas een pixel breder of hoger wordt, leidt dat immers tot een OnPaint event). Dat is inefficiënt en leidt tot schermflikkering.
Volgens mij is bovenstaande niet waar, of op z'n minst een non-argument. Immers, als een gebruiker het mainform resized, zullen altijd en in elk geval, ongeacht van de implementatie, alle vierkanten opnieuw getekend moeten worden.

Het schermflikkeren is te voorkomen door bij het eerste object wat je update ervoor te zorgen dat wijzigingen pas aan het eind doorgevoerd worden.

Voor de rest sluit ik me aan bij je opmerkingen, maar vond dit ene puntje toch relevant, sorry :)

[ Voor 31% gewijzigd door Verwijderd op 21-11-2005 23:39 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:47

Tomatoman

Fulltime prutser

Verwijderd schreef op maandag 21 november 2005 @ 23:38:
[...]
Volgens mij is bovenstaande niet waar, of op z'n minst een non-argument. Immers, als een gebruiker het mainform resized, zullen altijd en in elk geval, ongeacht van de implementatie, alle vierkanten opnieuw getekend moeten worden.
Als je al het tekenwerk op één canvas zou doen, zou bij elke vergroting van het canvas het complete canvas opnieuw getekend moeten worden. Bij het gebruik van afzonderlijke controls met elk hun eigen canvas gaat dit echter veel subtieler, lees: efficiënter. :)

Neem nog even mijn voorbeeldcode. De TScrollBox is ingesteld op Align = alClient en in de OnPaint handler heb ik drie regels code toegevoegd:
Delphi:
69
70
71
  { Piepen als de eerste paint box getekend wordt }
  if Box = FPaintBoxList[0] then
    Beep;

Telkens als het eerste vierkant opnieuw getekend wordt, hoor je nu een piep. In onderstaande schermafdruk is het eerste vierkante paars:

Afbeeldingslocatie: http://img515.imageshack.us/img515/5019/resize3sz.jpg

Als je nu het form met de cursor breder maakt, hoor je niets. Blijkbaar wordt het paarse vierkant niet opnieuw getekend. Maar als je het form eerst dusdanig smaller maakt dat het paarse vierkant nog maar gedeeltelijk zichtbaar is en het form daarna weer verbreedt, hoor je wel degelijk een hele rij piepjes. Blijkbaar wordt het paarse vierkant nu wel opnieuw getekend.

Hoe kan dit? Achter de schermen zullen alleen de regions waar daadwerkelijk wat opnieuw getekend moet worden geïnvalideerd worden. In de schermafdruk kun je duidelijk zien dat bij het breder maken van het venster het paarse vierkant ongewijzigd blijft. Windows weet dit ook een zal daarom het vierkant niet invalideren, zodat er geen OnPaint event volgt.

Jaja hezik, het is dus echt efficiënter. Vooral omdat tekenwerk relatief veel CPU cycles kost. :)

Een goede grap mag vrienden kosten.


Verwijderd

Ik ben toevallig ook met een projectje bezig waar de gebruiker met de standaard tekenfuncties zelf kan tekenen, en ik dacht ook aan om voor elke tekening een aparte container te gebruiken. Dat zou een hoop dingen veel makkelijker maken:
-minder/geen opnieuw tekenen bij veranderingen in andere tekeningen
-geen opnieuw tekenen bij verplaatsen object (alleen de coordinaties van de container veranderen)
-geen opnieuw tekenen bij veranderen z-order (alleen de z-order van de containers veranderen)

Maar het gebruik van aparte containers heeft 1 groot nadeel:
-Sommige tekenfuncties hebben invloed op wat er al op de canvas staat getekend. Sommige vullen een bepaalde kleur in als ze die tekenkomen, of ze wisselen elke kleur om. Dit werkt natuurlijk niet als elk object zijn eigen container/canvas heeft. Dit effect zou je misschien nog kunnen simuleren, maar toch kan je dan niet garanderen dat alles hetzelfde uit zou zien als ze dezelfde canvas zouden gebruiken.

  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
ok :), mijn eerste probleem is nu opgelost en alles werkt nu perfect.
ik heb alleen een tweede probleem waar ik niet uit kom.
ik heb nu globaal gezien de volgende situatie.

een formulier:
Delphi:
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
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,unit2;

type
  TForm1 = class(TForm)

  private
    { Private declarations }
  public
    { Public declarations }
    blaat: TMijnObject;

    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);
    self.blaat := TMijnObject.create(AOwner);
end;

end.


en een bestand met een class erin:
Delphi:
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
unit Unit2;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,ExtCtrls;

type
 TMijnObject = class(TPaintBox)

  constructor Create(AOwner: TComponent); override;
  procedure MijnObjectPaint;
 end;

var
MijnObject: TMijnObject;

implementation

uses unit1;

constructor TMijnObject.Create(AOwner: TComponent);
  begin
   inherited create(AOwner);
   //self.OnPaint := {??} { moet ik hier iets mee? } 
   self.Left := 10;
   self.Top := 10;
   self.Width := 200;
   self.Height := 200;
   self.Canvas.MoveTo(20,20);       // hier doet ie ook moeilijk
   self.Canvas.LineTo(100,100);     // exeption: {control has no parent window }
  end;

  procedure TMijnObject.MijnObjectPaint;
  begin

      {hier moet dan een figuur op eigen canvas worden getekend
      maar ik krijg deze onpaint niet aan de gang.}
      self.Canvas.MoveTo(20,20);
      self.Canvas.LineTo(100,100);
  end;
end.


wat ik nu voor mekaar gestumperd probeer te krijgen is het volgende.
ik heb een form. dit form heeft een child object dat ik zelf gemaakt heb. het childobject is afgeleid van een TPaintBox. het childobject word aangemaakt op het moment dat het form ook gemaakt wordt. nu wil ik op de canvas van dat childobject een tekening maken, met behulp van het onpaint event. en omdat het een eigen control is en bij als child op het form staat, zou delphi hem nu ook moeten tekenen als ik alles goed begrepen heb. ik hoop dat ik het duidelijk uitgelegd heb.

mijn probleem is nu dat ik die onpaint niet getriggerd krijg of op zijn minst niet gekoppeld krijg aan mijn eigen procedure die dan uitgevoerd moet worden. ik heb voor mijn gevoel zo'n beetje alles geprobeerd, behalve het juiste dus :? zou iemand me kunnen helpen.

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


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Dus je wilt runtime een event zetten? Zie http://www.nldelphi.com/f...read.php?s=&threadid=2443

Maar je kan ook een TPanel of nog beter: een TGraphicControl nemen en de Paint method overriden.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

tomatoman schreef op dinsdag 22 november 2005 @ 00:02:
Jaja hezik, het is dus echt efficiënter. Vooral omdat tekenwerk relatief veel CPU cycles kost. :)
Neenee tomatoman, het principe wat jij beschrijft is niet efficienter. In de praktijk blijkt die methode efficienter omdat de bouwers van Delphi/Windows wat optimalisatietruukjes hebben uitgehaald. DAT is de reden waarom het efficienter is, niet vanwege het onderliggende systeem.

Niets weerhoudt je ervan diezelfde optimalisaties zelf toe te voegen.

Voor alle duidelijkheid: ik vind jouw methode ook beter, waarom zelf het wiel uitvinden als het er al is? Dat neemt niet weg dat je eerste verklaring waarom dat efficienter zou zijn, domweg niet waar is.

Sterker nog.. als ik ga optimaliseren is 'mijn' methode juist sneller, omdat er minder overhead inzit. Als je een goede programmeur één canvas geeft en de verantwoordelijkheid daar alles zelf op te tekenen, is dat per definitie efficienter dan 'jouw systeem'. Simpelweg omdat in de 'één-canvas-methode" minder overhead besloten zit.

Een simpel voorbeeld hiervan zijn events. Zodra je het op 'jouw manier' gaat doen, zal hij een hoop events moeten controleren of deze ook gezet zijn. Events die overbodig zijn binnen dit specifieke project, maar die vanwege de generieke aard vd. gebruikte componenten wel aanwezig zijn. Als je e.e.a. zelf maakt, zul je die events nooit toevoegen en raak je er dus ook geen cycles aan kwijt..

[ Voor 37% gewijzigd door Verwijderd op 22-11-2005 19:06 ]


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
LordLarry schreef op dinsdag 22 november 2005 @ 18:56:
Dus je wilt runtime een event zetten? Zie http://www.nldelphi.com/f...read.php?s=&threadid=2443

Maar je kan ook een TPanel of nog beter: een TGraphicControl nemen en de Paint method overriden.
mijn object is een afgeleide van een TPaintBox, en dat is op zijn beurt weer een afgeleide van een TGraphicControl. en als ik het goed heb dan roept de paint method alleen een onpaint event aan.
wat dus bij mij niet gebeurt, of het gebeurd wel maar dan heb ik mijn onpaint niet goed gelinked. in ieder geval lukt het me niet om onpaint te tekenen. ik moet dus op de een of andere manier die onpaint van het object aan de gang krijgen.
en ik zal je link eens bekijken ;)

ik heb even naar je link gekeken. en daar zie ik dat ze hetzelfde doen als tomatoman in zijn voorbeeld. namelijk een procedure schrijven en die toewijzen aan het object.
vb: obj.onpaint := blaat();
dit heb ik ook geprobeerd, maar blijkbaar doe ik iets fout. want de onpaint word helemaal niet aangeroepen bij mij. als iemand nog een idee heeft hoor ik het graag :) , want volgens mij moet het gewoon kunnen.

[ Voor 47% gewijzigd door tombo_inc op 22-11-2005 21:30 ]

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


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Ja, dat is want een TPaintBox doet. Maar aangezien jij een afgeleide maakt van de TPaintBox en zelf het event gaat gebruiken kan je net zo goed een TGraphicControl nemen en de Paint method overriden. Maar goed, dat is je eigen keus.

Wat jij niet in je code doet is het OnPaint event koppelen aan de method MijnObjectPaint. Dat zal je ook nooit lukken, want een de method die OnPaint verwacht bevat parameters en die heeft jouw method niet. Zie de url die ik je gaf voor meer uitleg en een voorbeeld.

We adore chaos because we like to restore order - M.C. Escher


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
ik zal mijn hersenen er nog eens even over laten kraken :p
waarschijnlijk ben ik gewoon iets heel simpels vergeten, want volgens mijn logica O-) zou deze structuur toch moeten werken.

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


  • tombo_inc
  • Registratie: December 2004
  • Laatst online: 10-03 13:21
zo het is me eindelijk gelukt :Y) .
zoals ik al dacht was het gewoon een stomme fout. ik was namelijk wat parameters vergeten.
ff scheef gekeken dus. bedankt voor de hulp allemaal _/-\o_ .

ik heb nu de volgende werkende code:
Delphi:
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
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,unit2;

type
  TForm1 = class(TForm)

  private
    { Private declarations }
  public
    { Public declarations }
    blaat: TMijnObject;

    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);
    self.blaat := TMijnObject.create(AOwner);
end;

end.

Delphi:
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
unit Unit2;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,ExtCtrls;

type
 TMijnObject = class(TPaintBox)

  constructor Create(AOwner: TComponent); override;
  procedure MijnObjectPaint(Sender: TObject);
 end;

var
MijnObject: TMijnObject;

implementation

uses unit1;

constructor TMijnObject.Create(AOwner: TComponent);
  begin
   inherited create(AOwner);
   self.OnPaint := MijnObjectPaint;
   self.Parent  := Form1;
   self.Left    := 10;
   self.Top     := 10;
   self.Width   := 200;
   self.Height  := 200;
  end;

  procedure TMijnObject.MijnObjectPaint(Sender: TObject);
  begin
      self.Canvas.MoveTo(20,20);
      self.Canvas.LineTo(100,100);
  end;

end.


ik heb alleen nu nog een vraag. B)
waarom moet je het object (blaat:TMijnObject) nog een parent toewijzen? want het is toch al een child van Form1. of mis ik nu weer iets. :?

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


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Omdat je alleen een Owner meegeeft via de constructor. Een Owner hoeft niet het component te zijn waarop de paintbox wordt getekend. Dus daarom moet je ook nog een Parent zetten.

We adore chaos because we like to restore order - M.C. Escher

Pagina: 1