Komponent rozszerzający możliwość innego komponentu
Jak sama nazwa mówi, tworzymy komponent który będzie oparty o inny komponent. Nie będziemy dodawali żadnych nowych własności czy zdarzeń – po prostu pozmieniamy początkowe ustawienia danego komponentu. Dla przykładu weźmy TRichEdit i na nim oprzyjmy nasz pierwszy komponent.
To, co dla nas istotne, że konstruktor przekazuje jeden parametr TComponent* Owner, czyli wskaźnik do właściciela osadzonego komponentu. W naszym przypadku będzie to wskaźnik do Form1 (bo na nim będziemy osadzać nasz komponent)
Dlaczego akurat TComponent? Jak mówiłem, jest to klasa bazowa dla wszystkich komponentów. Nie trudno się domyśleć, że musimy pobrać uchwyt rodzica...
Dodatkowo musimy pamiętać, że jesteśmy wewnątrz klasy, dlatego odwoływanie się do konkretnej właściwości czy zmiennej klasie musimy zrobić za pośrednictwem wskaźnika this (jak powyżej).


- Tworzymy nowy projekt (uruchamiamy C++Builder’a)
- Z menu wybieramy Component —> New Component
- Nastepnie wypełniamy okno dialogowe wg schematu:
- Ancestor type: TRichEdit
- Class Name: TRichIP
- Palettce Page: System32 (nazwa zakładki)
- Unit file name: ścieżka do pliku cpp gdzie zapiszemy kod komponentu
- Search path: nic nie zmieniamy (samo się zmodyfikuje )
- Ancestor type: TRichEdit
- Powstaje kod komponentu, w którym musimy zmienić tylko konstruktor jak w kodzie poniżej.
__fastcall TRichIP::TRichIP(TComponent* Owner)
: TRichEdit(Owner)
{
SECURITY_ATTRIBUTES sat;
STARTUPINFO startupinfo;
PROCESS_INFORMATION pinfo;
HANDLE hRead;
HANDLE hWrite;
char buffer[1024];
DWORD bytesRead;
// !-- Bardzo istotne --!
this->Parent = dynamic_cast<TWinControl*>(Owner);
// Przykładowe parametry RichEdita
this->Clear();
this->Color = clBlack;
this->Font->Color = clYellow;
this->Font->Name = "Verdana";
this->Font->Size = 10;
this->Font->Style = this->Font->Style << fsBold;
//Tworzenie potoku...
sat.nLength = sizeof(SECURITY_ATTRIBUTES);
sat.lpSecurityDescriptor = NULL;
sat.bInheritHandle = TRUE;
CreatePipe((PHANDLE)&hRead, (PHANDLE)&hWrite, &sat, NULL);
//Uruchamianie procesu...
startupinfo.cb = sizeof(STARTUPINFO);
GetStartupInfo(&startupinfo);
startupinfo.hStdOutput = (PHANDLE)hWrite;
startupinfo.hStdError = (PHANDLE)hWrite;
startupinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startupinfo.wShowWindow = SW_HIDE;
CreateProcess(NULL, "ipconfig", NULL, NULL, TRUE, NULL,
NULL, NULL, &startupinfo, &pinfo);
//Zapisanie wyniku do RichEdita
RtlZeroMemory(buffer, 1024);
ReadFile(hRead, buffer, 1023, &bytesRead, NULL);
this->Lines->Add( buffer );
//Zamkniecie potoku i uchwytow do procesu
CloseHandle(hRead);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
//Kolorowanie ipkow i nie tylko
int pos=1, pos2=-1;
while(1)
{
pos = this->FindTextA(":", pos,
this->Lines->Text.Length(),TSearchTypes()<< stMatchCase);
if (pos == -1) break;
pos2 = this->FindTextA("\n", pos+1,
this->Lines->Text.Length(),TSearchTypes()<< stMatchCase);
if (pos2 == -1) break;
this->SelStart = pos+1;
this->SelLength = pos2 - pos - 1;
this->SelAttributes->Color = clRed;
pos = pos2+1;
}
this->SelStart = 0;
}
: TRichEdit(Owner)
{
SECURITY_ATTRIBUTES sat;
STARTUPINFO startupinfo;
PROCESS_INFORMATION pinfo;
HANDLE hRead;
HANDLE hWrite;
char buffer[1024];
DWORD bytesRead;
// !-- Bardzo istotne --!
this->Parent = dynamic_cast<TWinControl*>(Owner);
// Przykładowe parametry RichEdita
this->Clear();
this->Color = clBlack;
this->Font->Color = clYellow;
this->Font->Name = "Verdana";
this->Font->Size = 10;
this->Font->Style = this->Font->Style << fsBold;
//Tworzenie potoku...
sat.nLength = sizeof(SECURITY_ATTRIBUTES);
sat.lpSecurityDescriptor = NULL;
sat.bInheritHandle = TRUE;
CreatePipe((PHANDLE)&hRead, (PHANDLE)&hWrite, &sat, NULL);
//Uruchamianie procesu...
startupinfo.cb = sizeof(STARTUPINFO);
GetStartupInfo(&startupinfo);
startupinfo.hStdOutput = (PHANDLE)hWrite;
startupinfo.hStdError = (PHANDLE)hWrite;
startupinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startupinfo.wShowWindow = SW_HIDE;
CreateProcess(NULL, "ipconfig", NULL, NULL, TRUE, NULL,
NULL, NULL, &startupinfo, &pinfo);
//Zapisanie wyniku do RichEdita
RtlZeroMemory(buffer, 1024);
ReadFile(hRead, buffer, 1023, &bytesRead, NULL);
this->Lines->Add( buffer );
//Zamkniecie potoku i uchwytow do procesu
CloseHandle(hRead);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
//Kolorowanie ipkow i nie tylko
int pos=1, pos2=-1;
while(1)
{
pos = this->FindTextA(":", pos,
this->Lines->Text.Length(),TSearchTypes()<< stMatchCase);
if (pos == -1) break;
pos2 = this->FindTextA("\n", pos+1,
this->Lines->Text.Length(),TSearchTypes()<< stMatchCase);
if (pos2 == -1) break;
this->SelStart = pos+1;
this->SelLength = pos2 - pos - 1;
this->SelAttributes->Color = clRed;
pos = pos2+1;
}
this->SelStart = 0;
}
To, co dla nas istotne, że konstruktor przekazuje jeden parametr TComponent* Owner, czyli wskaźnik do właściciela osadzonego komponentu. W naszym przypadku będzie to wskaźnik do Form1 (bo na nim będziemy osadzać nasz komponent)
Dlaczego akurat TComponent? Jak mówiłem, jest to klasa bazowa dla wszystkich komponentów. Nie trudno się domyśleć, że musimy pobrać uchwyt rodzica...
this->Parent = dynamic_cast<TWinControl*>(Owner);
Dodatkowo musimy pamiętać, że jesteśmy wewnątrz klasy, dlatego odwoływanie się do konkretnej właściwości czy zmiennej klasie musimy zrobić za pośrednictwem wskaźnika this (jak powyżej).
- Po dokonaniu zmian zapisujemy (tak dla pewności)
- Następnie instalujemy komponent w standardowym pakiecie
- Component —> Install Component
- Unit file name: ścieżka do naszego pliku cpp
- Serach path: nic nie zmieniać (automatycznie)
- Package file name: {$C++BUILDER}Lib DCLUSR50.bpk
- Wciskamy OK. i potwierdzamy ReBuildowanie pakietu, w razie wyskoczenia jakiegoś błędu, który nie ma związku ze skłądnia należy się upewnić o istnieniu katalogów {$C++BUILDER}ProjectsLib i {$C++BUILDER}ProjectsBpl (w tym ostatnim katalogu znajduje się skompilowany pakiet naszą kontrolką)
- Unit file name: ścieżka do naszego pliku cpp
- Component —> Install Component
- Zamykamy wszystko File —> Close All (zapisujemy zmiany)
- Tworzymy nowy projekt File —> New —> Application
- Dodajemy pakiet do projektu Projekt —> Options
- Z zakładki Packages wciskamy Add i z katalogu {$C++BUILDER}ProjectsBpl zaznaczamy plik DCLUSR50.bpl (wszystko co opisuje dotyczy C++Builderze 5.0 Professional – jak w innych – myślę, że podobnie)
- Pojawiła się zakładka System32, na której jest komponent o ładnej nazwie RichIP – wrzucamy na nasz formularz – kompilujemy – i działa...


Autorem tekstu jest:
Wojciech Bojewski
Materiał dodany przez użytkownika: _hador_
