Számkonverzió
A mellékelt példa Tip01 projektjében hexadecimális formátumban megadott számokat konvertálhatunk egészre és fordítva. Az egészre konvertálás műveletének lényege, hogy a kapott karakterláncon – mely a hexadecimális számot tartalmazza – visszafelé végigmenve megvizsgáljuk, hogy a lehetséges karakterek közül az adott karakter szám (0..9), vagy betű (A..F). A karaktert először a megfelelő számértékké konvertáljuk, majd egy bitművelet után adjuk a számot az összértékhez.
for(int i=d.Length-1;i>=0;i--)
{
c = d[i];
h2 = d.Length-i-1;
if (c>='A' && c<='F')
{
h1 = Convert.ToInt32(c)-55;
result += (h1 << (h2 << 2));
}
else if (c>'0' && c<='9')
{
h1 = Convert.ToInt32(c)-48;
result += (h1 << (h2 << 2));
}
...
Az egész szám konvertálásakor egy hátul tesztelő ciklusban képezzük a szám hexadecimális karaktereit. A ciklusban a szám bitjeit tologatjuk jobbra, vagyis a számot reprezentáló bitsorozatot fél bájtos csoportokban – a végéről az elejére haladva – megvizsgáljuk, és eldöntjük, hogy mely bitje 1 értékű (ÉS művelet a 0x0F számmal).
do
{
v = Convert.ToByte((number >> d) & 0x0F);
A kapott értéket szám- vagy betűkarakterré konvertáljuk, és beszúrjuk az eredmény-karakterlánc elejére.
if (v > 9)
{
r = Convert.ToChar(v+55) + r;
}
else
{
r = Convert.ToChar(v+48) + r;
}
d+=4;
Ezt a műveletet egészen addig folytatjuk, míg a szám nagyobb, mint az a bináris érték, melyet mindig növelünk 0xF értékkel.
GraphicsPath osztály Warp metódusa
A Warp metódus segítségével képesek vagyunk tetszőleges konverziókat elvégezni a megjelenítendő alakzatokon, vagy szövegeken.
A műveletet a Form OnPaint eseménykezelőjébe ágyaztuk. A feladatban egy karakterláncot fogunk piramis alakban egymás fölé kiírni úgy, hogy az adott lánc fölötti lánc mindig arányosan rövidebb lesz.
Ehhez szükség van egy GraphicsPath objektumra, mellyel összefüggő ponthalmazokat rajzolhatunk ki.
GraphicsPath path = new GraphicsPath();
A szöveget háromszor fogjuk kiírni, így az objektumban háromszor eltároljuk, a pozícióikat megfelelően változtatva.
for(int i=0;i<3;i++)
{
path.AddString(s,ff,0,70,new Point(0,90*i), StringFormat.GenericTypographic);
}
A következőkben létrehozunk egy pontlistát, mely a szövegeket befoglaló paralelogramma pontjait tartalmazza.
PointF[] points = new PointF[]
{
new PointF(this.ClientSize.Width/2-this.ClientSize.Width/4,50),
new PointF(this.ClientSize.Width/2+this.ClientSize.Width/4,n),
new PointF(0,this.ClientSize.Height),
new PointF(this.ClientSize.Width,this.ClientSize.Height)
};
A Warp metódusnak átadva ezeket, kirajzolható a három karakterlánc. A metódus elintézi az igazításokat.
path.Warp(points,new RectangleF(0,0,820,450));
A Graphics osztály segítségével színezhetjük a fenti objektum karakterláncait úgy, hogy meghívjuk annak FillPath metódusát.
e.Graphics.FillPath(Brushes.Blue,path);
A Form-ra helyezett ComboBox kontrol segítségével változtathatjuk, hogy a szövegek vízszintesen, vagy kicsit lejtve jelenjenek meg.
Kép méretre igazítása transzformációval
A projekt mappájában elhelyezett, a Form területénél lényegesen nagyobb méretű képet fogjuk összenyomva, a kívánt méretre igazítva megjeleníteni.
A kép magassági és szélességi adatait elosztjuk a befoglaló terület megfelelő értékeivel, majd eldöntjük, hogy a két szám közül melyik a nagyobb.
double max = Math.Max((double)image.Width/ClientSize.Width,(double)image.Height/ClientSize.Height);
float posX = 0;
float posY = (float)(ClientSize.Height*max/2-image.Height/2+100);
Létrehozzuk a transzformációhoz szükséges Matrix objektumot.
Matrix m = new Matrix(1.0f/(float)max,0,0,1.0f/(float)max,0,0);
A mátrix objektum Translate metódusa segítségével végzünk egy vektortranszformációt.
Majd a Graphics objektum Transform property-jének értékül adjuk a Matrix objektumot.
e.Graphics.Transform = m;
A Graphics osztály DrawImageUnscaled metódusával pedig kirajzoljuk a képet.
e.Graphics.DrawImageUnscaled(image,0,100);
ComboBox kontrol legördítése
A ComboBox kontrolok jellemzője, hogy csak a kis gombra kattintva érhetjük el, hogy a lista legördüljön. Számtalan alkalmazásban – többek közt a Windows-ban is – találkozhatunk olyan megoldással, hogy a kontrol területének tetszőleges pontjára kattintva az legördül, és a lista feltárul.
A Tip04Library projektben elkészítettünk egy kontrolt, mely hasonlóan működik. Csupán az OnMouseUp kezelőmetódusát kell felülírnunk. A kontrol gombjára kattintva az eseménykezelés hagyományos módon zajlik le, vagyis a lista legördül.
A gomb területének egyéb helyeire kattintva viszont más módszert alkalmazunk. Itt elküldünk egy üzenetet a SendMessage metódussal. A metódus deklarációja a következő:
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
A metódus paraméterei sorban a következők:
- A kontrol kezelője, mely az üzenetet tartalmazza.
- Az üzenet.
- Az üzenet első paramétere.
- Az üzenet második paramétere.
A kontrolnak történő üzenetküldés a következőképpen fest:
if (e.X < ClientRectangle.Width-20 && e.X >= 0)
{
SendMessage(Handle,0x100,0x73,0x3E0001);
}
A 0x100 értékű üzenet okozza a legördülést, melynek paraméterei 0x73 és 0x3E0001. Most már tetszőleges helyen kattinthatunk a kontrolon.
Regisztrált Win32 modulok lekérdezése
A Visual Studio.NET Tools menüjének OLE/COM Object Viewer pontjára kattintva elindul egy segédalkalmazás, amely lehetővé teszi, hogy a számítógépen regisztrált komponenseket és modulokat szemrevételezzük, vagy hasznos információkat kapjunk róluk. Ebben a szakaszban megvizsgáljuk, hogyan kérdezhetjük le ezeknek a moduloknak a nevét és elérési útvonalát programból.
A műveletben a Rendszerleíró adatbázis bejegyzéseit olvassuk ki sorban, hogy megtudjuk a fenti információkat. Ezek a bejegyzések a Registry HKEY_CLASSES_ROOT alatti TypeLib könyvtárába kerülnek. Itt először az egyes modulok GUID azonosítóit láthatjuk. Egy azonosító alatt egy modul több verzióban is szerepelhet. Az egyes verziók az azonosítón belül külön könyvtárat kapnak, melynek neve az adott verziószám.
A keresett modul nevét ezen a könyvtáron belül találhatjuk meg. Itt egyetlen sztring típusú bejegyzés szerepel, amely nem rendelkezik változónévvel. Az értéket az üres sztring (””) azonosítja.
A modult tartalmazó állomány elérési útját egy számot tartalmazó könyvtárban elhelyezkedő win32 könyvtárból olvashatjuk ki. Pl: ...9\WIN32.
A GetInstalledModules metódusban a következőket tesszük:
Elsőként megnyitjuk a HKEY_CLASSES_ROOT kulcsot, majd annak typelib alkulcsát.
RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.ClassesRoot, "");
RegistryKey subkey = key.OpenSubKey("typelib");
A megnyitott kulcs alatt található bejegyzések már a modulok adatait tartalmazzák. Ezeket egy listába gyűjtjük.
string[] moduls = subkey.GetSubKeyNames();
Egy ciklusban mindet megnyitjuk, és az alatta található kulcsokat (verziószámok) is kigyűjtjük.
for(int i=0;i<subkey.SubKeyCount;i++)
{
RegistryKey modulkey = subkey.OpenSubKey(moduls[i]);
string[] entries = modulkey.GetSubKeyNames();
A verziószám mappák egy értékkel rendelkeznek, mely a modul nevét tartalmazza. Ezt a Module struktúra modulename mezőjében helyezzük el.
for(int j=0;j<modulkey.SubKeyCount;j++)
{
if (Char.IsNumber(entries[j][0]))
{
RegistryKey versionkey = modulkey.OpenSubKey(entries[j]);
m = new Module();
m.modulename = versionkey.GetValue("").ToString();
A verziószám mappák alkulcsokat tartalmaznak, de ezek közül csak a szám feliratú mappák a fontosak. Ezek win32 almappáinak egy bejegyzését olvassuk ki a modul elérési útvonalának kigyűjtéséhez.
string[] subentries = versionkey.GetSubKeyNames();
for(int k=0;k<versionkey.SubKeyCount;k++)
{
if (Char.IsNumber(subentries[k][0]))
{
m.modulepath = " " + versionkey.OpenSubKey(subentries[k]).OpenSubKey("win32").GetValue("").ToString();
list.Add(m);
}
}
...
A művelet végén bezárjuk a subkey kulcsot, és a Module struktúrákat sorban felfűzzük egy listába, melyet a metódus visszaad.
A lista elemeit elhelyezzük a ListBox kontrolban, kicsit beljebb helyezve el az elérési útvonalat.
ArrayList l = GetInstalledModules();
for(int i=0;i<l.Count;i++)
{
Module m = (Module)l[i];
listBox1.Items.Add(m.modulename);
listBox1.Items.Add(m.modulepath);
}
Internet Explorer HISTORY listájának lekérdezése
Az Explorer azon listáját, mely az utoljára látogatott lapok címeit tartalmazza, szintén a Regisztry megfelelő kulcsának kiolvasásával kérdezhetjük le.
A címek listája a Registry-ben található az alábbi kulcs alatt:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\TypedURLs
Ez alatt a kulcs alatt urlX nevű sztring típusú értékek vannak. A névben az X egy sorszámot jelöl.
A GetHistoryList metódusban kigyűjtjük a látogatott címek listáját, majd egy ArrayList objektumban visszaadjuk ezeket.
Ehhez megnyitjuk a fent említett kulcsot.
RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.CurrentUser, "");
RegistryKey subkey = key.OpenSubKey("Software\\Microsoft\\internet Explorer\\TypedURLs");
Kilistázzuk a kulcs alatti bejegyzések neveit.
string[] values = subkey.GetValueNames();
Majd ezeket a neveket megadva a GetValue metódusnak, kigyűjthetjük a címeket.
for(int i=0;i<subkey.ValueCount;i++)
{
list.Add(subkey.GetValue(values[i]));
}
Az eredményt a Form ListBox kontroljában helyezzük el.