Akik már programoztak Visual C++ nyelven, azok biztosan tudják mekkora előnye van ennek a magas szintű programnyelvnek a Visual Basic-kel szemben. Bár a VB igen gyors és kellemes programfejlesztést tesz lehetővé, azonban az általa nyújtott rendszerszintű programozást lehetővé tevő eszközök köre igen korlátozott. Azonban ezen eszközök bizonyos szintű bővítésére ad lehetőséget - bár csak korlátozott mértékben - a Windows API függvények VB-ből történő meghívásának lehetősége. Pár példán keresztül nézzük meg, milyen lehetőségek rejlenek ezen API függvények VB-ből történő meghívásában, és melyek azok az alapvető eszközök, amiket érdemes is használnunk.

Először is nézzük meg mit is értünk Windows API elnevezés alatt. A Windows API (Application Programming Interface) olyan függvények, rendszer üzenetek, adat struktúrák, adat típus deklarációk gyűjteménye, mely gyűjtemény elemeit tetszés szerint felhasználhatjuk Microsoft Windows alatt futó alkalmazások fejlesztésében. Ezen elemek gyűjteménye tetszés szerint bővíthető, vagyis saját magunk is írhatunk ilyen rendszerszintű "elem-gyűjteményeket". Tekintsük át, hogy VB alól milyen módon érhetjük el ezen rendszerelemeket.

A VB-ben használni kívánt függvényhívásokat úgymond deklarálnunk kell. A deklaráció az alábbi szintaxisok alapján történhet:

[Public | Private] Declare Sub name Lib "libname"                           [Alias "aliasname"] [([arglist])] [Public | Private] Declare Function name Lib "libname"                         [Alias "aliasname"] [([arglist])] [As type]
 
Public Opcionális. Akkor használatos, ha a deklarált eljárást/függvényt az alkalmazás minden moduljából el szeretnénk érni.
Private Opcionális. A deklarált eljárás/függvény csak a deklarációs modulban használható.
Sub Opcionális. Jelzi, hogy a deklarált eljárás nem ad vissza értéket.
Function Opcionális. Jelzi, hogy a deklarált függvény értékkel tér vissza melyet különböző kifejezésekben fel is használhatunk.
name Kötelező. Az eljárás/függvény neve.
Lib Kötelező. Jelzi a DLL vagy egyéb kódforrás deklarációjának kezdetét.
libname Kötelező. Annak a DLL-nek vagy kódforrásnak a neve ahol az eljárás/függvény deklarálásra került.
Alias Opcionális. Az "álnév" deklarációjának kezdete.
aliasname Opcionális. A deklarált eljárás/függvény "álneve", vagy az eljárás ún. belépési pontja a DLL-ben.
arglist Opcionális. Az átadott paraméterek listája.
type Opcionális. A visszaadott érték típusa.

Az arglist argumentum szintaxisa:

[Optional] [ByVal | ByRef] [ParamArray] varname[( )] [As type]
 
Optional Opcionális. Jelzi, hogy a megadott argumentum nem kötelező. ParamArray argumentum esetén nem használható.
ByVal Opcionális. Érték szerinti paraméter átadást jelez.
ByRef Címszerinti paraméterátadást jelez. Alapértelmezett mód.
ParamArray Opcionális. Variant típusú tömb paramétert jelöl. Nem használható a ByVal, ByRef és Optional kulcsszavakkal.
varname Kötelező. A paraméter neve.
() Szükséges tömb változók esetén. Jelzi, hogy a varname egy tömb.
type Opcionális. A paraméter típusa.

A VB felhasználóinak igen nagy segítséget jelent az API függvények deklarációinak elkészítésében egy egyszerű kis segédprogram az API Viewer. Minden VB szinten elérhető függvény, adattípus, adat struktúra és konstans deklarációját tartalmazza, így a programozónak elég csak a szükséges elemet kiválasztania és a hozzá tartozó deklaráció azonnal generálódik.

Most, hogy már ismerjük az API függvények deklarálásának módját nézzünk át pár egyszerű és igen hasznos példát.

ShapeForm

