maandag 2 juli 2007

LinearGradient

Iedereen die wel eens wat heeft moeten tekenen in een Paint event weet dat het niet altijd even makkelijk is of anders heel veel werk. Tijdens de DevDays werd er gezeged dat een Gradient (overgang tussen twee kleuren) elke applicatie een stuk mooier maakt.

Voor mijn PDA heb ik een simpele klok applicatie geschreven maar iedereen die hem zag vond hem vreselijk lelijk. Daarom wilde ik graag een LinearGradient toevoegen.

Normaal gesproken gaat dat in twee stappen:
-Maak een Brush object aan (LinearGradientBrush)
-Gebruik van een Graphics object de FillRectangle methode en geef de brush als parameter mee. (De fillXX methode verwacht ook een Rectangle(x,y,width,height)

Nu zal je natuurlijk altijd zien dat een LinearGradientBrush niet beschikbaar is in een Windows Mobile/PDA omgeving.

Ik wilde natuurlijk wel een mooie gradient in mijn applicatie dus ik moest aan het werk. Mijn gereedschap was als volgt:

Een kleur bestaat uit drie kanalen -> red green blue met een waarden van 0 - 255
De nul waardes zijn zwart en de 255 waardes zijn de volledige kleur. Combinaties van kleuren zijn te maken door de verschillende kleuren meer of minder te gebruiken.

Ik kan in een For loopje kleuren aanpassen

De Solidbrush kan ik gebruiken om in één kleur te tekenen.

Het graphics object heeft een fillrect waarmee ik een pixel breed en de gewenst hoogte kan tekenen.

De code die ik gebruikt heb is als volgt:

///
/// Deze code tekend een gradient van de kleur donker zwart (50,10,50)
/// naar de kleur groen (50,240,50)
///

///
void drawGradient(Graphics g)
{
for (int x = 10; x < (this.Width + 10); x++)
{
Color c = Color.FromArgb(50,x , 50);
Rectangle rect = new Rectangle(x -10, 0, 1, this.Height);
Brush b = new SolidBrush(c);
g.FillRectangle(b, rect);
}
}

Dit is natuurlijk geen code die:

Mooi geschieden is van zijn container(breedte 255 pixels + en er komt een exception)
Werkt met variabele kleuren (van zwartig naar groening)
Logische parameters heeft (breedte/hoogte)
Code die goed omgaat met mogelijke exceptions

Daarom heb ik ook meteen maar een functie gemaakt in een static class die daar iets beter mee omgaat:

public static void drawGradient(Graphics g, int x, int y, int width, int height, Color start,Color end)
{
for (int i = x; i < width; i++)
{
int rs, gs, bs = 0;
rs = start.R;
gs = start.G;
bs = start.B;

int re, ge, be = 0;
re = end.R;
ge = end.G;
be = end.B;

//float diffR, diffG, diffB = 0F;
int ri, gi, bi;
ri = calcDiff(rs,re,width,i);
gi = calcDiff(gs, ge, width, i);
bi = calcDiff(bs, be, width, i);
if (gi > 255)
gi = gi;
Color c = Color.FromArgb(ri,gi,bi);
Brush b = new SolidBrush(c);

Rectangle r = new Rectangle(x+i, y, 1, height);
g.FillRectangle(b, r);
}
}

static int calcDiff(int rs, int re, int width, int i)
{
float diff = 0F;
int move = re - rs;
float mt, wt;
mt = (float)move;
wt = (float)width;
diff = (mt / wt) * i;
if (move > 0)
move = move;
diff += rs;

return (int)diff;
}

Geen opmerkingen: