Ja sugerowałbym umieścić przed kodem wykonywanym w zdarzeniu OnClick dla ListBox funkcję wyrzucającą z funkcji - return. To zapewni łatwiejszą obsługę zdarzenia, to co proponuję jest odwrotnością tego co proponuje
Miro_007:
- Kod: Zaznacz cały
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
if(ListBox1->ItemIndex == -1) return; // jeżeli nic nie zostało zaznaczone - przerwanie funkcji
// dalej kod wykonywany jeżeli wartość ItemIndex >= 0
}
Funkcji
Execute nie używa się tak, jak ty to robisz. Służy ona do wywołania okna wyboru plików, ale też zwraca wartość true lub false w zależności od tego, czy wybrano plik (true), czy też nie (false):
Powinno być:
- Kod: Zaznacz cały
if(OpenDialog2->Execute())
{
AnsiString nazwapliku = OpenDialog2->FileName;
char nazwaplikuX[20];
sprintf(nazwaplikuX, "%s", nazwapliku.c_str());
CopyFile(nazwapliku.c_str(), kat.c_str(), false);
String archiwum = nazwapliku.c_str();
String DestDir = kat;
String param = " x -y \"" + archiwum + "\" \"*.*\" \"" + DestDir + "\"";
ExecuteUnrar(fileUnrar, param.c_str(), NULL);
}
jest:
TIniFile *Ini = new TIniFile("\config\\Ustawienia.ini");
powinno być:
- Kod: Zaznacz cały
TIniFile *Ini = new TIniFile("\\config\\Ustawienia.ini");
Rozmiar zmiennej
nazwaplikuX jest za mały, skoro ma przechowywać ścieżkę dostępu do katalogu lub pliku, to jej rozmiar powinien odpowiadać maksymalnego dozwolonemu rozmiarowi takiej ścieżki, czyli:
- Kod: Zaznacz cały
char nazwaplikuX[MAX_PATH];
podobnie sugerowałbym postąpić ze zmienną
katX.
Na dobrą sprawę nie używasz zmiennej
nazwaplikuX, więc jest ona tutaj zbędna,tak samo jest ze zmienną
katX.
ShowMessage(kat.c_str());
Funkcja
ShowMessage oczekuje zmiennej typu AnsiString, nie char, więc powinno być:
- Kod: Zaznacz cały
ShowMessage(kat);
String archiwum = nazwapliku.c_str();
Zmiennej AnsiString przypisujesz wartość typu char, nie ma to sensu, wogóle zmienna
archiwum jest już tutaj zbędna, gdyż zastępuje ją zmienna
nazwapliku. Tak samo ze zmiennÄ…
DestDir - zastąpiłeś ją zmienną
kat.
A teraz przyczyna błędu, czytaj uważnie.
Do pliku Ustawienia.ini podajesz w swoim programie względną ścieżkę dostępu, względną względem programu, gdyż nie podajesz nazwy litery dysku, ani też dokładnej lokalizacji tego pliku, dlatego program szuka domyślnie tego pliku w podkatalogu config, w katalogu programu (katalog_programu\config\Ustawienia.ini). Dzieje się tak dopóty, dopóki domyślna ścieżka programu (zdefiniowana jaka ParamStr(0) - ale to inna sprawa) nie ulegnie zmianie, a ulega zmianie, gdy użyjesz obiektu OpenDialog, wtedy domyślna ścieżka zostaje zastąpiona ścieżką wybraną w OpenDialog, w efekcie przy drugim użyciu funkcji program nie szuka już pliku Ustawienia.ini w katalogu programu, lecz szuka go w katalogu wybranym w OpenDialog (katalog_OpenDialog\config\Ustawienia.ini). Tak więc względna domyślna ścieżka programu uległa zmianie przy pierwszym użyciu funkcji, dlatego powinieneś zawsze podawać bezwzględną ścieżkę dostępu, a wiec powinno to wyglądać tak:- Kod: Zaznacz cały
String fileIni = ExtractFilePath(ParamStr(0)) + "config\\Ustawienia.ini";
TIniFile *Ini = new TIniFile(fileIni);
W celu uniknięcia błędów powinieneś zdefiniować domyślny katalog z którego będzie korzystał program, gdy nie odnajdzie pliku
Ustawienia.ini, czyli ten fragment kodu może wyglądać tak:
- Kod: Zaznacz cały
kat = Ini->ReadString("INFO", "katalog", "c:\\'domyślny katalog\\")+ "Popup Changer\\";
Twój kod powinien wyglądać tak:
- Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String fileIni = ExtractFilePath(ParamStr(0)) + "config\\Ustawienia.ini";
TIniFile *Ini = new TIniFile(fileIni);
String kat = Ini->ReadString("INFO", "katalog", "c:\\'domyślny katalog\\") + "Popup Changer\\";
ShowMessage(kat);
String nazwa = InputBox("Dodaj popup","Podaj nazwÄ™ popupa:","");
if(nazwa.IsEmpty())
{
ShowMessage("Nie wybrałes pliku!");
return;
}
TRegistry *Rejestr = new TRegistry();
Rejestr->RootKey = HKEY_LOCAL_MACHINE;
Rejestr->OpenKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\WinRAR.exe", false);
String fileUnrar = Rejestr->ReadString("Path") + "\\unrar.exe";
delete Rejestr;
if(fileUnrar.IsEmpty())
{
fileUnrar = kat + "\\unrar.exe";
if(!FileExists(fileUnrar)) // jeżeli brak pliku unrar.exe
{
int idx = Application->MessageBox("Nie odnaleziono pliku 'Unrar.exe'\n"
"Czy chcesz odszukać plik ręcznie?", "UNRAR", MB_YESNO | MB_ICONQUESTION);
if(idx == ID_YES)
{
if(OpenDialog1->Execute()) // dodatkowy OpenDialog do wyboru pliku Unrar.exe
{
fileUnrar = OpenDialog1->FileName;
}
}
else return; // przerywa działanie z braku pliku Unrar.exe
}
}
if(OpenDialog2->Execute())
{
String nazwapliku = OpenDialog1->FileName;
CopyFile(nazwapliku.c_str(), kat.c_str(), false);
String param = " x -y \"" + nazwapliku + "\" \"*.*\" \"" + kat + "\"";
ExecuteUnrar(fileUnrar, param.c_str(), NULL);
}
}
//---------------------------------------------------------------------------
Co do tego powyższego kodu, to jak zrobić że jeśli w InputBoxie nie poda się niczego, to nie wykonywać dalszych poleceń? Próbowałem za pomocą goto , ale nie udało mi się wstawić tego goto na sam koniec tego kodu. Pisało, że nie może odnaleźć czy coś takiego.
Dodałem funkcję return, w celu przerwania wykonywania dalszych instrukcji, czyli to jest ten fragment kodu:
- Kod: Zaznacz cały
String nazwa = InputBox("Dodaj popup","Podaj nazwÄ™ popupa:","");
if(nazwa.IsEmpty())
{
ShowMessage("Nie wybrałes pliku!");
return;
}
Zmienna nazwa jest dla mnie zagadkowa, gdyż przypisujesz jej wartość, ale nie wykorzystujesz w żaden sposób, więc wydaje się tutaj zbędna.
Zdarzenie OnCreate jest wywoływane zawsze w chwili tworzenia klasy formularza, czyli jest to pierwsze zdarzenie wywoływane przy uruchomieniu programu, kolejne to OnShow, ale to zdarzenie może być wywoływane wielokrotnie, zawsze gdy formularz jest wyświetlany.