Grafik, Events und anderes bei eigener Komponente
-
JBOpael schrieb:
Ja, habe aber mittlerweise rausgefunden wann on Paint aufgerufen wird.
Sehr aufschlussreich in bezug auf dein erstes Posting.
-
Da hast du wohl recht
Paint wird zur Laufzeit nur aufgerufen wenn TForm von etwas anderem verdeckt oder von minimiert zu maximiert wechselt.
-
Nicht ganz.
Du kannst jederzeit eine SendMessage mit WM_PAINT zur Komponente schicken...
-
Ich kann auch Paint direkt aufrufen.
Das Problem mit dem Event hat sich auch fast gelöst. hab das DYNAMIC davor vergessen. Ich bekomme jetzt keine fehlermeldung aber auf den click reagiert er auch nicht.
-
Ansich läuft der Click-Code , aus einer Anwendung :
void __fastcall TForm1::MyGraph1MyOnClick(TObject *Sender, TPoint Position) { int x = Position.x; int y = Position.y; ShowMessage("Klick in x= " + IntToStr(x) + " und y = " + IntToStr(y)); // x, y sind hier noch Formularkoordinaten } //---------------------------------------------------------------------------
Hast was übersehen?
-
Ich weiß zwar nicht ob man übersehen nennen kann.hab durch zufall raus gefunden wenn der Component Owner von TGraphicControl kommt, Funktioniert es nicht und wenn der Owner von TWinControl kommt dann funktioniert es. Dasversteh ich zwar nicht ganz weil doch beide von TControl abgeleitet sind in der die Ereignisse und Events enthalten sind.
-
Hi,
Alternativ bietet sich an, die WndProc-Methode zu benutzen.
*.h
//--------------------------------------------------------------------------- #ifndef main_graphicH #define main_graphicH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <Buttons.hpp> //--------------------------------------------------------------------------- //typedef void __fastcall (__closure *MyClickEvent)(TObject *Sender,TPoint Position); class TForm1; class TMyGraph : public TGraphicControl { friend class TForm1; private: POINT points[5]; //MyClickEvent FMyOnClick; protected: void __fastcall WndProc(Messages::TMessage &Message); public: //void __fastcall MyOnClick(TObject *Sender, TPoint Position); /* void __fastcall Click() { TPoint point; GetCursorPos(&point); // Screen-Koordinaten if(FMyOnClick) FMyOnClick(this,point); TGraphicControl::Click(); } */ __property Canvas ; // Zugriff auf Canvas erlauben __fastcall TMyGraph(TComponent* Owner); }; //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // Komponenten, die von der IDE verwaltet werden TButton *Button1; TButton *Button2; TBitBtn *BitBtn1; TSpeedButton *SpeedButton1; TLabel *Label1; TLabel *Label2; void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); private: public: TMyGraph* MyGraph; __fastcall TForm1(TComponent* Owner); __fastcall ~TForm1(void); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif
*.cpp
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "main_graphic.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; __fastcall TMyGraph::TMyGraph(TComponent* Owner) : TGraphicControl(Owner) { Width = 120; Height = 120; Canvas->Brush->Color = clBlack; points[0].x = 0; points[0].y = 0; points[1].x = Width -1; points[1].y = 0; points[2].x = Width -1; points[2].y = Height -1; points[3].x = 0; points[3].y = Height -1; points[4].x = 0; points[4].y = 0; } //--------------------------------------------------------------------------- void __fastcall TMyGraph::WndProc(Messages::TMessage &Message) { switch(Message.Msg) { case WM_PAINT : { // Rahmen zeichnen Canvas->Pen->Color = clRed; Canvas->Polyline(points,4); } break; case WM_LBUTTONDOWN : { int X = (LPARAM) Message.LParamLo; int Y = (LPARAM) Message.LParamHi; // Ausgabe der Koordinaten Form1->Label1->Caption = "Klick bei X: " + IntToStr(X); Form1->Label2->Caption = "Klick bei Y: " + IntToStr(Y); } break; case WM_MOUSEMOVE : { int X = (LPARAM) Message.LParamLo; int Y = (LPARAM) Message.LParamHi; // Ausgabe der Koordinaten Form1->Label1->Caption = "X: " + IntToStr(X); Form1->Label2->Caption = "Y: " + IntToStr(Y); } break; } TGraphicControl::WndProc(Message); } //--------------------------------------------------------------------------- /* void __fastcall TMyGraph::MyOnClick(TObject *Sender, TPoint Position) { int x = Position.x; int y = Position.y; ShowMessage("Klick in x= " + IntToStr(x) + " und y = " + IntToStr(y)); TGraphicControl::Click(); } */ //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { MyGraph = new TMyGraph(this); MyGraph->Left = 10; MyGraph->Top = 10; MyGraph->Parent = Form1; } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1(void) { delete MyGraph; } //---------------------------------------------------------------------------
Die erste Variante Klick-Event ist kommentiert.
mfg
kpeter
-
Hmm... damit kann man schon was anfangen
Wenn ich jetzt mit Canvas eine Linie Male, kann ich dann auch rausfinden ob die Maus gerade auf der Linie ist, oder muss ich das über X/Y coordinaten selber raus suchen?
nachdem was ich so in der BCB Hilfe gelesen habe, könnte ich mit dem HDC Handle von Canvas vielleicht etwas machen, aber habe nicht rausfinden können wie das gehen soll.
-
JBOpael schrieb:
Wenn ich jetzt mit Canvas eine Linie Male, kann ich dann auch rausfinden ob die Maus gerade auf der Linie ist, oder muss ich das über X/Y coordinaten selber raus suchen?
Eigentlich sollte es anders herum sein. Nach den Mauskoordinaten (oder Stift) wird eine Linie gezeichnet. Win API's LineDDA zb.
edit:
Damit hier keine Langeweile aufkommt
einfügen in *.cpp
// gleich unterhalb Form-Konstruktor VOID CALLBACK LineDDACallBack( int X, int Y, LPARAM lParam ) { Form1->MyGraph->Canvas->Pixels[X][Y] = RGB(0, 0, 0); // Koordinaten ausgeben ( und irgendwann speichern ...) // Gimmick Form1->Memo1->Lines->Add("X: " + IntToStr(X) + ", Y: " + IntToStr(Y)); } //--------------------------------------------------------------------------- // in WndProc vervollständigen case WM_MOUSEMOVE : { int X = (LPARAM) Message.LParamLo; int Y = (LPARAM) Message.LParamHi; LineDDA( oldx, oldy, X, Y, (LINEDDAPROC)LineDDACallBack, NULL ); oldx = X; oldy = Y; // Ausgabe der Koordinaten Form1->Label1->Caption = "X: " + IntToStr(X); Form1->Label2->Caption = "Y: " + IntToStr(Y); } break;
mfg
kpeter
-
Eigentlich sollte es anders herum sein. Nach den Mauskoordinaten (oder Stift) wird eine Linie gezeichnet. Win API's LineDDA zb.
Der Sinn dahinter ist ja das ich nicht nur eine Linie Malen kann, sondern diese Linie auch ändern, verschieben und vor allem zuordnen kann.
Mit dem was du geschieben hast, habe ich ein Problem. da ich das ja versuche in eine Komponente zu packe stoße ich bei dem Callback auf ein Problem.
Wenn ich den außerhalb meiner klasse als funktion anlege, funktioniert das ich komm aber dann nicht an mein Canvas dran. und wenn ich den Innerhalb meiner klasse anlege bekomme ich die Fehlermeldung:
[BCC32 Fehler] GraphicControl1.h(175): E2235 Elementfunktion muß aufgerufen oder ihre Adresse übernommen werden
weder die BCB Hilfe noch google gibt mir antworten darauf
-
Dann anders; anstatt LineDDA geht natürlich auch
// ersatzweise für CALLBACK LineDDA POINT points[2]; points[0].x = oldx; points[0].y = oldy; points[1].x = X; points[1].y = Y; this->Canvas->Polyline(points, 1); oldx = X; oldy = Y;
kpeter
-
Damit kann ich doch nur eine Linie zeichnen und keine gezeichnete Linie erkennen ?!
-
JBOpael schrieb:
gezeichnete Linie erkennen
Wie ist das gemeint?
-
Wenn ich mit Canvas eine Linie Zeichne und ich dann mit der Maus auf die linie gehe dann soll ein ereignis ausgelöst werden.
genau genommen will ich es hin bekommen das die linie einen Focus bekommen kann. quasi so wie man es von Grafikprogrammen kennt. Man malt eine Linie und wenn die Linie angeklickt wird erhält sie den Fokus und ich kann die Linie per maus noch vergrößern, verschieben etc.. So soll das endprodukt aussehen.
-
Linien zeichnen geht ja nun.
Verbunden mit WM_LBUTTONDOWN und WM_LBUTTONUP (Startpunkt/Endpunkt) können gerade Linien und geometrische Figuren gezeichnet
werden. Die Pixelpositionen bekommst du ja geliefert.Wo ist da das Problem?
-
Wenn ich jetzt mit Canvas eine Linie Male, kann ich dann auch rausfinden ob die Maus gerade auf der Linie ist, oder muss ich das über X/Y coordinaten selber raus suchen?
Das ist das was ich hier gefragt hatte. ich muss also die pixel coordinaten mit den Maus coordinaten vergleichen und wenn die die maus auf der linie ist das event auslösen.
-
Das bekommt man hin, Mauskoord. mit Liniekoord. vergleichen. Aber deshalb bekommt diese
Linie sicher keinen Fokus oder wird gar markiert.Das spielt jetzt wieder in den anderen Thread hinein...
mfg
kpeter
-
class TMyGraphic : public TGraphicControl { ... public: __fastcall TMyGraphic(TComponent* Owner) : TGraphicControl(Owner) { Widht=100; Height=100; } } class PACKAGE TGundgrafik : public TWinControl { private: TMyGraphic *MeineGrafik; public: __fastcall TGundgrafik(TComponent* Owner) :TWinControl(Owner) { MeineGrafik = new TMyGraphic(this); MeineGrafik->Parent=this; MeineGrafik->Left=0;//this->Left; MeineGrafik->Top=0;//this->Top; // MeineGrafik->Width=130;//this->Width ; // MeineGrafik->Height=130;//this->Height; } }
Beim Anlegen soll TMyGraphic so groß sein wie TGundgrafik.
1.Problem: Wie komme ich an die größe von Owner? Left, Widht etc ist im Konstruktor noch 0.
2. Problem: Wo muss ich das definieren. wenn ich das aus dem Konstuktor von TMyGraphic Weg lasse und bei TGundgrafik hinzufüge dann macht der das nicht.
-
Hi,
die Eigenschaft auf Align = alClient; setzen
edit:
an die Grösse kommst du über einen Zeiger:TForm1* MyOwner; MyOwner = static_cast<TForm1*>(Form1); int w = MyOwner->Width;
mfg
kpeter
-
Auf Align hätte ich auch selber kommen können
aber wiso ist im Konstruktor die breite des Objects noch nicht bekannt?
__fastcall TGundgrafik(TComponent* Owner) :TWinControl(Owner) { int breite=this->Widht; // breite ist 0 }