Historia wymaga pasterzy, nie rzeźników.



Metoda PropDrawValue()
Ta metoda odpowiedzialna jest za wyświetlenie aktualnej wartości edytowanej właściwości, obok
nazwy tej ostatniej. Wysokość komórki jest przy tym sztywno określona przez parametr ARect i
nie można jej zmienić. Jako że wyświetlanie aktualnej „wartości” jest tu w istocie
wyświetlaniem poszczególnych elementów listy wartości, metoda PropDrawValue() może z powodzeniem scedować swe zadanie na metodę ListDrawValue(), podając jako pierwszy z
parametrów wywołania wyświetlany łańcuch zwracany przez metodę GetVisualValue() i
kopiując pozostałe parametry. W przypadku, gdy wyświetlony ma być pusty łańcuch, całą sprawę
załatwić można jeszcze prościej — wypisując ów łańcuch za pomocą metody ACanvas–
>TextRect bądź wywołując odziedziczoną metodę PropDrawValue(). Przedefiniowaną w
opisany sposób metodę PropDrawValue() przedstawia wydruk 10.15.
Wydruk 10.15 Implementacja metody PropDrawValue()
void __fastcall TShapeTypePropertyEditor::PropDrawValue
(Graphics::TCanvas* ACanvas,
const Windows::TRect& ARect,
bool ASelected)
{
if( GetVisualValue() != "" )
{
ListDrawValue(GetVisualValue(), ACanvas, ARect, ASelected);
}
else
{
ACanvas->TextRect( ARect,
ARect.Left+1,
ARect.Top+1,
GetVisualValue() );

// można też użyć konstrukcji:
// inherited::PropDrawValue(ACanvas, ARect, ASelected);
//

}
}

Metoda PropDrawName()
Metoda ta odpowiedzialna jest za wypełnienie pola nazwy właściwości; podobnie jak w przypadku
PropDrawValue() wysokość komórki jest zadana a priori i nie można jej zmienić. Przypadki,
kiedy przedefiniowanie standardowej metody TPropertyEditor przynosi rzeczywiste
korzyści, są naprawdę rzadkie i sprowadzają się w zasadzie do konieczności umieszczenia obok
nazwy właściwości jakiegoś piktogramu symbolizującego jej charakter. Jeden z edytorów naszego
przykładowego pakietu EnhancedEditors — TImageListPropertyEditor — opatruje
właściwości typu TCustomImageList* ikoną charakterystyczną dla komponentu
TImageList, czego przykład widzimy na rysunku 10.7. Wydruk 10.16 przedstawia natomiast
przedefiniowaną metodę PropDrawName() tegoż edytora.

Tu proszę wkleić rysunek z pliku AG-10-A.BMP
Rysunek 10.7 Poprzedzenie ikoną nazwy właściwości

Wydruk 10.16 Przykład przedefiniowanej metody
PropDrawName()
void __fastcall TImageListPropertyEditor::PropDrawName
(Graphics::TCanvas* ACanvas,
const Windows::TRect& ARect,
bool ASelected)
{
// prostokąt przeznaczony na tekst nazwy
TRect ValueRect = ARect;

try
{
// Wyczyść przedmiotowy obszar płótna
ACanvas->FillRect(ARect);

if(GetName() != "") // czy nazwa nie jest pustym łańcuchem?
{
if(Screen->PixelsPerInch > 96)
{
ACanvas->Draw( ARect.Left + 1,
ARect.Top + 2,
ImageListPropertyImage );
}
else
{
ACanvas->Draw( ARect.Left + 1,
ARect.Top,
ImageListPropertyImage );
}


// zmodyfikuj prostokąt przeznaczony na tekst nazwy
ValueRect = Rect( ARect.Left + 16 + 2,
ARect.Top,
ARect.Right,
ARect.Bottom );
}
}
__finally
{
// wypisanie tekstu niezależnie od tego, czy udało się narysowanie ikony
inherited::PropDrawName(ACanvas, ValueRect, ASelected);

// można również użyć następującej konstrukcji:
// ACanvas–>TextRect(
// ValueRect,
// ValueRect.Left+1,
// ValueRect.Top+1,
// GetName()
// );


}

}

Połączyłem listingi 10.16 i 10.17 w jeden listing

Zmienna ValueRect reprezentuje tu prostokąt, w którym wypisana będzie nazwa właściwości.
Początkowo prostokąt ten tożsamy jest z całą komórką Inspektora Obiektów przeznaczoną na
nazwę właściwości, jednak po udanym narysowaniu ikony zmniejszany jest lewostronnie o jej
rozmiar (plus dwupikselowy margines). Rysowany obrazek ukrywa się pod właściwością
ImageListPropertyImage, inicjowaną w konstruktorze zawartością pobraną z zasobu:

__fastcall TImageListPropertyEditor::TImageListPropertyEditor
(const _di_IFormDesigner ADesigner,
int APropCount)
: TComponentProperty(ADesigner,
APropCount)
{
ImageListPropertyImage = new Graphics::TBitmap();

ImageListPropertyImage->LoadFromResourceName(
reinterpret_cast<int>(HInstance),
"RESOURCE_ImageListProperty"
);
}

Wyświetlany obrazek pozycjonowany jest odmiennie w zależności od tego, czy używane są duże
(rozdzielczość co najmniej 96 pikseli na cal) czy małe czcionki.
Instalowanie pakietów zawierających
edytory
Jak już wcześniej pisaliśmy, rejestracja edytora właściwości, polegająca na jego integracją z IDE, wykonywana jest przez funkcję RegisterPropertyEditor(). Wymaga się, by funkcja ta
wywołana była w treści funkcji o nazwie Register(), zamkniętej w przestrzeń nazw
(namespace) o nazwie tożsamej z nazwą pliku, w której występuje — z dokładnością do
wielkości liter: nazwa przestrzeni namespace musi rozpoczynać się od wielkiej litery i w dalszej części być pisana wyłącznie małymi literami. Oto przykład rejestracji edytora
TShapeTypePropertyEditor:
Wydruk 10.17 Rejestracja pakietu edytora #include <vcl.h>
#pragma hdrstop

#include "NameOfThisFile"

// plik zawierający deklarację edytora
#include "PropertyEditors.h"

#include <TypInfo.hpp>

// Plik zawierający deklarację TPropInfo* i GetPropInfo()
#include "GetTypeInfo.h"

//--------------------------------------------------------------------------//
#pragma package(smart_init)
//--------------------------------------------------------------------------//
namespace Nameofthisfile // nazwa rozpoczyna się wielką literą,
// później wyłącznie małe litery


{

void __fastcall PACKAGE Register()
{

// informacja o typie właściwości TShape::Shape
TPropInfo* TShapeTypePropInfo =
Typinfo::GetPropInfo(__typeinfo(TShape), "Shape");

// rejestracja edytora TShapeTypePropertyEditor dla dowolnej
// (tj. bez względu na nazwę) właściwości typu TShapeType
// w dowolnym komponencie


RegisterPropertyEditor(
EnumTypeInfo("TShapeType")*TShapeTypePropInfo->PropType,
0, //dowolny komponent
"", //dowolna właściwość typu TShapeType

Podstrony