Ogólne pytanka

dział ogólny

Ogólne pytanka

Nowy postprzez Gazunio » środa, 13 maja 2009, 20:50

Witam. Niedawno rozpocząłem swoja przygodę z programowaniem w C++ Builderze. Wcześniej jedynie miałem do czynienia z programowaniem w batchu i AC.
Tak więc robie teraz programik, w którym wybiera się dany element, który ma byc kopiowany do katalogu który sie wcześniej wybrało. I tu mam problem z kopiowaniem. Po kompilacji i próbie kopiowania w programie pojawia sie problem ze nie mozna odczytać z dysku źródłowego, mimo że taki folder istnieje, Podana jest ściezka bezwzględna do folderu.
Mam kolejne pytanko. Jak wykonać ProgressBar dla pobierania plików. Udało mi sie dodać do programu mozliwość szukania aktualizacji, ale chciałbym by był pokazywany stan pobierania. I też jak wykonać, by nie "zamulało" okienka w którym się pobiera. Jeszcze mam pytanie w sprawie ściągania. Chce by poprzez HTTP wyszukiwało pliki z nazwą np. aktualizacja1, aktualizacja2 itp. Jesli bedzie taki plik to go pobierze. I mam pytanie czy jest możliwośc wypakowania archiwum zip w programie, bo te pliki chciałbym by były archiwami zip.
I jeszcze. Czy da sie zmienić styl paska tytułowego i zakładek ( tworzę program za pomoca zakładek)

Oczywiście czytam porady na portalu, ale nie mogę sie doszukać interesujacych mnie elementów.
Z góry dzieki za pomoc.
Avatar użytkownika
Gazunio
Bladawiec
Bladawiec
 
Posty: 32
Dołączył(a): środa, 13 maja 2009, 18:40
Podziękował : 3
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2009
Gadu Gadu: 5147883
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Cyfrowy Baron » czwartek, 14 maja 2009, 08:25

Za dużo pytań, za mało konkretów, zbyt mała znajomość tematu.
Skoro jeszcze nie programowałeś w C++ to zacznij o rzeczy prostych.
► patrz serwis: Cyfrowy Baron



Tak więc robie teraz programik, w którym wybiera się dany element, który ma byc kopiowany do katalogu który sie wcześniej wybrało. I tu mam problem z kopiowaniem. Po kompilacji i próbie kopiowania w programie pojawia sie problem ze nie mozna odczytać z dysku źródłowego, mimo że taki folder istnieje, Podana jest ściezka bezwzględna do folderu.


Nic z tego nie rozumiem.



Mam kolejne pytanko. Jak wykonać ProgressBar dla pobierania plików. Udało mi sie dodać do programu mozliwość szukania aktualizacji, ale chciałbym by był pokazywany stan pobierania. I też jak wykonać, by nie "zamulało" okienka w którym się pobiera. Jeszcze mam pytanie w sprawie ściągania. Chce by poprzez HTTP wyszukiwało pliki z nazwą np. aktualizacja1, aktualizacja2 itp. Jesli bedzie taki plik to go pobierze. I mam pytanie czy jest możliwośc wypakowania archiwum zip w programie, bo te pliki chciałbym by były archiwami zip.


Potrzebne są dodatkowe biblioteki, typu INDY, ZipForge, gdyż standardowo środowisko C++ Builder takowych nie zawiera, wiec o wypakowywaniu archiwów ZIP nie ma mowy, chyba że sam stworzysz podobną bibliotekę, ale to zadanie bardzo złożone.
Co do ściągania plików za pomocą protokołu HTTP w połączeniu z ProgressBar to w przygotowywanej przeze mnie aktualizacji, już to jest, jak skończę wrzucę to do serwisu.



I jeszcze. Czy da sie zmienić styl paska tytułowego i zakładek ( tworzę program za pomoca zakładek)

