Collegamento alle chiamate di sistema (API) di windows
Non è previsto in Visual BASIC, per esempio, la possibilità di ricevere messaggi relativi al funzionamento del mouse al di fuori della finestra dellapplicazione. In questi casi è possibile chiamare direttamente le API, cattura.vbp permette allutente di posizionare il mouse al di fuori della finestra, creare un rettangolo che contenga larea da catturare. Una volta rilasciato il mouse, il rettangolo apparirà nella finestra; da qui, potrà essere trasferito su disco o negli Appunti. Quanto illustrato richiede lo svolgimento di tre funzioni che non possono essere utilizzate in Visual BASIC:
ricevere linput del mouse quando si trova al di fuori della finestra;
disegnare un rettangolo al di fuori della finestra;
copiare limmagine bitmap da una qualsiasi area dello schermo nella form.
Per utilizzare una chiamata di sistema è necessario indicare a Visual BASIC in quale .DLL si trova, sono tre le principali: User, GDI e Kernel.
Type ApiPoint
X As Integer
Y As Integer
End Type
Libreria User, cattura tutti gli eventi relativi al mouse.
Declare Function SetCapture Lib "User" (ByVal hWnd As Integer) As Integer
Libreria User, rilascia il mouse.
Declare Sub ReleaseCapture Lib "User" ()
Libreria GDI, crea un device context.
Declare Function CreateDC Lib "GDI" (ByVal lpDriverName As String, ByVal
lpDeviceName As Any,ByVal lpOutPut As Any,ByVal lpInitData As Any) As Integer
Libreria User, converte le coordinate a cui punta lpPoint in modo che facciano riferimento allo schermo e non allarea utile.
Declare Sub ClientToScreen Lib "User" (ByVal hWnd As Integer, lpPoint As ApiPoint)
Libreria GDI, imposta la posizione grafica corrente.
Declare Function MoveTo Lib "GDI" (ByVal hDC As Integer, ByVal X As Integer, ByVal Y
As Integer) As Long
Libreria GDI, traccia una linea dalla posizione grafica corrente.
Declare Function LineTo Lib "GDI" (ByVal hDC As Integer, ByVal X As Integer, ByVal Y
As Integer) As Integer
Libreria GDI, cancella il device context
Declare Function DeleteDC Lib "GDI" (ByVal hDC As Integer) As Integer
Declare Function SetROP2 Lib "GDI" (ByVal hDC As Integer, ByVal nDrawMode As
Integer) As Integer
Declare Function BitBlt Lib "GDI" (ByVal hDestDC As Integer, ByVal X As Integer, ByVal
Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC
As Integer, ByVal XSrc As Integer, ByVal YSrc As Integer, ByVal dwROP As Long)
As Integer
ByVal indica il passaggio degli argomenti come valore.
Queste sono le variabili a livello form1 nella parte declarations delloggetto general.
Dim Anchor As ApiPoint vertice in alto a sinistra del rettangolo
Dim Current As ApiPoint vertice in basso a destra del rettangolo
Dim OldCurrent As ApiPoint
Dim CapFlag As Integer indica se la cattura è in corso
Per il riconoscimento degli eventi relativi al mouse al di fuori della finestra si utilizza la funzione API SetCapture (), che richiede come argomento hWnd, lo handle della finestra principale dellapplicazione. Visual BASIC consente di utilizzare gli handle come proprietà.
Sub Form_Load ()
Dummy% = SetCapture(hWnd)
CapFlag = 0
End Sub
Sub Form_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single)
Anchor.X = X:Anchor.Y = Y
ClientToScreen hWnd, Anchor
OldCurrent.X = Anchor.X:OldCurrent.Y = Anchor.Y
CapFlag = -1 'True
End Sub
A questo punto, si ha il controllo del puntatore del mouse; bisogna ora impostare il codice per attivare il disegno del rettangolo in qualunque parte dello schermo.
Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim hDCScreen As Integer
If CapFlag Then
Current.X = X:Current.Y = Y
hDCScreen = CreateDC("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
ClientToScreen hWnd, Current
Dummy% = SetROP2(hDCScreen, 6)
Dummy2& = MoveTo(hDCScreen, Anchor.X, Anchor.Y)
Dummy% = LineTo(hDCScreen, OldCurrent.X, Anchor.Y)
Dummy% = LineTo(hDCScreen, OldCurrent.X, OldCurrent.Y)
Dummy% = LineTo(hDCScreen, Anchor.X, OldCurrent.Y)
Dummy% = LineTo(hDCScreen, Anchor.X, Anchor.Y)
OldCurrent.X = Current.X:OldCurrent.Y = Current.Y
Dummy2& = MoveTo(hDCScreen, Anchor.X, Anchor.Y)
Dummy% = LineTo(hDCScreen, Current.X, Anchor.Y)
Dummy% = LineTo(hDCScreen, Current.X, Current.Y)
Dummy% = LineTo(hDCScreen, Anchor.X, Current.Y)
Dummy% = LineTo(hDCScreen, Anchor.X, Anchor.Y)
Dummy% = DeleteDC(hDCScreen)
End If
End Sub
DeleteDC () disattiva il device context dello schermo, se si continuano ad allocare nuovi handle di device context Windows resterà privo di spazio.
Ora si può scrivere il codice per catturare limmagine quando lutente rilascia il mouse.
Sub Form_MouseUp (Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim hDCScreen As Integer
If CapFlag Then se è true cattura limmagine
ReleaseCapture:CapFlag = 0:Current.X = X:Current.Y = Y
ClientToScreen hWnd, Current
hDCScreen = CreateDC("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
cancella il rettangolo rimasto sullo schermo
Dummy% = SetROP2(hDCScreen, 6)
Dummy2& = MoveTo(hDCScreen, Anchor.X, Anchor.Y)
Dummy% = LineTo(hDCScreen, OldCurrent.X, Anchor.Y)
Dummy% = LineTo(hDCScreen, OldCurrent.X, OldCurrent.Y)
Dummy% = LineTo(hDCScreen, Anchor.X, OldCurrent.Y)
Dummy% = LineTo(hDCScreen, Anchor.X, Anchor.Y)
copia limmagine dello schermo nella form
MapWidth% = Abs(Anchor.X - Current.X) larghezza della bitmap
MapHeight% = Abs(Anchor.Y - Current.Y) altezza della bitmap
If Anchor.X < Current.X Then:UpperLeftX% = Anchor.X
Else:UpperLeftX% = Current.X
End If
If Anchor.Y < Current.Y Then:UpperLeftY% = Anchor.Y
Else:UpperLeftY% = Current.Y
End If
Dummy%=BitBlt(hDC,0,0,MapWidth%,MapHeight%,hDCScreen,
UpperLeftX%,UpperLeftY%, &HCC0020)
Dummy% = DeleteDC(hDCScreen)
End If
End Sub
Collegamento di visual BASIC al C
Visual BASIC effettua collegamenti a codice esterno tramite il formato .DLL.
Il codice in C è salvato non come .EXE, ma come .DLL.
O/P/Project Type: DLL
O/P/C/Category/Memory Model: Large
O/P/C/Category/Windows Prolog/Epilog: Protected Mode DLL
O/P/L/Category/Input/Distinguish Letter Case non selezionarlo
#include <windows.h>
int _far _pascal LibMain (HANDLE hModule, WORD wDataSeg, WORD cbHeapsize, LPSTR lpszCmdLine)
{ return TRUE; }
int _far _pascal _export CInterface (int arg1)
{ return (arg1+1); }
void _far _pascal _export MyTest (LPSTR lpMessaggio)
{ MessageBox (NULL, lpMessaggio,"Test",NULL);}
Il file di definizione è il seguente.
LIBRARY CUSER
EXETYPE WINDOWS
PROTMODE
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
SEGMENTS 'WEP_TEXT' FIXED PRELOAD
HEAPSIZE 1024
EXPORTS
WEP @1 RESIDENTNAME
CInterface @2
MyTest @3
Se la libreria comprende più funzioni queste devono essere elencate sotto la Cinterface.
Il progeto in Visual BASIC è vbcuser.vbp. Prima di effettuare altre operazioni, si devono dichiarare le funzioni di cuser.dll in general nella form.
Declare Function CInterface Lib "\windows\system\cuser.dll" (ByVal x As Integer) As Integer
Declare Sub MyTest Lib "\windows\system\cuser.dll" (ByVal msg As String)
Quindi, si dichiari la variabile x.
Dim x As Integer
La sinizializzi ad uno e la si visualizzi nella Textbox e nel contatore.
Sub Form_Load ()
Print " Fare clic sul pulsante per chiamare la function C "
Print " ed incrementare il valore visualizzato"
Print " Fare clic sulla form per visualizzare il messaggio!"
x = 1
Text1.Text = Str$(x)
End Sub
Ora, quando lutente fa clic su Command1, si può chiamare Cinterface e clic nella form si chiama MyTest.
Sub Command1_Click ()
x = CInterface(x)
Text1.Text = Str$(x)
Gauge1.Value = x
End Sub
La variabile x è visualizzata anche da un contatore, GAUGE.VBX, limpostazione è immagazzinata nella proprietà VALUE, il cui valore è compreso tra zero e cento, lo si imposti a dieci. È possibile utilizzare con PICTURE una serie di bitmap come sfondi.
È possibile realizzare un controllo che risponda a proprie specifiche esigenze: quindi si potrà inserirlo nella Toolbox. Si realizzerà un controllo che consiste in un rettangolo, lo si chiamerà controllo box. Si può definire una proprietà, BoxColor e due eventi: ClickInside e ClickOutside.
Inizializzazione e registrazione di un controllo: init.c
La prima fase nellimpostazione di un controllo consiste nel registrarne le proprietà e gli eventi con Visual BASIC utilizzando VBRegisterMode().
Si possono inserire le informazioni relative alla proprietà BoxColor in una struttura PROPINFO, come la seguente:
typedef struct tagPROPINFO
í PSTR npszName; /*nome della proprietà*/
FLONG fl; /*flag PF_*/
BYTE offsetData; /*offset nella struttura*/
BYTE infoData; /*0 o valore di _INFO*/
LONG dataDefault; /*0 o valore di _INFO*/
PSTR npszEnumlist; /*NULL o un pointer near ai valori delle proprietà*/
BYTE enumMax; /*Il massimo valore ammesso*/
ý PROPINFO
Il secondo campo, fl, contiene i flag che istruiscono Visual BASIC sul funzionamento della proprietà. Tali flag sono:
DT_HSZ (stringa), DT_SHORT, DT_LONG, DT_BOOL, DT_COLOR, DT_ENUM, DT_REAL, DT_XPOS, DT_XSIZE, DT_YPOS, DT-YSIZE, DT_PICTURE;
PF_fPropArray, PF_fSetData imposta i dati nella struttura indicata dal programmatore;
PF_fSetMsg, PF_fNoShow, PF_fNoRuntimeW, PF_fGetData, PF_fGetMsg, PF_fSetCheck, PF_fSaveData, PF_fSaveMsg, PF_fGetHszMsg, PF_fUpadateOnEdit, PF_fEditable, PF_fPreHwnd, PF_fDevVal, PF_fNoIntDef.
Si può inoltre notare che Visual BASIC comunica tramite una serie di messaggi il cui prefisso è VBM_, mentre lambiente Windows comunica con VM_
Per tenere traccia delle proprietà del controllo casella si imposterà una struttura BOX:
typedef struct tagPROPINFO
í RECT rectDrawRegion;
SHORT BocColor;
ý BOX;
Si stanno qui immagazzinando sia le dimensioni della casella che il valore corrente di BoxColor nel controllo. Il tipo RECT è il seguente:
typedef struct tagRECT
í int left;
int top;
int right;
int bottom;
ý RECT;
Visual BASIC fornisce una serie di puntatori alle strutture PROPINFO:
Name PROPINFO_STD_NAME
Index PROPINFO_STD_INDEX
BackColor PROPINFO_STD_BACKCOLOR
ForeColor PROPINFO_STD_FORECOLOR
Left PROPINFO_STD_LEFT
Top PROPINFO_STD_TOP
Width PROPINFO_STD_WIDTH
Height PROPINFO_STD_HEIGHT
Enabled PROPINFO_STD_ENABLED
Visible PROPINFO_STD_VISIBLE
MousePointer PROPINFO_STD_MOUSEPOINTER
Caption PROPINFO_STD_CAPTION
FontName PROPINFO_STD_FONTNAME
FontBold PROPINFO_STD_FONTBOLD
FontItalic PROPINFO_STD_FONTITALIC
FontStrike PROPINFO_STD_FONTSTRIKE
FontUnder PROPINFO_STD_FONTUNDER
FontSize PROPINFO_STD_FONTSIZE
TabIndex PROPINFO_STD_TABINDEX
Parent PROPINFO_STD_PARENT
DragMode PROPINFO_STD_DRAGMODE
DragIcon PROPINFO_STD_DRAGICON
BorderStyleOff PROPINFO_STD_BORDERSTYLEOFF
TabStop PROPINFO_STD_TABSTOP
Tag PROPINFO_STD_TAG
Text PROPINFO_STD_TEXT
BorderStyleOn PROPINFO_STD_BORDERSTYLEON
Si possono utilizzare risparmiando lavoro di programmazione.
#include <windows.h>
#include "c:\vb\cdk\vbapi.h" /*contiene i prototipi delle funzioni VB*/
#include "c:\msvc\output\box.h"
Per creare lelenco di queste proprietà, poi passarle a Visual BASIC in VBRegisterMode(), bisogna impostare una matrice di puntatori.
PROPINFO Property_BoxColor =
{ "BoxColor",
DT_SHORT | PF_fGetData | PF_fSetMsg | PF_fSaveData,
(USHORT)&(((BOX *)0)->BoxColor), 0, /* ottiene l'offset */
0,
NULL, 0
};
PPROPINFO Box_Properties[] =
{ PPROPINFO_STD_CTLNAME,
PPROPINFO_STD_INDEX,
PPROPINFO_STD_BACKCOLOR,
PPROPINFO_STD_LEFT,
PPROPINFO_STD_TOP,
PPROPINFO_STD_WIDTH,
PPROPINFO_STD_HEIGHT,
PPROPINFO_STD_VISIBLE,
PPROPINFO_STD_PARENT,
PPROPINFO_STD_DRAGMODE,
PPROPINFO_STD_DRAGICON,
PPROPINFO_STD_TAG,
&Property_BoxColor,
PPROPINFO_STD_HWND, /*VB2*/
NULL
};
A questo punto è stata sviluppata interamente la gestione delle proprietà. La fase successiva consiste nella registrazione degli eventi, è necessario creare una matrice di strutture EVENTINFO, ciascuna delle quali è definita in vbapi.h:
typedef struct tagEVENTINFO
í PSTR npszName; /*nome della procedura dellevento*/
USHORT cParms; /*numero di parametri da pasare*/
USHORT cwParms; /*numero di parole dei parametri*/
PWORD npParmTypes; /*elenco dei parametri per tipo*/
PSTR npszParmProf; /*stringa di profilo dei parametri*/
LONG fl; /*flag EF_*/
ý PROPINFO
In ClickInside si possono passare le coordinate x e y, a questo scopo bisogna indicare il tipo di argomenti da passare alla procedura dellevento,i relativi numeri e i nomi nella struttura EVENTINFO. Visual BASIC possiede queste costanti:
ET_I2 variabile scalare o matrice signed integer a 16 bit
ET_I4 variabile scalare o matrice signed integer a 32 bit
ET_R4 variabile scalare o matrice real a 32 bit
ET_R8 variabile scalare o matrice real a 64 bit
ET_CY variabile scalare o matrice currency a 64 bit
ET_SD variabile scalare o matrice stringa
ET_FS variabile stringa a lunghezza fissa
WORD Paramtypes_ClickInside[] = {ET_R4, ET_R4};
Per esempio, levento ClickOutside non richiede il passaggio di parametri, il che è indicato inserendo 0 o NULL nella struttura.
EVENTINFO Event_ClickOutside =
{ "ClickOutside",
0,
0,
NULL,
NULL
};
EVENTINFO Event_ClickInside =
{ "ClickInside",
2,
4,
Paramtypes_ClickInside,
"X As Single,Y As Single"
};
Ci sono vari eventi predefiniti e sono:
Click PEVENTINFO_STD_CLICK
DblClick PEVENTINFO_STD_DBLCLICK
DragDrop PEVENTINFO_STD_DRAGDROP
DragOver PEVENTINFO_STD_DRAGOVER
GetFocus PEVENTINFO_STD_GETFOCUS
KeyDown PEVENTINFO_STD_KEYDOWN
KeyPress PEVENTINFO_STD_KEYPRESS
KeyUp PEVENTINFO_STD_KEYUP
LostFocus PEVENTINFO_STD_LOSTFOCUS
MouseDown PEVENTINFO_STD_MOUSEDOWN
MouseMove PEVENTINFO_STD_MOUSEMOVE
MouseUp PEVENTINFO_STD_MOUSEUP
PEVENTINFO Box_Events[] =
{ &Event_ClickInside,
&Event_ClickOutside,
PEVENTINFO_STD_DRAGDROP,
PEVENTINFO_STD_DRAGOVER,
NULL
};
Lultima fase consiste nellinserire i puntatori a tali matrici in una struttura MODEL e passarli a VBRegisterMode()
typedef struct tagMODEL
í USHORT usVersion; /*versione VB usata dal controllo*/
FLONG fl; /*struttura bitfield*/
PCTLPROC pctlproc; /*procedura del controllo*/
FSHORT fsClassStyle; /*classe di stile della finestra*/
FLONG flWndStyle; /*stile di default della finestra*/
USHORT cbCtlExtra; /*byte allocati per la struttura HCTL*/
USHORT idBmpPalette; /*id del bitmap*/
PSTR npszdefCtlname /*prefisso del nome del controllo*/
PSTR npszClassname /*nome della classe di Visual BASIC*/
PSTR npszParentClassname
NPPROPLIST npproplist /*lista delle caratteristiche*/
NPEVENTLIST npeventlist /*lista degli eventi*/
BYTE nDefProp /*indice della caratteristica di default*/
BYTE nDefEvent /*indice dellevento di default*/
BYTE nDefValue /*indice del valore del controllo di default*/
ý MODEL
MODEL modelBox =
{ VB_VERSION, /*versione del Visual BASIC*/
0, /*nessun parametro addizionale*/
(PCTLPROC)BoxCtlProc, /*procedura di evento del controllo*/
CS_VREDRAW | CS_HREDRAW,
0L, /*se si vuole il bordo si usa WS_BORDER*/
sizeof(BOX), /*dimensioni*/
IDBMP_BOX, /*id del bitmap per la toolbox*/
"Box", /*prefisso del nome del controllo*/
"BoxClass", /*nome della classe del controllo*/
NULL,
Box_Properties, /*puntatore alle proprietà*/
Box_Events, /*puntatore agli eventi*/
IPROP_BOX_COLOR, /*proprietà di default*/
IEVENT_BOX_CLICKINSIDE, /*evento di default*/
IPROP_BOX_COLOR /*proprietà che rappresenta il valore del controllo*/
};
HANDLE hmodDLL;
int _far _pascal LibMain (HANDLE hModule, WORD wDataSeg, WORD cbHeapsize, LPSTR lpszCmdLine)
{ wDataSeg = wDataSeg;
cbHeapSize = cbHeapSize;
lpszCmdLine = lpszCmdLine;
hmodDLL = hModule;
return 1;
}
BOOL _far _pascal _export VBINITCC (USHORT usVersion, BOOL fRuntime)
{ fRuntime = fRuntime;
usVersion = usVersion;
return VBRegisterModel(hmodDLL, &modelBox);
}
A questo punto si è completata la registrazione del controllo. Per rendere attivi tali eventi e proprietà, Visual BASIC invia dei messaggi alla funzione BoxCtlProc().
Realizzazione del bitmap del controllo
È necessario realizzare quattro bitmap per la toolbox, corrispondenti ai vari monitor; come base di partenza si può usare c:\vb\cdk\pix\pixcd.bmp.
Dopo aver creato questi file, si possono assegnare alle risorse corrispondenti dei numeri arbitrari in box.h
#define IDBMP_BOX 5000 /*boxcu.bmp*/
#define IDBMP_BOXDOWN 5001 /*boxcd.bmp*/
#define IDBMP_BOXMONO 5003 /*boxmu.bmp*/
#define IDBMP_BOXEGA 5006 /*boxeu.bmp*/
long _far _pascal _export BoxCtlProc(HCTL, HWND, USHORT, USHORT, LONG);
typedef struct tagBOX
{ RECT rectDrawRegion;
SHORT BoxColor;
} BOX;
typedef BOX FAR * PBOX;
#ifndef RC_INVOKED
#define IPROP_BOX_CTLNAME 0
#define IPROP_BOX_INDEX 1
#define IPROP_BOX_BACKCOLOR 2
#define IPROP_BOX_LEFT 3
#define IPROP_BOX_TOP 4
#define IPROP_BOX_WIDTH 5
#define IPROP_BOX_HEIGHT 6
#define IPROP_BOX_VISIBLE 7
#define IPROP_BOX_PARENT 8
#define IPROP_BOX_DRAGMODE 9
#define IPROP_BOX_DRAGICON 10
#define IPROP_BOX_TAG 11
#define IPROP_BOX_COLOR 12
#define IPROP_BOX_HWND 13 //VB2
#define IEVENT_BOX_CLICKINSIDE 0
#define IEVENT_BOX_CLICKOUTSIDE 1
#define IEVENT_BOX_DRAGDROP 2
#define IEVENT_BOX_DRAGOVER 3
#endif
È quindi necessario associare queste ID di risorsa ai file bitmap, operazione che è svolta in box.rc nel modo seguente
#include "box.h"
IDBMP_BOX BITMAP DISCARDABLE "boxcu.bmp"
IDBMP_BOXDOWN BITMAP DISCARDABLE "boxcd.bmp"
IDBMP_BOXMONO BITMAP DISCARDABLE "boxmu.bmp"
IDBMP_BOXEGA BITMAP DISCARDABLE "boxeu.bmp"
Procedura di controllo del box
#include <windows.h>
#include "vbapi.h"
#include "box.h"
void near PaintBox(PBOX pbox, HWND hwnd, HDC hdc);
BOOL near InBox(PBOX pbox, SHORT x, SHORT y);
void near FireClickInside(HCTL hctl, SHORT x, SHORT y);
void near FireClickOutside(HCTL hctl);
long far pascal _export BoxCtlProc (HCTL hctl, HWND hwnd, USHORT msg, USHORT wp,LONG lp)
Si passa hctl alle funzioni API di Visual BASIC e hwnd alle funzioni API di Windows
{ PBOX pbox;
LPRECT prect;
pbox = (PBOX)VBDerefControl(hctl);
/*va eliminato il riferimento a hctl quando si invalida pbox anche dopo le chiamate a VB*/
switch (msg){
case WM_CREATE: pbox->BoxColor = FALSE;break;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
if (InBox(pbox, LOWORD(lp), HIWORD(lp))){
FireClickInside(hctl, LOWORD(lp), HIWORD(lp));
} else FireClickOutside(hctl);break;
case WM_PAINT: /*ridisegna il controllo*/
if (wp) PaintBox(pbox, hwnd, (HDC)wp);
else { PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
PaintBox(pbox, hwnd, ps.hdc);
EndPaint(hwnd, &ps);
} break;
case WM_SIZE: /*il controllo è stato ridimensionato*/
prect = &pbox->rectDrawRegion;
GetClientRect(hwnd, prect); /*disegna la casella nel box*/
prect->left = prect->right / 4;
prect->right = 3 * prect->right / 4;
prect->top = prect->bottom / 4;
prect->bottom = 3 * prect->bottom / 4;break;
case VBM_SETPROPERTY: /*BoxColor è stata impostata*/
switch (wp){
case IPROP_BOX_COLOR:
pbox->BoxColor = (SHORT)lp;
InvalidateRect(hwnd, NULL, TRUE);
return 0; } break; }
return VBDefControlProc(hctl, hwnd, msg, wp, lp);
}
void near PaintBox (PBOX pbox, HWND hwnd, HDC hdc)
{ HBRUSH hbr;
HBRUSH hbrOld = NULL;
LPRECT prect = &pbox->rectDrawRegion;
hwnd = hwnd;
if(pbox->BoxColor){
hbr = CreateSolidBrush(RGB(0, 0, 255)); /*brush blu*/
hbrOld = SelectObject(hdc, hbr);}
Rectangle(hdc, prect->left, prect->top, prect->right, prect->bottom);
if(pbox->BoxColor){
SelectObject(hdc, hbrOld); /*ripristina il brush precedente*/
}
}
BOOL near InBox(PBOX pbox, SHORT x, SHORT y)
{ LPRECT prect = &pbox->rectDrawRegion;
return ((prect->left < x) & (prect->right > x) & \
(prect->top < y) & (prect->bottom > y));
}
void near FireClickOutside(HCTL hctl)
{VBFireEvent(hctl, IEVENT_BOX_CLICKOUTSIDE, NULL);}
typedef struct tagCLICKINSIDEPARMS
{ float far *Y;
float far *X;
LPVOID Index;
} CLICKINSIDEPARMS;
void near FireClickInside(HCTL hctl, SHORT x, SHORT y)
{ CLICKINSIDEPARMS EventParams;
float VisBasX, VisBasY;
VisBasX = (float)VBXPixelsToTwips(x);
VisBasY = (float)VBYPixelsToTwips(y);
EventParams.X = &VisBasX;
EventParams.Y = &VisBasY;
VBFireEvent(hctl, IEVENT_BOX_CLICKINSIDE, &EventParams);
}
Box.def indica al linker ciò che si vuole creare
LIBRARY BOX
EXETYPE WINDOWS
DESCRIPTION 'Visual BASIC Box Custom Control'
CODE MOVEABLE
DATA MOVEABLE SINGLE
HEAPSIZE 2048
EXPORTS
WEP @1 RESIDENTNAME
SEGMENTS
WEP_TEXT FIXED
Uso del nuovo controllo personalizzato
Non resta che utilizzare box.vbx allinterno di box.mak, si può emettere un segnale acustico se lutente fa clic al di fuori della casella (ma allinterno del controllo) e se ne possono emettere due se fa clic allinterno della casella.
Sub Box1_ClickInside (X As Single, Y As Single)
Beep
Beep
End Sub
Sub Box1_ClickOutside ()
Beep
End Sub