Készítsünk egy olyan dialógusablakot, mely nem a már megszokott form formátumban jelenik meg, hanem egy általunk megrajzolt szabálytalan formátumú alakzathoz igazodik. Nézzük meg milyen API függvények és eljárások deklarációjára lesz szükségünk.

Függvény deklarációk.

Public Declare Function GetPixel Lib "gdi32"     (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
 
hDC Egy DeviceContext handle. (Ezen a területen kérjük le az adott pixelt)
X,Y A pixel X,Y koordinátái.
return value Egy long típusú érték, amely a pixel színét mutatja meg.

Egy adott Device Context egy pixelének színét kérhetjük le.

pixelColor = GetPixel(bg.hdc, X, Y)



Public Declare Function SetWindowRgn Lib "User32"               (ByVal hWnd As Long,                ByVal hRgn As Long,                ByVal bRedraw As Boolean) As Long
 
hWnd Window handle. Az adott ablak "címe". (Egy pointer)
hRgn Egy RECT területre mutató pointer. (pl. egy dialógusablak egy adott területére mutathat)
hRedraw A terület újrarajzolását teszi lehetővé.

A jelzett hWnd-jű objektum egy adott területét állítjuk be az átadott hRgn objektummal.



Public Declare Function CreateRectRgn Lib "gdi32"                 (ByVal X1 As Long,                  ByVal Y1 As Long,                  ByVal X2 As Long, ByVal Y2 As Long) As Long

Az aktuális ablak megadott koordinátákkal körülhatárolt területét kérhetjük le.


Public Declare Function CombineRgn Lib "gdi32"                 (ByVal hDestRgn As Long,                  ByVal hSrcRgn1 As Long,                  ByVal hSrcRgn2 As Long,                  ByVal nCombineMode As Long) As Long
 
hDestRgn Cél területre mutató pointer.
hSrcRgn1 Forrás területre mutató pointer. 
hSrcRgn2 A másik forrás terület címe.
nCombineMode A két forrás terület kombinálásának módja.

Két adott területre mutató objektumot "kombinálhatunk" egy újabb cél területre különböző módok alapján.


Public Declare Sub ReleaseCapture Lib "User32" ()

Érzékeli az egér formmal történő "kommunikációját". (Segítségével pl. meg tudjuk oldani egy fejléc nélküli form mozgatását.)


Public Declare Function DeleteObject Lib "gdi32"                                   (ByVal hObject As Long) As Long

A megadott pointer által mutatott objektumot törölhetjük.



Public Declare Function SendMessage Lib "User32" Alias "SendMessageA"                         (ByVal hWnd As Long,                          ByVal wMsg As Long,                          ByVal wParam As Long,                          lParam As Any) As Long
 
hWnd Egy dialógusablakra mutató ponter.
wMsg A rendszerüzenet.
wParam A rendszerüzenet paramétere.
lParam A rendszerüzenet paramétere.

Rendszerszintű üzeneteket küldhetünk az OP rendszer felé. (Példánkban ezt használjuk a fejléc nélküli form mozgatására.)
 

Konstansok
 

Public Const RGN_DIFF = 4
A területek kombinációjánál a kombináció módját átlátszó típusként definiálhatjuk.
 
Public Const WM_SYSCOMMAND = &H112
Rendszerszintű üzenetet küldhetünk a SendMessage függvényt használva (wMsg paraméter).
 
Public Const SC_CLICKMOVE = &HF012&
A WS_SYSCOMMAND rendszerüzenet használatakor az egér lenyomásakor előidézhető ablak mozgatást válthatjuk ki.
 
Public Const WM_NCLBUTTONDOWN = &HA1 Public Const HTCAPTION = 2
Szintén rendszer szintű üzenetek, melyek segítségével a dialógusablak fejlécén történő kattintás szimulálható. Szintén keret nélküli ablakok mozgatására használható.
 

Első feladatunk a ShapeForm elkészítése. Tegyük a következőt. Rajzoljunk egy tetszüleges zárt vonalakból álló formát, és a hátteret valamint az átlátszóra állítandó területeket állítsuk be fehér színre. A formunk szempontjából fontos a fehér szín megadása (bár ez más szín is lehetne), mivel ez alapján szeretnénk a form adott területeit átlátszóra állítani. A lényeg, hogy olyan színt válasszunk az átlátszóság jelölésére, ami a rajzon semmijen más kitöltendő területen nem szerepel.

Miután elkészítettük a rajzot, indítsuk el a VB-t és hozzunk létre egy üj Standard exe projektet. A létrehozott form tulajdonságait állítsuk be a következő értékekre:
 

BorderStyle  None
BackColor &H00FFFFFF&
Caption (Akármi)
Picture Az elkészített kép.
AutoRedraw True
ShowInTaskbar True
MousePointer Size All
ScaleMode Pixel

Majd ezután adjun egy modult a projekthez és végezzük el a szükséges API függvények és konstansok deklarálását. Azután készítsük el a ShapeForm eljárásunkat a következő paraméterekkel.

  • Adhassuk meg a változtatni kívánt form nevét
  • Adjuk meg annak a színnek a számát, amely az átlátszóságot jelzi.

Az elkészített függvényünk:
 
 

Public Function ShapeForm(bg As Form, transColor)Dim X, Y As Integer CurRgn = CreateRectRgn(0, 0, bg.ScaleWidth, bg.ScaleHeight) While Y <= bg.ScaleHeight   While X <= bg.ScaleWidth     If GetPixel(bg.hdc, X, Y) = transColor Then       TempRgn = CreateRectRgn(X, Y, X + 1, Y + 1)       success = CombineRgn(CurRgn, CurRgn, TempRgn, RGN_DIFF)       DeleteObject (TempRgn)     End If     X = X + 1   Wend   Y = Y + 1   X = 0 Wend success = SetWindowRgn(bg.hWnd, CurRgn, True) DeleteObject (CurRgn) End Function

Első lépésként lekérjük az aktuális ablak teljes területét. Ezután a form teljes területén végigrohanva lekérjük a form hDC-je segítségével az egyes koordináták által meghatározott pixel színét. Ha a kapott szín megegyezik az átlátszóságot jelölő színnel akkor, egy temporary terület felhasználásával kombináljuk a pixel területét és az eredeti területet, oly módon, hogy az eredeti terület pixel által jelölt területét átlátszóra állítjuk. Majd legvégül az így "elkészített" területet hozzárendeljük a formhoz. Ennyi! J

Miután a formunk ekészült, már csak annak mozgatását kell megoldanunk. Ezt úgy csináljuk, hogy a formon bárhol kattintva majd az egeret mozgatva vonszolhassuk a ShapeFormunkat.

Két megoldást ajánlok, de ezek közül csak a második megoldás működik NT és Win9x alatt egyaránt. (Az első csak Win9x alatt.)

A megoldások:
 
 

1.
Private Sub Form_MouseDown(Button As Integer, Shift As Integer,                            X As Single, Y As Single)     call ReleaseCapture   Result& = SendMessage(Me.hWnd, WM_SYSCOMMAND, SC_CLICKMOVE, 0) End Sub
 
 

2.

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim lngReturnValue As Long If Button = 1 Then   Call ReleaseCapture   lngReturnValue = SendMessage(Me.hWnd, WM_NCLBUTTONDOWN,                                HTCAPTION, 0&) End If End Sub

Mindkét megoldás a SendMessage függvényt alkalmazza, csak más paraméterekkel. Az első megoldás egy rendszerszintű üzenetet küld az OP rendszernek, mely a SC_CLICKMOVE paramétert használva egy klikkelés utáni ablak vonszolást tesz lehetővé.

A második módszer egy a form fejlécén történő egérkattintást szimulál, mely hatására a form ugyanúgy mozgatható, mint ha a fejléccel tologatnánk.


ShapeForm alkalmazás futtatás közben.

Mint láthattátok a Windows API függvények igen széles körben alkalmazhatók. Bár ezek tejeskörű szemléltetésére ez a pár példa igen kevésnek bizonyul. Ha kicsit többet szeretnétek megtudni az egyes API függvényekről, akkor ajánlom figyelmetekbe a Visual C++ 6.0 helpjét valamint a MSDN Library internetcímet, ahol a VC++ egyes függvényeiről bővebb információkat kaphattok.

A cikkben szereplô példaprogram forráskódja itt található meg!