Można rysować na pasku tytułowym ( ► patrz serwis: Cyfrowy Baron), ale to nie wygląda zbyt dobrze. Potrzebne są dodatkowe biblioteki (np. VCLSkin), lub można stworzyć formularz bez paska i nałożyć na niego maskę pod postacią bitmapy, wtedy będzie to wyglądać np. podobnie jak w jednym z programów który waśnie wykańczam.

babilon.png
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Gazunio » czwartek, 21 maja 2009, 18:44

Poprzednie problemy rozwiązane. Ale teraz mam problem. Poprzez program chcę uruchomić plik wsadowy z dwoma parametrami. Próbowałem to wykonać poprzez SheelExecute, ale z niezbyt dobrym skutkiem.
Plik wsadowy, w właściwie program Unrar.exe, z pakietu WinRar - (nie umiem obłsugiwać ZipGeniusa, więc musiałem skorzystać z tego) ma składnię do uruchamiania:
Kod: Zaznacz cały
Unrar.exe x -y <plik do wypakowania>

Tak więc muszę przekazać parametry "x", "-y" oraz lokalizację pliku do wypakowania. Wcześniej lokalizację programu wsadowego (Unrar) określiłem jako plik.c_str(). Inaczej niż char nie mogę, bo tam pisze coś że nie może zamienić AnsiString na char. Natomiast plik do wypakowania to plik2.c_str().
Jak to mogę wykonać? Obie lokalizacje mają spacje w nazwach.

Z góry dzięki za pomoc.
Avatar użytkownika
Gazunio
Bladawiec
Bladawiec
 
Posty: 32
Dołączył(a): środa, 13 maja 2009, 18:40
Podziękował : 3
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2009
Gadu Gadu: 5147883
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Cyfrowy Baron » piątek, 22 maja 2009, 14:34

Też kiedyś używałem na potrzeby pewnego programu, właśnie Unrar.exe. Stworzyłem specjalne funkcje, ale Tobie podam prostsze rozwiązanie:

Plik nagłówkowy (np. Unit1.h):
Kod: Zaznacz cały
//------------------------------------
#include <filectrl.hpp> /* <- biblioteka wymagana do użycia funkcji SelectDirectory, musi znajdować się koniecznie w pliku nagłówkowym*/
//------------------------------------


