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 dell’applicazione. In questi casi è possibile chiamare direttamente le API, cattura.vbp permette all’utente di posizionare il mouse al di fuori della finestra, creare un rettangolo che contenga l’area 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 l’input del mouse quando si trova al di fuori della finestra;

disegnare un rettangolo al di fuori della finestra;

copiare l’immagine 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 all’area 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 dell’oggetto 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 dell’applicazione. 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 l’immagine quando l’utente 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 l’immagine

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 l’immagine 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 s’inizializzi ad uno e la si visualizzi nella Textbox e nel contatore.

 

Sub Form_Load ()

Print

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 l’utente 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

 

Contatori

La variabile x è visualizzata anche da un contatore, GAUGE.VBX, l’impostazione è 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.

 


 

Controlli personalizzati

È 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 nell’impostazione 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 l’ambiente 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 l’elenco 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 dell’evento*/

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 dell’evento,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, l’evento 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

};

L’ultima fase consiste nell’inserire 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 dell’evento 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 all’interno di box.mak, si può emettere un segnale acustico se l’utente fa clic al di fuori della casella (ma all’interno del controllo) e se ne possono emettere due se fa clic all’interno della casella.

 

Sub Box1_ClickInside (X As Single, Y As Single)

Beep

Beep

End Sub

Sub Box1_ClickOutside ()

Beep

End Sub