programm problem mit code



  • oha, natürlich, einach den zeiger kopieren! 😞

    danke für den atritt

    ok, speicherproblem bleibt bestehen, hängt jetzt aber mit grünem pfeil in dieser zeile:

    ListBox2->Items->Add(my->Name);
    

    jetzt irgendwelche ideen?

    gruß gerd



  • Vielleicht ist FindChildControl() nicht das richtige. Versuch's mal mit FindComponent() und (wie vorher im Edit gesagt)
    prüfe, ob Du auch einen Wert zurückbekommst. Das könntest Du aber auch im Debugger sehen.

    Gruß,

    Alexander



  • danke, werde es probieren.

    zumindest bekomme ich mit findchildcontrol bei den labels nichts zurück!

    gruß gerd



  • aber da bekomme ich nicht die positionen heraus, da left und sowas erst ab TControl enthalten sind!

    gruß gerd



  • so, habe mal nen neues projekt gestartet, und siehe da, speicherfehler treten nur noch bei den labels auf, da bekomme ich irgendwie keine daten zurück über die findchildcontrol() funktion.

    ansonsten läuft es rund

    gruß gerd



  • gerd01 schrieb:

    aber da bekomme ich nicht die positionen heraus, da left und sowas erst ab TControl enthalten sind!

    TControl* ctrl = dynamic_cast<TControl*> (FindComponent("Tritratrulala")); // Oder statt TControl TLabel o.ä.
    if (ctrl != 0)
    {
       // Was immer Du willst
    }
    

    Gruß,

    Alexander



  • super das ein cast so auch funktioniert wusste ich noch nicht, danke. werde es mal versuchen.

    so nun noch eine antwort auf meine dritte frage:

    frage 3:
    wie man ja unschwer erkennt sollen die elemente der form „markiert” werden, um sie eventuell zu verschieben, ähnlich der IDE des bcb. gibt es grundsätzlich eine fertige api-funktionalität, die mir so etwas ermöglicht? (ich kann mir nicht vorstellen das das über objekte (siehe hier shape1) der form passiert!?) also exakt so wie beim bcb? (so wie auch zum beispiel bei einer verschiebenung eines toolbars)?

    wenn ja, könnte mir da jemand ein simples beispiel geben?

    gruß gerd



  • so, habe auch den speicherfehler aufgedeckt:

    wenn man die components durchläuft muss man einen abziehen, steht zumindest im beispielcode der hilfe, dann stürzt es auch nicht mehr ab. 🙂

    gruß gerd



  • Hallo,

    Ich habe mir nun mal nicht alle 3 Seiten durchgelesen und weiss jetzt nicht, ob es schon eine Lösung gibt, aber mir ist folgendes aufgefallen :

    Das geht so oder so nicht :
    Du kannst nicht Components durchzählen und Controls benutzen.
    Außerdem kann das new weg.
    [cpp]
    TControl *ChildControl = new TControl(Application);
    for(int i=0; i < this->ComponentCount; i++)
    {
    ChildControl = this->Controls[i];
    if(ChildControl->Visible)
    ListBox1->Items->Add(ChildControl->Name);
    }
    [/cpp]

    Wenn dann so :

    [cpp]
    TControl *ChildControl;
    for (int i=0; i < ControlCount; i++)
    {
    ChildControl = Controls[i];
    if (ChildControl->Visible)
    ListBox1->Items->Add(ChildControl->Name);
    }
    [/cpp]

    Bis dann denn,
    🙂
    Nash



  • Nash schrieb:

    Wenn dann so :

    Wenn ich das richtig sehe, dann bekommt man mit Controls[] nur die untergeordneten Controls - also Controls, deren
    Parent-Eigenschaft in diesem Fall das Formular ist. Willst Du aber auch einen Button, der auf einem Panel liegt und
    dann folglich als Parent eben dieses Panel hat, erreichen musst Du die gesamte Control-Hierarchie durchschreiten.
    Mit Components bekommt man automatisch alle Komponenten, die auf dem Formular liegen. Hat man - wie in diesem Fall -
    den Namen der Komponente zur Hand, dürfte FindComponent() der einfachste Weg sein, auch wenn man casten muss, um
    an die gewünschten Eigenschaften zu kommen.
    Interessant in dem Zusammenhang könnte außerdem noch ControlAtPos() sein (wieder nur für Unter-Controls), womit man
    das Control anhand der Maus-Position ermitteln kann. Das könnte für Verschiebezwecke ganz praktisch sein.

    gerd01 schrieb:

    wenn man die components durchläuft muss man einen abziehen, steht zumindest im beispielcode der hilfe

    Die Hilfe bezieht sich doch nur auf die (beinahe schon triviale) Eigenart, dass der erste Index bei 0 und nicht bei
    1 beginnt. Was hast Du denn jetzt gemacht?

    Gruß,

    Alexander



  • die for-schleife mit "componentcount-1" laufen lassen, und schon klappt alles! er hatte an dieser stelle dann den index überschritten, aber dein casting vefahren habe ich eingebunden, scheint zu funzen. danke.

    gruß gerd



  • Hallo,

    Oops...
    Das kommt davon, wenn man das nicht selber ausprobiert und mal schnell zwischendurch antwortet. Natürlich immer bis Count minus 1. 🙂

    [cpp]TControl *ChildControl;
    for (int i=0; i < ControlCount - 1; i++)
    {
    ChildControl = Controls[i];
    if (ChildControl->Visible)
    ListBox1->Items->Add(ChildControl->Name);
    }[/cpp]

    Bis dann denn,
    🙂
    Nash



  • Ich verstehe nicht dieses Problem mit ComponentCount - 1 bzw. ControlCount - 1. 😕
    So wie von Nash vorgeschlagen...

    Nash schrieb:

    [cpp]TControl *ChildControl;
    for (int i=0; i < ControlCount - 1; i++)
    {
    ChildControl = Controls[i];
    if (ChildControl->Visible)
    ListBox1->Items->Add(ChildControl->Name);
    }[/cpp]

    ... wird doch wohl ein Control unterschlagen?

    Zum Test habe ich mal einfach eine neue Anwendung erstellt, ein Panel (Panel1) darauf platziert und
    auf diesem wiederum (nur zum Test) ein Label (Label1) und einen Button (Button1). Außerdem liegt
    direkt auf dem Form noch ein Memo (Memo1) und ein weiterer Button (Button2), in dessen OnClick-Ereignis
    ich folgendes geschrieben habe:

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
       Memo1->Lines->Clear();
       Memo1->Lines->Add("List of components");
       Memo1->Lines->Add("---------------------------");
       for (int i = 0; i < ComponentCount; ++i)
       {
          Memo1->Lines->Add(Components[i]->Name);
       }
       Memo1->Lines->Add("");
       Memo1->Lines->Add("List of controls");
       Memo1->Lines->Add("---------------------------");
       for (int i = 0; i < ControlCount; ++i)
       {
          Memo1->Lines->Add(Controls[i]->Name);
       }
    }
    

    Es gibt hier keinerlei Exceptions o.ä. und im Memo steht nach Anklicken des Button2:

    List of components
    ---------------------------
    Panel1
    Label1
    Button1
    Memo1
    Button2

    List of controls
    ---------------------------
    Panel1
    Memo1
    Button2

    Wie man erkennt werden - korrekterweise - insgesamt die vorher erwähnten fünf Komponenten aufgelistet
    und die 3 Unter-Controls des Formulars. Da Label1 und Button1 auf dem Panel1 liegen erscheinen sie
    nicht in der Controls-Auflistung des Formulars.

    Was passiert denn da bei Euch?

    Gruß,

    Alexander



  • stimmt, die minus eins ist nicht entscheident, irgenwie hakt mein proggie immer noch, wenn ich zu schnell ein andere control wähle!

    mache ich es langsam, dann klappt auch! *wunder* *kopfkratz*

    gruß gerd



  • also ich raffe es nicht, sollte doch jetzt eigentlich funzen, nur irgendwie bekomme ich immer nen komisches fenster unter winxp, erst ist der rahmen des fensters normal, dann ändert er sich irgendwann. auch wenn ich langsam klicke?!

    hier nochmal mein kompletter quellcode

    header:

    //---------------------------------------------------------------------------
    
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// Von der IDE verwaltete Komponenten
        TListBox *ListBox1;
        TListBox *ListBox2;
        TLabel *Label1;
        TLabel *Label2;
        TCheckBox *CheckBox1;
        TButton *Button1;
        TEdit *Edit1;
        TGroupBox *GroupBox1;
        TPanel *p;
        TListBox *ListBox3;
        TShape *Shape1;
        void __fastcall ListBox1Click(TObject *Sender);
        void __fastcall FormCreate(TObject *Sender);
        void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,
              TShiftState Shift, int X, int Y);
        void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift,
              int X, int Y);
        void __fastcall FormMouseUp(TObject *Sender, TMouseButton Button,
              TShiftState Shift, int X, int Y);
        void __fastcall pMouseDown(TObject *Sender, TMouseButton Button,
              TShiftState Shift, int X, int Y);
    private:	// Anwender-Deklarationen
    public:		// Anwender-Deklarationen
        __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    

    quellcode:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    bool Start=false; // im moment unwichtig
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::ListBox1Click(TObject *Sender)
    {
        ListBox2->Items->Clear();
        TControl* ctrl;
        // Objekte mit Panel durchlaufen
        for( int i = 0 ; i < p->ControlCount ; i++ )
        {
            ctrl = dynamic_cast<TControl*> ( FindComponent( p->Controls[i]->Name ) );
            if( ctrl->HasParent() && ctrl != 0 )
            {
                p->Controls[i]->Left = p->Left + 5;
                p->Controls[i]->Top = p->Top + 5;
                p->Controls[i]->Parent = this;
                p->Left += 5;
                p->Top += 5;
                p->Width -= 5;
                p->Height -= 5;
            }
        }
        ctrl = dynamic_cast<TControl*> (FindComponent(ListBox1->Items->Strings[ListBox1->ItemIndex]));
        // Objekt mit Panel hinterlegen
        if ( ctrl != 0 )
        {
            ListBox2->Items->Add(ctrl->Name);
            p->Left = ctrl->Left - 5;
            p->Top = ctrl->Top - 5;
            p->Width = ctrl->Width + 10;
            p->Height = ctrl->Height + 10;
            ctrl->Parent = p;
            ctrl->Left = 5;
            ctrl->Top = 5;
            ctrl->Width = p->Width - 10;
            ctrl->Height = p->Height - 10;
            p->Visible = true;
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
        for( int i=0; i < this->ControlCount ; i++ )
        {
            if( this->Controls[i]->Visible )
                ListBox1->Items->Add( this->Controls[i]->Name );
            this->Controls[i]->Visible = true;
        }
        Shape1->Visible = false;
        p->Visible = false;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
    //    Start = true;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
          int X, int Y)
    {
    /*    if(Start)
        {
            //Shape1->Width = X - Shape1->Left;
            //Shape1->Height = Y - Shape1->Top;
        }*/
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
    /*    ListBox2->Items->Clear();
        TRect rectc,rects;
        for( int i=0; i < this->ControlCount; i++ )
        {
            if( this->Controls[i]->Name != "Shape1" )
            {
                rectc = this->Controls[i]->BoundsRect;
                rects = Shape1->BoundsRect;
                if (rectc.Left >= rects.Left && rectc.right <= rects.right && rectc.Bottom <= rects.bottom && rectc.top >= rects.top)
                    ListBox2->Items->Add(this->Controls[i]->Name);
            }
        }
        Start=false;*/
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::pMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
        ReleaseCapture();
        SendMessage(dynamic_cast <TPanel*>(Sender)->Handle,WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    }
    //---------------------------------------------------------------------------
    

    vielleicht noch ne idee?

    gruß gerd



  • Was veranstaltest Du denn in ListBox1Click()? 😕
    Vielleicht kannst Du davon mal eine kommentierte Version posten.

    Es wäre bestimmt sehr hilfreich (nicht nur für außenstehende), den Variablen aussagekräftigere Namen als
    Listbox1 oder p zu geben. Dann würde sich der Code wie normaler Text lesen lassen. Man könnte auch sagen:

    Jetzt ist es Quell-Code, dann wäre es (vielleicht) Quell-Text.

    Vielleicht würdest Du dann auch selbst besser erkennen, wo Dein(e) Fehler liegt/liegen.

    Aber ein heißer Kandidat scheint mir auf jeden Fall ListBox1Click() zu sein. Versuche doch mal die Routine
    in zusammengehörige Blöcke zu zerlegen und diese Blöcke zu beschreiben.

    Gruß,

    Alexander



  • hi, ich finde es eigentlich sehr logisch?! du nicht? 🙂

    // Zur weiteren Darstellung erstmal leeren    
        ListBox2->Items->Clear();
        // Zeiger für Objektreferenz holen
        TControl* ctrl;
        /* Objekte auf dem Panel durchlaufen und schauen, ob Objekt vorhanden,
           wenn ja, dann die Position des Objektes zurückholen durch Panelposition,
           und Form wieder zum parent des objektes machen.*/
        for( int i = 0 ; i < p->ControlCount ; i++ )
        {
    
            ctrl = dynamic_cast<TControl*> ( FindComponent( p->Controls[i]->Name ) );
            // hat die kompo eine elternkompo
            if( ctrl->HasParent() && ctrl != 0 )
            {
                // wenn ja pos setzen und elternkompo auf form setzen
                p->Controls[i]->Left = p->Left + 5;
                p->Controls[i]->Top = p->Top + 5;
                p->Controls[i]->Parent = this;
                // rahmenbreite zurücksetzen falls element zweimal ausgeählt wird.
                p->Left += 5;
                p->Top += 5;
                p->Width -= 5;
                p->Height -= 5;
            }
        }
        // gewähltes element aus liste wählen
        ctrl = dynamic_cast<TControl*> (FindComponent(ListBox1->Items->Strings[ListBox1->ItemIndex]));
        // Objekt mit Panel hinterlegen
        if ( ctrl != 0 )
        {
            // Namen schreiben
            ListBox2->Items->Add(ctrl->Name);
            // Panelgröße und pos anpassen
            p->Left = ctrl->Left - 5;
            p->Top = ctrl->Top - 5;
            p->Width = ctrl->Width + 10;
            p->Height = ctrl->Height + 10;
    
    /* Panel wird elternkompo des objektes, damit dahinter ein panel liegt, wegen dem benötigten handle in "OnpMouseDown(..)" */
    
            ctrl->Parent = p;
    
            //Da Panelbereich überall 5px überstehen soll, hier neu pos setzen
            ctrl->Left = 5;
            ctrl->Top = 5;
            ctrl->Width = p->Width - 10;
            ctrl->Height = p->Height - 10;
            p->Visible = true;
        }
    


  • Hallo,

    Oops...
    Das kommt davon, wenn man das nicht selber ausprobiert und mal schnell zwischendurch antwortet.

    Na toll... und Fernsehen sollte man auch nicht. Sorry... 🤡

    TControl *ChildControl;
    for (int i=0; i < ControlCount; i++) 
    { 
      ChildControl = Controls[i]; 
      if (ChildControl->Visible) 
        ListBox1->Items->Add(ChildControl->Name); 
    }
    

    Schonmal getestet, ob der Sender hier gültig ist :

    SendMessage(dynamic_cast <TPanel*>(Sender)->Handle,WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    

    Probier mal die Prüfung auf NULL immer nach vorne zu nehmen. Ansonsten versucht er erst die Prüfung auf HasParent() (was ins Auge gehen kann) und dann erst auf NULL (was dann schon zu spät ist).
    [cpp]
    for( int i = 0 ; i < p->ControlCount ; i++ )
    {
    ctrl = dynamic_cast<TControl*> (FindComponent(p->Controls[i]->Name));
    if (ctrl != NULL && ctrl->HasParent())
    {
    p->Controls[i]->Left = p->Left + 5;
    p->Controls[i]->Top = p->Top + 5;
    p->Controls[i]->Parent = this;
    p->Left += 5;
    p->Top += 5;
    p->Width -= 5;
    p->Height -= 5;
    }
    [/cpp]

    P.S.:
    this-> kann man weglassen, wenn Objekte vom Form gemeint sind.

    Bis dann denn,
    🙂
    Nash



  • gerd01 schrieb:

    hi, ich finde es eigentlich sehr logisch?! du nicht?

    Sonst hätte ich wohl kaum gefragt.
    Mal im Einzelnen:
    [cpp]
    // Zur weiteren Darstellung erstmal leeren ---> Unnötiger Kommentar; das steht in der nächsten Zeile
    ListBox2->Items->Clear();
    // Zeiger für Objektreferenz holen ---> Unnötiger Kommentar;
    TControl* ctrl;
    /* Objekte auf dem Panel durchlaufen und schauen, ob Objekt vorhanden,
    wenn ja, dann die Position des Objektes zurückholen durch Panelposition,
    und Form wieder zum parent des objektes machen./
    Wofür ist das Panel da? Ich rate mal, dass Du meinen Vorschlag mit dem "Panel unterschieben"
    hier umgesetzt hast? Ein aussagekräftiger Name würde hier vielleicht manche Frage und Rätselei ersparen.
    Denk doch auch mal dran, ob Du in einem Jahr noch weißt, was Du da gemacht hast...(Antwort ist Nein)

    for( int i = 0 ; i < p->ControlCount ; i++ )
    {
    Wofür ist die nachfolgende Zeile gut? Ich versuche mal zu beschreiben, was Du da machst:
    Du nimmst ein Objekt vom Typ TControl
    und versuchst anhand des Namens die entsprechende
    Komponente (TComponent
    ) auf dem Formular zu finden, was ja gelingen muss, da das gefundene
    Control sicher zum Form gehört und TControl eine Unterklasse von TComponent ist.
    Das ganze ist flüssiger als flüssig: Überflüssig**
    ctrl = dynamic_cast<TControl
    > ( FindComponent( p->Controls[i]->Name ) );
    // hat die kompo eine elternkompo ---> Unnötiger Kommentar; das steht in der nächsten Zeile
    Wie von Nash schon angemerkt, sollte die Reihenfolge vertauscht werden.
    Prüfen auf 0 ist hier aber ohnehin unnötig, wenn Du den (unnötigen) cast weglässt.
    Dann ist auch die ganze Prüfung auf den Parent unnötig. Überleg mal selbst warum.

    if( ctrl->HasParent() && ctrl != 0 )
    {
    // wenn ja pos setzen und elternkompo auf form setzen
    p->Controls[i]->Left = p->Left + 5;
    p->Controls[i]->Top = p->Top + 5;
    p->Controls[i]->Parent = this; // Was passiert hier, wenn Du z.B. ein Panel auf einem Panel hast?
    // rahmenbreite zurücksetzen falls element zweimal ausgeählt wird.
    p->Left += 5;
    p->Top += 5;
    p->Width -= 5;
    p->Height -= 5;
    }
    }
    // gewähltes element aus liste wählen
    ctrl = dynamic_cast<TControl*> (FindComponent(ListBox1->Items->Strings[ListBox1->ItemIndex]));
    // Objekt mit Panel hinterlegen
    if ( ctrl != 0 )
    {
    // Namen schreiben
    Ja, aber warum? Dass Du das machst kann ich dem Code entnehmen, aber wofür?
    Vor allem weshalb Listbox? Hier wäre ein aussagekräftiger Name u.U. aufschlussreich.
    Wird denn die Listbox2 jemals für irgendwas benötigt? Wenn ja: wofür? Wenn nein: Könnte
    man nicht einfach einen Label für Anzeigezwecke verwenden?

    ListBox2->Items->Add(ctrl->Name);
    // Panelgröße und pos anpassen
    p->Left = ctrl->Left - 5;
    p->Top = ctrl->Top - 5;
    p->Width = ctrl->Width + 10;
    p->Height = ctrl->Height + 10;

    /* Panel wird elternkompo des objektes, damit dahinter ein panel liegt, wegen dem benötigten handle in "OnpMouseDown(..)" */

    ctrl->Parent = p; Vielleicht solltest Du Dir den Original-Parent irgendwo speichern (s.o.), um ihn später
    wieder korrekt zurücksetzen zu können.

    //Da Panelbereich überall 5px überstehen soll, hier neu pos setzen
    Anstatt überall 5 zu verwenden, solltest Du Dir überlegen, ob Du nicht lieber eine Konstante verwendest.
    Das hat zwei Vorteile:
    1. Wenn Du den Wert ändern willst.
    2. Bessere Lesbarkeit.

    ctrl->Left = 5;
    ctrl->Top = 5;
    ctrl->Width = p->Width - 10;
    ctrl->Height = p->Height - 10;
    p->Visible = true;
    }

    [/cpp]

    Was die Benennung von Variablen, Methoden und Klassen betrifft, bin ich recht empfindlich. Es bringt mich regelmäßig
    zur Weißglut, wenn ich nichtssagenden Namen im Quelltext begegne, den ich verstehen muss. Bei sichtbaren Komponenten
    halte ich mich an die Faustregel: Aussagekräftige Namen für alle Komponenten, mit denen ein Benutzer interagieren kann.
    Dazu gehören auf jeden Fall Buttons, Checkboxes und eben auch Listboxes. Label, die nur Beschriftungszwecken dienen
    benenne ich meist nicht extra.

    Noch ein Tip, mit dem Du Dir vielleicht einen Haufen Code ersparen kannst: Es gibt in Stringlisten auch die Möglichkeit
    Objekte zu speichern, also Text mit Objekten zu assoziieren - und TListbox verwendet intern eine Stringliste...

    Gruß,

    Alexander

    PS: Ich habe mir relativ viel Zeit genommen. Bitte nimm Dir auch die Zeit und gehe möglichst alle meine Anregungen durch.
    Wenn Du dann wieder Fragen hast, werde ich Dir bestimmt helfen.



  • hi,

    vielleicht werdet Ihr ja nun etwas schlauer daraus 🙂

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    /*
    "Start" wird für die Markierung meherer Elemente benötigt, ich habe Sie jetzt mal
    mit reingenommen, damit Ihr den Sinn meiner ListBox2 (lstSelectedControls) versteht.
    */
    
    bool Start=false;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::lstSelectableControlsClick(TObject *Sender)
    {
        shpMarker->Visible = false;
        lstSelectedControls->Items->Clear();
        TControl* ctrl;
        // Objekte mit Panel durchlaufen
    
        /*
        @Alexander Kempf:
        Ja, Du hast recht, ich habe Deinen Vorschlag mit dem Panel umgesetzt, damit
        ich beim Verschieben (pnlBehinderMouseDown) unten einen Handle bekomme, um
        mit ReleaseCapture() arbeiten zu können.
    
        @Nash:
        Dass ich für Methoden und Eigenschaften kein this benötige ist mir klar, aber
        ich sehe dann eher, was zur aktuellen Form gehört, wenn ich gleiche Methoden
        in anderen Elementen aufrufe
        */
    
        for( int i = 0 ; i < pnlBehinder->ControlCount ; i++ )
        {
            /*
            @Alexander Kempf:
            Warum ist der cast hier unwichtig? Hast Du mir doch selber gezeigt!
            */
            ctrl = dynamic_cast<TControl*> ( FindComponent( pnlBehinder->Controls[i]->Name ) );
            if( ctrl != 0 && ctrl->HasParent() )
            {
    
                /*
                Falls Controls einen anderen Parent besitzen als die Form selbst,
                sind Positionsangaben relativ zum Parent. Da ich in diesem Codeabschnitt
                aber den eventuell vorhandenen Parent von einem Control als Parent
                wieder entferne setze ich die Positionen des Controls wieder auf
                relative Werte der Form.
                */
    
                pnlBehinder->Controls[i]->Left = pnlBehinder->Left + 5;
                pnlBehinder->Controls[i]->Top = pnlBehinder->Top + 5;
                pnlBehinder->Controls[i]->Parent = this;
    
                /*
                Wenn man das Gleiche Control wieder aus der ListBox1 (lstSelectableControls)
                wählt, würde der Rahemn, wenn ich ihn im nachfogenden Code nicht wieder
                verkleinere doppelt so breit um ein Control gesetzt werden, deshalb hier
                der Abzug der Größen- und Positionsangaben
                */
    
                pnlBehinder->Left += 5;
                pnlBehinder->Top += 5;
                pnlBehinder->Width -= 5;
                pnlBehinder->Height -= 5;
            }
        }
    
        /*
        Listbox1 (lstSelectableControls) enhält alle wählbaren Kompos
        "ctrl" enthält also das gewählte Control, welches jetzt das Panel (pnlBehinder)
        als Parent zugewiesen bekommt
        */
    
        ctrl = dynamic_cast<TControl*> (FindComponent(lstSelectableControls->Items->Strings[lstSelectableControls->ItemIndex]));
    
        // Objekt mit Panel hinterlegen
    
        if ( ctrl != 0 )
        {
            /*
            Da ich ja noch das Markierungstool intus habe nehme ich hier eine ListBox2
            (lstSelectedControls), in der ich die Markierungen anzeige
            */
    
            lstSelectedControls->Items->Add(ctrl->Name);
    
            /*
            Panel etwas versetzt dahinter platzieren, damit Rahmen greifbar wird.
            */
    
            pnlBehinder->Left = ctrl->Left - 5;
            pnlBehinder->Top = ctrl->Top - 5;
            pnlBehinder->Width = ctrl->Width + 10;
            pnlBehinder->Height = ctrl->Height + 10;
    
            ctrl->Parent = pnlBehinder;
            ctrl->Left = 5;
            ctrl->Top = 5;
            ctrl->Width = pnlBehinder->Width - 10;
            ctrl->Height = pnlBehinder->Height - 10;
    
            pnlBehinder->Visible = true;
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
        /*
        Alle Wählbaren Kompos in ListBox1 (lstSelectableControls) schmeissen (nur zum Testen)
        */
    
        for( int i=0; i < this->ControlCount ; i++ )
        {
            if( this->Controls[i]->Visible )
                lstSelectableControls->Items->Add( this->Controls[i]->Name );
            this->Controls[i]->Visible = true;
        }
    
        // Markierungstoolrahmen ausblenden
        shpMarker->Visible = false;
    
        // Panel ausblenden
        pnlBehinder->Visible = false;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
        // Markierungstool startet
        Start = true;
        shpMarker->Left = X;
        shpMarker->Top = Y;
        shpMarker->Width = 0;
        shpMarker->Height = 0;
        shpMarker->Visible = true;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
          int X, int Y)
    {
        // Zum zeichnen eines Rechtecks
        if(Start)
        {
            shpMarker->Width = X - shpMarker->Left;
            shpMarker->Height = Y - shpMarker->Top;
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
        /*
        Neu gefundenene Elemente werden wieder in eine gesäuberte ListBox2
        (lbSelectedControls) geschmissen um zu prüfen, ob markiert
        */
        int Temp;
    
        if(shpMarker->Width < 0)
        {
            Temp = shpMarker->Width * -1;
            shpMarker->Width = Temp;
            shpMarker->Left = shpMarker->Left - Temp;
        }
    
        if(shpMarker->Height < 0)
        {
            Temp = shpMarker->Height * -1;
            shpMarker->Height = Temp;
            shpMarker->Top = shpMarker->Top - Temp;
        }
    
        lstSelectedControls->Items->Clear();
        TRect rectc,rects;
        for( int i=0; i < this->ControlCount; i++ )
        {
            if( this->Controls[i]->Name != "shpMarker" )
            {
                rectc = this->Controls[i]->BoundsRect;
                rects = shpMarker->BoundsRect;
                if (rectc.Left >= rects.Left && rectc.right <= rects.right && rectc.Bottom <= rects.bottom && rectc.top >= rects.top)
                    lstSelectedControls->Items->Add(this->Controls[i]->Name);
            }
        }
        //Markierungstoolphase beendet
        Start=false;
        shpMarker->Visible = false;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::pnlBehinderMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
        // Zum Verschieben des Panels mit dem aktuellen Control als Child des Panels
        ReleaseCapture();
        SendMessage(dynamic_cast <TPanel*>(Sender)->Handle,WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    }
    //---------------------------------------------------------------------------
    

    So, denke jetzt sollte aber alles Lesbar sein, habe mir auch mühe gegeben und mehr kommentiert und überflüssige Statements rausgenommen!

    @Alexander Kempf:
    ok, dass mit den Konstanten wäre ne richtige Vorgehensweise, und das mit dem Aktuellen Parent speichern ist auch ne wunderbare Idee, allerdings habe ich es ja mit Absicht erst mal alles der Form bzw. dem Panel als Child untergejubelt, weil es in allererster Linie ein Test werden soll, ob es alles überhaupt so klappt.

    Ein Label als Anzeigezwecke für ein Control ist sinnvoll, doch ich zeige unter Umständen auch mehrere an, siehe code (Markierungstool)

    @Nash:
    Wie prüfe ich es denn "ob der Sender hier gültig" ?

    gruß gerd


Anmelden zum Antworten