Plik źródłowy (np. Unit1.cpp):
Kod: Zaznacz cały
//---------------------------------------------------------------------------
#define NO_WIN32_LEAN_AND_MEAN /* <- dodać jeżeli występują problemy z biblioteką filectrl.hpp, jeżeli nie usunąć*/
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall ExecuteUnrar(AnsiString  FileName,  char param[], HWND h)
{
SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof (sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = h;
sei.lpVerb = "open";
sei.lpFile = FileName.c_str();
sei.lpParameters = param;
sei.nShow = SW_HIDE; // okno konsoli cmd.exe nie będzie wyświetlane

if(ShellExecuteEx(&sei))
  try
  {
   WaitForSingleObject(sei.hProcess, INFINITE);
  }
  __finally
{
  CloseHandle(sei.hProcess);
}
}
//---------------------------------------------------------------------------
#include <Registry.hpp>
void __fastcall UnPack(String archiwum, String DestDir)
{
// tutaj zostaje pobrana ścieżka dostępu do katalogu WinRar'a i do programu Unrar.exe
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"; // program Unrar.exe
delete Rejestr;

String param = " e -o+ \"" + archiwum + "\" \"*.*\" \"" + DestDir + "\"";
ExecuteUnrar(fileUnrar, param.c_str(), NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Wypakuj1Click(TObject *Sender)
{
if(OpenDialog1->Execute())
{
  String Dir = ExtractFilePath(OpenDialog1->FileName);
  if(SelectDirectory("Wybierz katalog na wypakowane pliki", "", Dir,
     TSelectDirExtOpts() << sdNewFolder << sdShowEdit << sdShowShares
     << sdShowFiles << sdNewUI, NULL))
  {
   UnPack(OpenDialog1->FileName, Dir);
  }
}   
}
//---------------------------------------------------------------------------




Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Gazunio » niedziela, 24 maja 2009, 17:00

Dziękuję za ten kod. Udało mi się go zrozumieć :D Przekształciłem go dla swoich potrzeb, i teraz wszystko dobrze działa. I na wszelki wypadek umieszczam razem z programem unRar'a, bo WinRar nie każdy ma.
A jako że nadal próbuję się uczyć programowania, to mam kolejne pytania ...
Ma w projekcie ListBoxa, który zawiera nazwy folderów z danego katalogu. Po kliknięciu na jakąś pozycję pojawia się w Edit nazwa tej zaznaczonej pozycji. Ale problem pojawia się gdy kliknie się na "puste pole" - jest List Index out of bounds (-1) . Chciałbym jakoś to zabezpieczyć, by nie pojawiał się taki monit o błędzie. Najlepiej gdyby nic się nie działo.

Mam też problem z buttonem dodającym do listy kolejne pozycje, wykorzystującym wypakowywanie z użyciem UnRara. Otóż udaje mi się wypakować tylko za pierwszym razem. Drugim razem nic się już nie dzieje. Dla testów dodałem ShowMessage zawierającego katalog, do którego ma się wypakowywać archiwum. I za pierwszym razem jest to cała ścieżka dostępu do katalogu ( C:\sasa\aaa\PPP\ ), a drugim razem tylko sama końcówka (PPP\).
Oto kod tego buttona,
Kod: Zaznacz cały
TIniFile *Ini = new TIniFile("\config\\Ustawienia.ini");
AnsiString kat;
kat = Ini->ReadString("INFO", "katalog", "")+ "Popup Changer\\";
char katX[20];
sprintf(katX, "%s", kat.c_str());
ShowMessage(kat.c_str());
AnsiString nazwa = InputBox("Dodaj popup","Podaj nazwę popupa:","");
if (nazwa=="")
{
ShowMessage("Nie wybrałes pliku!");
}
else
  {
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"; // program Unrar.exe

if (fileUnrar=="")
{String fileUnrar = kat+"\\unrar.exe"; }
delete Rejestr;

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);

  }


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.

Miałbym jeszcze pytanie: Czy istnieje jakieś inne rozwiązanie, dzięki któremu można uruchamiać jakieś zdażenia w programie tylko za pierwszym uruchomieniem tego programu? Bo ja tylko wymyśliłem by w OnCreate programu sprawdzało czy w pliku Ini jest jakaś tam wartość, jeśli jej nie ma to tworzy i uruchamia coś tam.
Avatar użytkownika
Gazunio
Bladawiec
Bladawiec
 
Posty: 32
Dołączył(a): środa, 13 maja 2009, 18:40
Podziękował : 3
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2009
Gadu Gadu: 5147883
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Miroo_007 » poniedziałek, 25 maja 2009, 00:53

Ma w projekcie ListBoxa, który zawiera nazwy folderów z danego katalogu. Po kliknięciu na jakąś pozycję pojawia się w Edit nazwa tej zaznaczonej pozycji. Ale problem pojawia się gdy kliknie się na "puste pole" - jest List Index out of bounds (-1) . Chciałbym jakoś to zabezpieczyć, by nie pojawiał się taki monit o błędzie. Najlepiej gdyby nic się nie działo.

Kod: Zaznacz cały
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
     if(ListBox1->ItemIndex >= 0) Edit1->Text = ListBox1->Items->Strings[ListBox1->ItemIndex];
}
Avatar użytkownika
Miroo_007
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): sobota, 18 października 2008, 10:49
Lokalizacja: Rzeszów
Podziękował : 0
Otrzymał podziękowań: 0
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Cyfrowy Baron » poniedziałek, 25 maja 2009, 12:56

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.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez wargo » piątek, 29 maja 2009, 13:11

