ein paar Fragen...



  • Hallo!

    Ich bin C++-Neuling und möchte ein Programm schreiben dass ich zum Beispiel am oberen Bildschirmrand "anheften" kann. Auf dieses kann ich dann per Drag&Drop Dateien bzw. Verknüpfungen von Dateien oder Ordner ziehen. (Dies soll so funktionieren wie Schnellstartleiste von Windows)
    Ich bin soweit dass ich normale Dateien auf mein Programm ziehen kann, aber den Arbeitsplatz, die Netzwerkumgebung kann ich nicht drauf ziehen (Cursor wird zu durchgestrichenem Kreis).
    1.Wie kann ich das beheben ?

    Da die Verknüpfungen ja beim nächsten Neustart des Programms wieder da sein sollen benutze ich am besten die Registry...
    Also erzeuge ich, wenn ein Objekt auf mein Programm gezogen wird, erst ein Registryeintrag (Zeichenfolge) z.B. Winamp "c:\programme\winamp\winamp.exe" und dann den anklickbaren Button in meinem Programm.
    2.Wie kann ich das oben erwähnte "Anheften" an einen Bildschirmrand realisieren ?
    3.Die Buttons generiere ich ja im Programm durch das Auslesen der Registry, jetzt habe ich gemacht das man die Buttons rechtsklicken kann und ein Popupmenü erscheint (mit Umbenennen, Bearbeiten, Löschen). Wie muss die Funktion "Umbenennen" nun aussehen damit ich auch die Caption des RICHTIGEN buttons ändern kann?
    ...also...so werden die Buttons erzeugt:

    Reg->OpenKey("Software\\Programm",false);
            TStringList *values = new TStringList;
            Reg->GetValueNames(values);
            for(int i=0;i<values->Count;i++){
                hilf1 = Reg->ReadString(values->Strings[i]);
                hilf2 = values->Strings[i];
                if(FileExists(hilf1)==true){
                    button = hilf2;
                    TButton* button;
                    button = new TButton(this);
                    button->Parent=this;
                    button->Caption=hilf2;
                    button->Top=(10+i*30);
                    button->Left=10;
                    button->Width=200;
                    button->OnClick=run;
                    button->PopupMenu=PopupMenu1;
    

    und ist die folgende Funktion so optimal, oder hab ich da etwas viel zu umständlich bzw. falsch gemacht ?

    void __fastcall TForm1::run(TObject *Sender)
    {
    TRegistry *Reg = new TRegistry();
    Reg->RootKey = HKEY_LOCAL_MACHINE;
    AnsiString datei,adresse;
    
    datei=static_cast<TButton*>(Sender)->Caption;
    Reg->OpenKey("SOFTWARE\\DDrop",false);
    adresse=Reg->ReadString(datei);
    ShellExecute(0,NULL,adresse.c_str(), NULL, NULL, SW_SHOWNORMAL);
    Reg->CloseKey();
    }
    

    Vielen Dank im voraus
    Johannes



  • Johannes2002,

    Johannes2002 schrieb:

    ...
    Da die Verknüpfungen ja beim nächsten Neustart des Programms wieder da sein sollen benutze ich am besten die Registry...

    also ich würde ja die Registry nicht als "beste" Variante zum Speichern von Daten betrachten - aber das ist irgendwo auch Geschmackssache.

    Johannes2002 schrieb:

    2.Wie kann ich das oben erwähnte "Anheften" an einen Bildschirmrand realisieren ?

    Ich wüßte von keiner eingebauten Funktionalität, die Dir das abnimmt. Ich fürchte, Du mußt das selbst programmieren: jedesmal, wenn das Formular bewegt oder in der Größe geändert wird Testen, ob die Fenster-Ränder einen bestimmten Abstand zu den Bildschirm-Rändern unterschreiten und gegebenfalls das Fenster um den Abstand verschieben.

    Johannes2002 schrieb:

    Wie muss die Funktion "Umbenennen" nun aussehen damit ich auch die Caption des RICHTIGEN buttons ändern kann?

    Im OnPopup-Ereignis kannst Du über die property PopupComponent des Menüs auf das aufrufende Objekt (also einer Deiner Buttons) zugreifen. Und die eingebaute Funktion InputQuery könnte Dir eventuell einiges an Arbeit abnehmen...



  • Johannes2002 schrieb:

    [...] Ich bin C++-Neuling [...]

    Darum auch ein Tipp: Bei deinem Code ist ein Fehler an folgender Stelle:

    // [...]
                if(FileExists(hilf1)==true){
                    button = hilf2;
                    TButton* button;
                    button = new TButton(this);
    // [...]
    

    Also ich glaub nicht, dass das Programm so jemals gelaufen ist.

    1. Du kannst button nicht verwenden, bevor du es deklariert hast.
    2. button ist nach der Deklaration ein Objekt, Objekte kann man nicht einfach zuweisen, und schon garnicht kann man einem Objekt ein String zuweisen, wenn du dem Button eine Beschriftung zuweisen möchtest: Das geht nur nach der Deklaration (1.) und nur so:

    TButton* button;
                    button = new TButton(this);
                    button->Caption=hilf2;
    

    Und zum Abspeichern von Pfaden usw. eignen sich wunderbar Textdateien, also wozu Registry? Speicher's doch einfach in eine Textdatei und öffne diese beim nächsten Start der Anwendung wieder. Bei TStrings gibts nämlich ne ganz einfache Funktion:

    SaveToFile(); und LoadFromFile();

    Ansonsten ist der Code ganz ok.



  • danke für eure antworten!

    also ich würde ja die Registry nicht als "beste" Variante zum Speichern von Daten betrachten - aber das ist irgendwo auch Geschmackssache.

    okay...ich steige dann jetzt auf dateien um, ich dachte dass ich vielleicht am besten ein struct benutze das so aussieht
    Integer Position;
    String Name[20];
    String Adresse[60];
    aber ich blicke da ehrlich gesagt noch nicht so durch wie ich solche datensätze in eine datei schreibe...

    wegen dieser sache...

    if(FileExists(hilf1)==true){ 
                    button = hilf2; 
                    TButton* button; 
                    button = new TButton(this);
    

    das ging schon, ich habs zwar nicht mitgepastet, aber button hab ich zuerst als String deklariert. das heißt die button die dann erstellt werden heißen so wie die exenamen. das habe ich gemacht, damit ich die buttons wiedererkenne...

    kann ich mit SaveToFile auch Struktur in den Dateien haben ? also wie kann ich dann wieder auf bestimmte datensätze zugreifen...

    danke nochmal im voraus
    johannes



  • Also Struktur kannst du nicht wirklich einbringen. Nimm doch ne ListBox und mit ListBox->Items->Strings[index] kannst du auf die Zeilen zugreifen, und in diesen Zeilen sollten die Pfade stehen.

    Und wenn du in eine Liste die Pfade einliest und aber nur die Dateinamen anzeigen möchtest, kannst du das mit einer TListBox (ListBox1) lösen, die du auf deiner Form erstellst und mit folgendem Quellcode:

    void __fastcall TForm::FormCreate(TObject* Sender)
    {
        TStrings* List=new TStrings(List);
        List->LoadFromFile("Pfade.txt");
        for (int i=0;i<List->Count;i++)
            ListBox1->Items->Add(ExtractFileName(List->Strings[i]));
    }
    

    Damit sieht man nicht die kompletten Pfade sondern nur die Dateinamen.

    Wenn du die Pfade anzeigen willst, nimmst du statt ExtractFileName() einfach ExtractFilePath().



  • mmm, aber ich möchte nicht nur den pfad speichern, sondern auch die Position wo der Button hinkommt usw...
    speicher ich es dann nicht besser als struct in dateien hab ?
    ich hab jetzt mal rumprobiert...und so kann ich es abspeichern:

    using namespace std;
    struct Auto {
    String Marke;
    String Typ;
    Integer PS;
    };
    Auto s_auto;
    fstream File("Autos.dat", ios::out|ios::binary);

    s_auto.Marke = "Marke";
    s_auto.Typ = "Typ";
    s_auto.PS = 360;

    if (File.is_open())
    {
    File.write((const char*)&s_auto, sizeof(s_auto));
    }
    }
    File.close();

    das funktioniert auch...aber ich weiß nicht wie ich die Datensätze wieder lesen kann

    ich habs so probiert:

    File.open("Autos.dat", ios::in|ios::binary);
    if (File.is_open())
    {
    while (File.read((char*)&s_auto, sizeof(s_auto)))
    ShowMessage(s_auto.Marke);
    }

    aber das gibt ein ausnahmefehler...

    kann mir jemand helfen ?

    danke
    johannes



  • bzw. das produziert eine zugriffsverletzung in der ntdll.dll...



  • Johannes2002,

    Johannes2002 schrieb:

    ...kann ich mit SaveToFile auch Struktur in den Dateien haben ? also wie kann ich dann wieder auf bestimmte datensätze zugreifen...

    es gibt zwei einfache Varianten, Struktur zu erzeugen:

    1. die einzelnen Daten durch Kommata oder so getrennt in die Text-Datei schreiben
      Info1, Info2, Info3
      Info1, Info2, Info3
      Info1, Info2, Info3
      ...

    2. jede Info in eine extra Zeile der Text-Datei schreiben
      Info1
      Info2
      Info3
      Info1
      Info2
      Info3
      ...



  • Windoof schrieb:

    Also Struktur kannst du nicht wirklich einbringen.

    warum nicht ?



  • @Andreas W:

    Na dann erklär mit mal, wie du mit SaveToFile() Struktur einbringen willst, wenn dann musst du die Struktur in der StringListe schon haben, aber du kannst keine richtige Struktur erzeugen.

    @Johannes2002:

    Oder du nimmst TIniFile (inifiles.hpp):

    TIniFile* ini=new TIniFile("C:\\ini.ini");
    TStrings* SectionList=new TStrings;
    ini->ReadSections(SectionList);
    for (int i=0;i<SectionList->Count;i++)
    {
            ListBox1->Items->Add(ini->ReadString(SectionList->Strings[i],"Name","-"));
            ListBox2->Items->Add(ini->ReadString(SectionList->Strings[i],"Pfad","C:\\"));
    }
    

    Oder du schreibst alle Infos in anderen Textdateien untereinander, z.B. Dateinamen.txt, Pfade.txt, Groessen.txt, usw.



  • Windoof schrieb:

    @Andreas W:

    Na dann erklär mit mal, wie du mit SaveToFile() Struktur einbringen willst...

    done.



  • Wo ist da die Funktion SaveToFile() aufgeführt?



  • void SaveToFile()
    {
    TFileStream* stream=new TFileStream("C:\\test.dat",fmCreate); 
       Auto car; 
      car.Nummber=122; 
      strcpy(car.Marke,"Audi"); 
      strcpy(car.Typ,"Kombi"); 
      car.PS=180; 
       stream->Write((void*)&car,sizeof(car)); 
     delete Stream;
    }
    

    so besser ?



  • Ich meine auch nicht deine Funktion "SaveToFile()", sondern die "TStrings::SaveToFile()".



  • hallo

    zu deiner frage wegen arbeitsplatz und netzwerkumgebung.
    das funkt deshlab nicht, weil das keine dateien oder ordner sind.
    die sehen nur so aus. solche ordner kannst auch selber erzeugen.
    erstell mal folgenden ordner:"test.{208D2C60-3AEA-1069-A2D7-08002B30309D}"

    der string, der rechts vom punkt steht wird CLSID genannt, und damit identifiziert windows den ordner als netzwerkumgebung(zumindest bei win2k).

    ob man solche "ordner" irgendwie per drag´n´drop uebernehmen kann, hab ich keine ahnung.

    @Windoof : wieso versteifst du dich so auf dein SaveToFile ? Johannes2002 will einfach seine daten speichern. das das unbedingt mit TStrings laufen soll, hab ich niergendwo gelesen.

    Meep Meep



  • Nein, aber es ist die einfachste Methode. Vielleicht nicht die schnellste, vielleicht auch nicht unbedingt die idealste, aber die verständlichste. 😃

    Naja egal, ich hab mich auch nicht drauf versteift, aber er hat gefragt, ob man mit SaveToFile (von TStrings) Struktur einbringen kann, und das geht aber nunmal nicht wirklich, man kann nur String-Listen abspeichern und keine Tabellen, die müsste man sich selbst basteln. Dass er diese unbedingt verwenden soll, hab ich nie gesagt, sondern ich hab sie nur vorgeschlagen.


Anmelden zum Antworten