A készítendő új kontrolhoz két ilyen Color típusú property-t hozunk létre. A kontrol feladata az lesz, hogy a megadott két szín között színátmenetet rajzoljon ki a teljes területére. Az új kontrol a mellékelt TestControl02 alkönyvtárban található.
Nézzük most a megvalósítást. A kontrol forrása a UserControl2.cs-ben található.
Első teendőnk a kontrol konstruktorában van.
public UserControl2()
{
InitializeComponent();
Itt kell beállítanunk, hogy a kontrol átlátszó legyen. A kontrolunk valójában nem lesz átlátszó, mivel annak teljes területét mi rajzoljuk ki, de pont ez a lényege ennek a lépésünknek, hiszen ha az átlátszóság tulajdonság beállított, akkor nem történik meg a háttér automatikus kifestése a BackColor színnel. Mivel minden esetben a teljes területet újrarajzoljuk ez amúgy is csak egy felesleges lépés lenne.
SetStyle(ControlStyles.Opaque, true);
Következő lépésként rendelkezünk arról, hogy amennyiben a kontrol mérete megváltozik, akkor a terület újrarajzolása automatikusan megtörténjen, vagyis a Paint esemény létrejöjjön.
SetStyle(ControlStyles.ResizeRedraw, true);
}
A kontrol property-jeihez szükségünk lesz két Color típusú változóra, valamint egy LinearGradientMode típusú változóra is. Ez utóbbiban azt fogjuk tárolni, hogy a színátmenet a kontrol területén vízszintes, vagy függőleges irányban történjen-e kirajzolásra.
private Color FColorStart = Color.White;
private Color FColorEnd = Color.Black;
private LinearGradientMode FGradientMode = LinearGradientMode.Horizontal;
Ha változóink adottak, akkor hozzuk létre a property-ket is. Mivel a két Color típusú property-hez új property szerkesztőt is szeretnénk létrehozni, így ezt egy attribútumba tudjuk megadni a property deklarációja előtt. Az Editor attribútum első paraméterében a szerkesztő osztály típusát, míg másodikban annak ősének típusát kell megadnunk. A property további részeiben újdonság nincs. Fontos, hogy a set metódusnál rendelkezzünk arról, hogy a kontrol területe újra rajzolásra kerüljön, mivel itt változott az egyik szín.
[
Editor(typeof(ColorEditorClass), typeof(UITypeEditor))
]
public Color ColorStart
{
get { return FColorStart; }
set
{
FColorStart = value;
Invalidate();
}
}
A Paint eseményét felhasználva a kontrolnak elvégezhetjük a színátmenet kirajzolását.
Ehhez egy színátmenetes ecsetre lesz szükségünk, melyet a LinearGradientBrush osztály valósít meg. Ennek konstruktorában meg kell adnunk, hogy mekkora területen fogjuk a színezést elvégezni, amely nyilván egyezik a kontrol méretével. A következő két paraméter lesz a két szín, amely között a színátmenetet létre kell hozni, végül arról rendelkezünk, hogy vízszintes, vagy függőleges irányba történjen-e meg a színátmenet képzés.
private void UserControl2_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
LinearGradientBrush brush = new LinearGradientBrush(ClientRectangle, FColorStart, FColorEnd, FGradientMode);
Ezt követően már csak ki kell rajzolnunk a létrehozott ecsettel egy akkora téglalapot, mely fedi a kontrol teljes területét.
e.Graphics.FillRectangle(brush, ClientRectangle);
}
Eddig csak felhasználtuk, de elkészítésével még nem foglalkoztunk, így nézzük most miként jön létre a ColorEditorClass osztály, melyet a ColorEditorClass.cs forrásban helyeztünk el.
A létrehozott új osztályt az UITypeEditor-ból kell származtatnunk.
public class ColorEditorClass: System.Drawing.Design.UITypeEditor
Ebben felül kell írnunk a GetEditStyle függvényt. Ez kerül meghívásra akkor, amikor a Visual Studio.NET Properties ablakában egy property-re kattintunk és el kell dönteni, hogy milyen típusú property szerkesztő tartozik hozzá.
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
if (context != null && context.Instance != null)
{
Ezt a visszatérési értéken keresztül tudjuk megadni, mely az UITypeEditorEditStyle felsorolt típus egyik eleme lehet. Nekünk most a DropDown értékre van szükségünk, mivel egy legördíthető ablakot szeretnénk kapni a property-hez.
return UITypeEditorEditStyle.DropDown;
}
return base.GetEditStyle(context);
}
Hamarosan szükségünk lesz egy IWindowsFormsEditorService típusú változóra, így most készítünk egy ilyet.
private IWindowsFormsEditorService wfes = null;
A következő felhasználandó függvény, melyet szintén felülírunk az EditValue lesz. Ez akkor fut, amikor a felhasználó legördíti a property-hez tartozó ablakot, így ez lesz az a pont, amikor nekünk ezt meg kell jeleníteni és a property értékének szerkesztését elvégezni.
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
if (context != null && context.Instance != null && provider != null)
{
Az imént létrehozott wfes nevű változónknak itt adunk értéket, melyben tároljuk a szerkesztő szolgáltató osztályát, hogy azt a későbbiek folyamán is elérhessük.
wfes = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
if (wfes != null)
{
A következő lépés lesz, hogy megjelenítünk egy kontrolt, melyben a szerkesztés elvégezhető. Mivel olyan kontrol nem áll rendelkezésre, melyben három TrackBar segítségével elvégezhető egy RGB szín kikeverése, így ezt is nekünk kell majd megvalósítani. Így létrehozunk egy DropControl-nak nevezett új kontrolt, melynek részletes leírására hamarosan visszatérünk.
DropControl dc = new DropControl();
Lesz ennek a kontrolnak egy property-je, mely Color típusban várja a property aktuális értékét, melyet majd szerkeszthetünk a segítségével. Ezt úgy tudjuk számára átadni, hogy a paraméterként kapott value értékét átadjuk.
dc.ColorValue= (Color)value;
A következő lépésben rendelkezhetünk a kontrol megjelenítéséről, melyhez az IWindowsFormsEditorService interfész DropDownControl függvényét kell meghívnunk, paraméterként átadva a megjelenítendő kontrolt.
wfes.DropDownControl(dc);
A property értékének szerkesztése végeztével a programunk futása ezen a ponton folytatódik, így itt a kontrol ColorValue property-jén keresztül lekérdezhetjük az újonnan beállított szín értéket.
value = dc.ColorValue;
}
}
A kapott színt kell a függvény visszatérési értékekén megadnunk, így ez lesz az adott property új értéke.
Térjünk most át a DropControl.cs-ban létrehozott DropControl objektum tárgyalására. Ez lesz az az új kontrol, mely tartalmaz három TrackBar-t az R, G és B színcsatorna értékének megválasztásához. Amikor e három TrackBar közül valamelyiket mozgatja a felhasználó, akkor létrejön a Scroll esemény. Ez lesz a pillanat, amikor kiszámítjuk az új Color színt és ezt rögtön be is állítjuk a kontrol háttérszínének, így az aktuális szín vizuálisan is látható lesz.
private void trackBar1_Scroll(object sender, System.EventArgs e)
{
BackColor = Color.FromArgb(trackBar1.Value, trackBar2.Value, trackBar3.Value);
}
Létre kell még hoznunk egy property-t ColorValue névvel. Ezen keresztül fogja a ColorEditorClass osztály tartani a kapcsolatot. Vagyis amikor megjelenik a Properties ablaknál a DropControl, akkor a ColorValue-jén keresztül kerül átadásra az aktuális szín, majd ezen keresztül is lesz kiolvasva a beállítás után.
public Color ColorValue
{
get
{
Amikor a property értékére van szükség, akkor azt vehetjük a kontrol háttérszínéből, hiszen a TrackBar-ok segítségével itt állítjuk be az aktuális színt.
return BackColor;
}
set
{
Amikor értéket adunk a property-nek, akkor be kell állítanunk a kontrol háttérszínét az adott színre, valamint a három TrackBar aktuális pozícióját is meg kell adnunk az adott szín összetevőinek értéke alapján.
BackColor = value;
trackBar1.Value = value.R;
trackBar2.Value = value.G;
trackBar3.Value = value.B;
}
}
Az új kontrol a hozzátartozó property szerkesztővel ezennel kész, most már csak fordítanunk és telepítenünk kell azt a Toolbox-ra, hogy használhassuk azt.