Cyfrowy Baron napisał(a):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.

A czego lepiej używać aby wykonać coś po uruchomieniu programu?
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
Podziękował : 12
Otrzymał podziękowań: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Cyfrowy Baron » piątek, 29 maja 2009, 13:44

To zależy co chcesz zrobić. Jeżeli odwołujesz się do jakichś zmiennych zadeklarowanych w klasie formularza, to możesz to robić w zdarzeniu OnCreate, jeżeli jednak odwołujesz się do jakichś komponentów znajdujących się na innych formularzach wchodzących w skład aplikacji, to próba zrobienia tego w zdarzeniu OnCreate zakończy się niepowodzeniem, w przypadku odwoływania się do tego zdarzenia w formularzu głównym, gdyż główna forma jest tworzona jako pierwsza, więc nie może tym samym odwoływać się do pozostałych form w chili gdy sama jest tworzona, gdyż inne formularze jeszcze nie zostały utworzone. Dlatego w takiej sytuacji trzeba korzystać ze zdarzenia OnShow.

Zdarzenie OnShow dla formularza głównego jest wywoływane tylko raz, po zdarzeniu OnCreate, podczas gdy dla innych formularzy jest wywoływane zawsze gdy przywołujesz ten formularz. W pewnych sytuacjach nawet dla formularza głównego zdarzenie OnShow może być wywoływane wielokrotnie, np. gdy ukryjesz formularz za pomocą funkcji Hide(), a potem ponownie go wyświetlisz za pomocą funkcji Show().

Zdarzają się sytuacji gdy nie można czegoś zrobić w żadnym z dostępnych zdarzeń formularza (czasami tak miewam), nie można skorzystać ze zdarzenia OnCreate, OnShow, OnActivate, OnPaint, OnResize, wtedy można umieścić na formularzu komponent TTimer, ustawiając mu na etapie programowanie właściwość Enabled na true, w zdarzeniu OnTimer obiektu Timer umieszczamy kod, który chcemy żeby został wykonany, gdy formularz główny jest już w pełni aktywny, a pod kodem umieszczamy instrukcję wyłączającą Timer, np:


Kod: Zaznacz cały
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//kod który chcemy żeby został wykonany, gdy formularz główny jest już w pełni aktywny

Timer1->Enabled = false; // zdezaktywowanie zegara
}


Zdarzenie OnTimer obiektu Timer zostanie wywołane tylko raz i dopiero po tym gdy aplikacja zostanie utworzona, wyświetlona i zostana wywołane wszystkie instrukcje zawarte w zdarzeniach OnCreate, OnShow, OnActivate.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Gazunio » wtorek, 23 czerwca 2009, 18:23

Wielkie dzięki za pomoc.
Teraz mam jeszcze pytanie. Jak wykonać hotkey'sy działające nie tylko przy widocznym oknie programu? Chodzi mi o to, że program sobię minimalizuję to tray'a i uruchamiam inny program, już nie mój, ale po wciśnieciu np. F12 wykonuje się jakaś akcja np. wciśnięcie Button1.
Jak to wykonać?
Avatar użytkownika
Gazunio
Bladawiec
Bladawiec
 
Posty: 32
Dołączył(a): środa, 13 maja 2009, 18:40
Podziękował : 3
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2009
Gadu Gadu: 5147883
    NieznanyNieznana

Re: Ogólne pytanka

Nowy postprzez Cyfrowy Baron » środa, 24 czerwca 2009, 13:52

Trzeba zamontować hak systemowy przechwytujący komunikaty wysyłane do systemu z klawiatury.
Przykład takiego programu znajdziesz w serwisie Cyfrowy Baron w dziale: porady -> API; porada: ]Keyloger, czyli przechwytywanie wciśnięcia klawiszy we wszystkich programach.

Musisz oczywiście zmodyfikować kod do własnych potrzeb.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 3 gości

cron