Questa è la seconda pagina della rubrica dedicata alla programmazione Visual Basic.

Attendere il caricamento completo...

Vai alla prima pagina



TaskManager2000

Interfaccia del programma TaskManager2000

Le sub sottostanti utilizzano delle API di cui ometto le dichiarazioni, perché facilmente recuperabili attraverso l'utilizzo del visualizzatore API, strumento indispensabile. Se avete dei problemi con l'utilizzo di questo strumento non esitate a scrivere.

Personalmente, sconsiglio vivamente l'utilizzo dell'API Declaration Loader, perché apparentemente risulta comodo in quanto usandolo si evita di scrivere le dichiarazione delle function, dei tipi o delle costanti. Però ha un grosso svantaggio: è che occupa un sacco di risorse inutili, infatti, non fà una selezione delle dichiarazioni utili, le carica indistintamente tutte.

Caricare migliaia di dichiarazioni, quando ne vengono usate solo poche decine è veramente troppo!!!.

Comunque se volete utilizzare questo strumento, selezionatelo dentro "Riferimenti" che trovate nel menu "Progetto" di VB.

Vedi Scheda di Taskmanager2000


TaskManager2000 - 1.622 Kb

"non contiene il source"

Scarica TM2000

Richiede la chiave di registrazione dopo 31 giorni di utilizzo. Puoi ottenerla

dall'autore via
Email, indicando Nome del Programma, versione. Oppure più

facilmente puoi riempire il
modulo di richiesta disponibile online.





Form Trasparenti

Esempio di funzionamento della funzione EffettoVetro

Un esempio di utilizzo di finestre trasparenti lo potete osservare dal programma TaskManager2000, presente nella sezione Download, di questo stesso sito e presente nell'esempio precedente.

Private Sub EffettoVetro(EffettoVetroB As Boolean)
'Attenzione! ecco alcuni suggerimenti per il corretto funzionamento.
'consiglio di impostare ScaleMode su 3 -Pixel direttamente in fase progettuale
Dim Larghezza As Long, Altezza As Long
Dim posControlloLeft, posControlloTop
Dim i As Integer
Dim r As Long
Dim scostamento As Long
Dim InternoForm As Long
Dim diffaltezza As Long
Dim difflarghezza As Long
Larghezza = ScaleX(Width, vbTwips, vbPixels)
Altezza = ScaleY(Height, vbTwips, vbPixels)
'se il bordo del form non è impostato su none c'è una discrepanza
'tra altezza e larghezza effettive con altezza e larghezza del form
difflarghezza = (Larghezza - ScaleWidth) / 2
diffaltezza = Altezza - difflarghezza - ScaleHeight
If EffettoVetroB = False Then
Regione = CreateRectRgn(0, 0, Larghezza, Altezza)
SetWindowRgn hwnd, Regione, True
Exit Sub
End If
Regione = CreateRectRgn(0, 0, 0, 0)
If EffettoVetroB = True Then
InternoForm = CreateRectRgn(0, 0, Larghezza, Altezza)
CombineRgn Regione, InternoForm, InternoForm, RGN_DIFF
End If
' Combina regioni dei controlli nel form
On Local Error Resume Next
'alcuni controlli possono generare errore. Tra questi:
'Gli Shape, Timer, ecc
For i = 0 To Me.Controls.Count - 1
posControlloLeft = ScaleX(Me.Controls(i).Left, Me.ScaleMode, vbPixels) + difflarghezza
posControlloTop = ScaleX(Me.Controls(i).Top, Me.ScaleMode, vbPixels) + diffaltezza
r = CreateRectRgn(posControlloLeft, posControlloTop, posControlloLeft + ScaleX(Me.Controls(i).Width, Me.ScaleMode, vbPixels), posControlloTop + ScaleY(Me.Controls(i).Height, Me.ScaleMode, vbPixels))
CombineRgn Regione, r, Regione, RGN_OR
Next
Err = 0
SetWindowRgn hwnd, Regione, True
End Sub

Come è possibile vedere si ricorre alle seguenti funzioni API:

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CreateEllipticRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
Private Const RGN_OR = 2
Private Const RGN_DIFF = 4
Private Const WM_NCLBUTTONDOWN = &HA1
Private Const HTCAPTION = 2

La funzione EffettoVetro, non fa altro che creare una regione sia per il form che per gli oggetti in esso contenuti e successivamente dispone queste regioni rispettando la disposizione nel form iniziale.

Alcuni Suggerimenti:

Nel caso in cui pensiate di applicare l'effetto in modo permanente nel form consiglio di impostare il bordo dello stesso su "None", cioè assenza di bordo, ed inoltre selezionate nel form lo scalemode = 3 cioè Pixel.

Source di EffettoVetro VB - 66 Kb

EffettoVetro



Icona TrayBar [Orologio di sistema]: posizionamento, modifica, gestione eventi


Completo di source del progetto esemplificativo.

Per prima cosa vediamo le dichiarazioni necessarie per questo compito. Naturalmente si tratta di function API e dichiarazioni di tipi di dati.


Public Type NOTIFYICONDATA
cbsize As Long
hwnd As Long
uid As Long
uflags As Long
ucallbackmessage As Long
hicon As Long
sztip As String * 64
End Type

Questo è il tipo di dati principale, vediamo quali sono le voci prncipali che lo compongono:

hwnd: rappresenta l'handle del form che posiziona questa icona.

hicon: è l'handkle della icona vera e propria.

sztip: rappresenta il messaggio che verrà visualizzato soffermando il puntatore del mouse sopra l'icona.

Questa ultima voce necessita di accorgimenti particolari che vedremo più avanti.

Continuiamo con le dichiarazioni:

Public leo As NOTIFYICONDATA
Public Const NIM_ADD = &H0
Public Const NIM_MODIFY = &H1
Public Const NIM_DELETE = &H2
Public Const WM_MOUSEMOVE = &H200
Public Const NIF_MESSAGE = &H1
Public Const NIF_ICON = &H2
Public Const NIF_TIP = &H4
Public Const WM_LBUTTONDOWN = &H201 'Button down
Public Const WM_LBUTTONUP = &H202 'Button up
Public Const WM_LBUTTONDBLCLK = &H203 'Double-click
Public Const WM_RBUTTONDOWN = &H204 'Button down
Public Const WM_RBUTTONUP = &H205 'Button up
Public Const WM_RBUTTONDBLCLK = &H206 'Double-click
Public Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long

L'oggetto "Leo" rappresenta l'oggetto icona. L'ultima voce è la dichiarazione della function API necessaria.

Le prime costanti (quelle che contengono NIM e NIF per intenderci) sono le costanti per definire le varie operazioni come il posizionamento la modifica e ultima ma non meno importante la cancellazione della icona.

Le seconde costanti serviranno per la gestione degli eventi del mouse, infondo l'icona a qualcosa deve pur servire, non c'è niente di più scocciante di programmi che vanno ad occupare spazio nella tray, solo per puro piacere.

Per posizionare l'icona ci serviremo di una sub:

Public Sub Icona(testo As String, f As Form)
trayicona = True
With leo
.cbsize = Len(leo)
.hwnd = f.hwnd
.uid = vbNull
.uflags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
.ucallbackmessage = WM_MOUSEMOVE
.hicon = f.Icon
.sztip = testo
End With
Shell_NotifyIcon NIM_ADD, leo
End Sub

Come si lancia questa sub?

call Icona(testo,Me)

ad esempio.

Particolare attenzione voglio riservare al testo. Come ho detto prima, la propietà dell'oggetto che si occupa di posizionere il testo è: sztip As String * 64 che è in realta un dato in formato Byte. Se non volete che vi compaiano delle scritte strane, generalmente gli ultimi 3/4 caratteri costituiti da simboli random, è bene "terminare" questa stringa. Per farlo ci sono due metodi:

t=string(chr(0),64)

t= "prova testo"

oppure

t= "prova testo" & chr(0)

Scegliete voi quello che più vi piace, funzionano bene entrambi.

Adesso l'icona c'è come si può modificare il testo?

With leo
.sztip = ""
.sztip = t
End With
Shell_NotifyIcon NIM_MODIFY, leo

Come si può togliere l'icona?

Shell_NotifyIcon NIM_DELETE, leo

E' bene prevedere tutti i modi di arresto del programma, ed in tutti posizionare questo comando. Altrimenti il programma si chiude ma l'icona rimane.


A questo punto manca solo la gestione dell'icona. Abbiamo detto che a qualcosa deve servire.

Dovete introdurre del codice dentro un evento del form e precisamente dentro l'evento che avviene quando passate il mouse sul form (rappresentato dalla icona) e cliccate.

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
DoEvents
Msg = Button
'Debug.Print str(Msg)
Msg = X / Screen.TwipsPerPixelX
Select Case Msg
Case WM_LBUTTONDBLCLK
popupmenu menupop
Case WM_RBUTTONUP
Case WM_RBUTTONDBLCLK
popupmenu menupop
End Select
End Sub

Come vedete al clic del mouse sia tasto destro, che sinistro si apre il menu popup. Naturalmente è necessario crearlo ed associare ad esso tutti i compiti che volete che esegua.

Potete effettuare delle variazioni sul tema, ad esempio far visualizzare il mouse solo al clic del tasto destro, oppure doppio clic, o meglio ancora associare un diverso comportamento ai due eventi.


Ma ecco il source completo di un progetto che vi mostra tutto questo.

Source di IconaTray - 12 Kb

IconaTray



Macro di conversione Numeri in Lettere

Ho creato questo algoritmo per rispondere alla necessità di convertire un numero in cifre nel corrispettivo scritto in lettere.

Ecco l'algoritmo ricorsivo principale:

Public Function NumLettere(n As Double) As String
Dim resto As Double
Dim centinaia As Double
Dim Ordine As Integer
Dim StrN As String
Dim Decina As String
Dim cestr As String
Dim migliaia As String
Dim restomilioni As Double
Dim numfin As Double
Dim restomiliardi As Double
Dim miliardi As String
NumLettere = ""
'modifica apportata il 28/3/00
If n = 0 And fatto = False Then NumLettere = "zero": Exit Function
fatto = True
If n < 20 Then NumLettere = Unità(n): Exit Function
StrN = Trim(Str(n))
Ordine = Len(Trim(Str(n)))
'unità
numfin = CDbl(Right(StrN, 2))
If numfin <= 19 Then
NumLettere = NumLettere(numfin)
Else
NumLettere = NumLettere(CDbl(Right(StrN, 1)))
'decine
StrN = Trim(Str(n - CDbl(Right(StrN, 1))))
Decina = Decine(CDbl(Right(StrN, 2)) / 10)
If (NumLettere = "uno" Or NumLettere = "otto") And Decina <> "" Then Decina = Left(Decina, Len(Decina) - 1)
'If NumLettere = "otto" And Decina <> "" Then Decina = Left(Decina, Len(Decina) - 1)
NumLettere = Decina & NumLettere
End If
centinaia = (CDbl(StrN) - CDbl(Right(StrN, 2))) / 100
If centinaia = 0 Then Exit Function
If centinaia <= 9 Then
If centinaia > 1 Then
cestr = NumLettere(centinaia) & Esp(2)
Else
cestr = Esp(2)
End If
Else
resto = Left(Trim(Str(centinaia)), Len(Trim(Str(centinaia))) - 1)
centinaia = Right(Trim(Str(centinaia)), 1)

'if centinaia =0 then
If centinaia > 1 Then cestr = NumLettere(centinaia) & Esp(2)
If centinaia = 1 Then cestr = Esp(2)
If resto <= 999 And resto > 0 Then
If resto = 1 Then
migliaia = Esp(3)
Else
migliaia = Left(NumLettere(resto) & Esp(3), Len(NumLettere(resto) & Esp(3)) - 2) & "a"
End If
Else
restomilioni = CDbl(Left(Trim(Str(resto)), Len(Trim(Str(resto))) - 3))
If restomilioni = 1 Then
milioni = "un" & Esp(6)
'aggiunta del 28/03
migliaia = NumLettere(CDbl(Right(Trim(Str(resto)), Len(Trim(Str(resto))) - 1))) & "mila"

Else
If restomilioni <= 999 And restomilioni > 0 Then
milioni = NumLettere(restomilioni) & "milioni"
Else
restomiliardi = CDbl(Left(Trim(Str(restomilioni)), Len(Trim(Str(restomilioni))) - 3))
End If
If restomiliardi = 1 Then
miliardi = "un" & Esp(9)
'aggiunta del 28/03/00
restomilioni = CDbl(Right(Trim(Str(restomilioni)), 3))
If restomilioni = 1 Then
milioni = "un" & Esp(6)
Else
If restomilioni <= 999 And restomilioni > 0 Then milioni = NumLettere(restomilioni) & "milioni"
End If
Else
If restomiliardi > 0 Then
miliardi = NumLettere(restomiliardi) & "miliardi"
restomilioni = CDbl(Right(Trim(Str(restomilioni)), 3))
If restomilioni = 1 Then
milioni = "un" & Esp(6)
Else
If restomilioni <= 999 And restomilioni > 0 Then milioni = NumLettere(restomilioni) & "milioni"
End If
End If
End If
' If restomilioni <> 0 Then milioni = Left(NumLettere(restomilioni) & Esp(6), Len(NumLettere(restomilioni) & Esp(6)) - 2) & "a"
'migliaia = NumLettere(CDbl(Right(Trim(Str(resto)), 3))) & Esp(3)
resto = CDbl(Right(Trim(Str(resto)), 3))
If resto <> 0 Then migliaia = Left(NumLettere(resto) & Esp(3), Len(NumLettere(resto) & Esp(3)) - 2) & "a"
End If

End If
End If
'cestr = Esp(((CDbl(StrN) - CDbl(Right(StrN, 2))) / 100) + 1)
'End If
If migliaia = "mila" Then migliaia = ""
NumLettere = miliardi & milioni & migliaia & cestr & NumLettere

End Function

Riporto per intero questo algoritmo per far vedere come sia possibile attraverso un certo schema logico rispondere alle necessità della complessa lingua italiana, certamente non priva di eccezioni.

Fino a che non ho provato a scrivere questa function, non mi ero mai accorto del semplice (solamente in apparenza) compito svolto durante una scrittura di un assegno.

Naturalmente questo algoritmo, come in generale tutti, lo si può scrivere in mille modi diversi e certamente ce ne sarà in giro una versione più efficace.

E' stato volutamente omesso la parte precedente che riporta le dichiarazione necessarie, comunque troverete tutto il necessario nel source disponibile sia in versione VB (un progetto) sia in versione Macro, contenuta in un file di Excel usato come esempio.

Ringrazio alcuni di voi che mi hanno segnalato alcune imperfezioni nel codice della versione iniziale.

EURO CHE PASSIONE: LEGGERE QUESTO ARTICOLO PER LE MODIFICHE DA APPORTARE PER CONVERTIRE ED UTILIZZARE LA MACRO CON L'EURO.

Source di Numeri in Lettere VB - 15 Kb

NumLettere

Source di Numeri in Lettere Excel - 15 Kb

NumLettere

Source di Numeri in Lettere Txt - 7 Kb

NumLettere

Le due versioni sono leggermente diverse. Se avete intenzione di usare il source in un file di Excel consiglio di scaricare la seconda versione.

Fatemi sapere cosa ne pensate scrivendomi una email


Creazione di File di Help stile WinHelp


Ecco la descrizione delle operazioni necessarie alla creazione di un help stile Windows Help file.

Per prima cosa occorre procurarsi il compilatore Microsoft: Help Compiler. Il file HC.exe è spesso disponibile in abbinamento di molti programmi. Il file HC.exe ha nomi diversi, potete trovare lo stesso file anche come Hcw.exe, Hcrtf.exe, ecc.

Il nome completo di questo compilatore è: Ms Help WorkShop.

Ms Help WorkShop si serve di un file RTF per la creazione di Help. Vediamo come deve essere scrito questo file.

Innanzi tutto è necessario aprire un editor RTF ad esempio MS Word. Vediamo proprio le operazioni da compiere con questo editor.

Come prima cosa, una volta aperto, Word è necessario abilitare lo stesso ad accettare testo nascosto: dal menu Strumenti scegliete Opzioni, Visualizza, quindi spuntate la casella Testo nascosto. A questo punto cominciate a digitare il testo contenente l'oggetto della guida.

Iniziate con la pagina Sommario del vostro Help.

Ogni link che create deve "puntare" ad una pagina prestabilita che è contraddistinta da una intestazione a piè di pagina prestabilita.

In questo modo Inserite nella prima pagina questa Intestazione a piè di pagina:

Dal menu, scegliete Inserisci, Note a piè di pagina... cliccate su personalizzata ed inserite questo nome per la nota: #Sommario attenzione al cancelletto.

Vediamo come costruire un qualunque link. Supponiamo di avere un link nel sommario alla pagina modem.

Scrivere in questo modo il link. Marcate con una sottolineatura doppia la frase (o la parola) del salto ipertestuale: Impostare il modem

Attenzione la sottolineatura deve essere doppia in questo modo:

fate seguire alla frase del salto ipertestuale una stringa che rappresenta il nome del salto. NON FATE SEGUIRE SPAZI TRA LA FRASE E IL NOME. Questa etichetta deve essere univoca, e deve essere formattata come testo nascosto ed è chiamata Stringa di Contesto.

Per formattare come testo nascosto dovete selezionarla, andare su carattere e selezionare l'opzione Testo Nascosto

Per completare il link, dobbiamo creare l'oggetto puntato, cioè dove deve andare la visualizzazione appena clicco su link.

Per fare questo inserire una interruzione di pagina con la combinazione di tasti Ctrl+Invio. Inserite in questa pagina la nota a piè di pagina #modem

Attenzione! suggerisco di usare lettere minuscole e parole brevi. E' tassativamente proibito usare parole con spazi o troppo lunghe. Limitate tale lunghezza a 6,7 caratteri.

In questo modo cliccando sulla frase Impostare Il modem verrà mostrato il contenuto della pagina contraddistinta dalla nota vista in precedenza.


Se volete introdurre i link nella casella di testo trova della guida è sufficiente inserire questa nota: #$modem, il carattere $ farà in modo di inserire quel link nella casella Trova.

E' possibile inserire immagini nel file RTF, ma non usate copia incolla, piuttosto selezionate Inserisci e successivamente immagine da file. Questo perchè il compilatore ha bisogno di rintracciare il file contenente la bitmap scelta.

Una volta scritto il file RTF con tutti i link desiderati, è necessario importarlo in MS Help WorkShop.

Avviate il programma, selezionate nuovo file di Help.

Successivamente caricate il file RTF scritto facendo clic su Files... e localizzate il file RTF scritto precedentemente. Adesso dobbiamo Mappare il file di Help, cliccate su Map... Associate ad ogni stringa di contesto un ID numerico univoco. Personalizzate a piacere le opzioni rimanenti su Option.

Unico suggerimento di questo ultimo passo è di dare alla Stringa di contesto Sommario l' ID 0 (zero). In questo modo potete collegare questo file al programma VB cui è destinato. Così facendo per richiamare la guida dal vostro programma è sufficiente premere F1. Attenzione la visualizzazione del file di Help non è assicurata nella fase di Debug, quindi provate a compilare il vostro progetto VB e successivamente provatelo lanciando il file eseguibile.


Questa introduzione alla creazione di un file di Help sarà più chiara osservando il file RTF e il file HPJ (creato da MS HelpWorkShop) che allego, sarà sufficiente scaricare questi file e visualizzarli.

Ricordo per il file RTF serve Word, e per il file HPJ serve MSHWS

Creazione di file help - esempio - 593 Kb esempiohlp.zip

Si tratta del file di Help di TempoInternet2000.


Monitorare una applicazione esterna

Vediamo come è possibile vedere se una applicazione è in esecuzione.

Per fare questo uso una funzione che sfrutta strumenti simili a quelli utilizzati per la creazione di TaskManager2000. In reealta devo estrarre i processi attualmente in esecuzione.

Alcune dichiarazioni API:


Private Const TH32CS_SNAPPROCESS As Long = 2&
Private Const MAX_PATH As Long = 260

Private Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szExeFile As String * MAX_PATH
End Type

Private Declare Sub CloseHandle Lib "Kernel32.dll" (ByVal hPass As Long)
Private Declare Function CreateToolhelpSnapshot Lib "Kernel32.dll" Alias "CreateToolhelp32Snapshot" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
Private Declare Function ProcessFirst Lib "Kernel32.dll" Alias "Process32First" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function ProcessNext Lib "Kernel32.dll" Alias "Process32Next" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long


in questo modo abbiamo definito che cosa è un processo, e le funzioni per recuperare i processi in esecuzione.

La funzione vera è propria è la seguente, come si vede è una funzione booleana che restituisce true se il processo cercato è in esecuzione e false se non lo è.

Private Function ProcessoAttivo(NomeProcesso As String) As Boolean
Dim uProcess As PROCESSENTRY32
Dim continua As Long
Dim Verifica As String
hSnapShot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&)
If hSnapShot = 0 Then Exit Function
uProcess.dwSize = Len(uProcess)
continua = ProcessFirst(hSnapShot, uProcess)
contaprocessi = 1
ProcessoAttivo = False
Do While continua
continua = ProcessNext(hSnapShot, uProcess)
Verifica = uProcess.szExeFile
If Trim(Verifica) <> "" Then
If InStr(1, Right(LCase(Left(Verifica, InStr(1, Verifica, Chr(0)) - 1)), Len(LCase(NomeProcesso))), LCase(NomeProcesso)) <> 0 Then ProcessoAttivo = True: Exit Function
End If
Loop
Call CloseHandle(hSnapShot)
End Function

Analizziamola:

prima di tutto accorre prendere il primo processo in esecuzione (il primo è quello che ha un handle inferiore). La proprietà uProcess.szExeFile è quella che contiene l'etichetta del processo. Tale etichetta è generalmente costituita dal nome dell'eseguibile, ad esempio: Explorer.exe, Winword.exe, ecc.

Poi, utilizzando ProcessNext vado a prendere via via tutti i processi e li confronto con quello cercato.

Osservate bene la parte del codice che serve per confrontare le stringhe:

If Trim(Verifica) <> "" Then
If InStr(1, Right(LCase(Left(Verifica, InStr(1, Verifica, Chr(0)) - 1)), Len(LCase(NomeProcesso))), LCase(NomeProcesso)) <> 0 Then ProcessoAttivo = True: Exit Function
End If

Perché questo controllo piuttosto ad un controllo del tipo Verifica=Nomeprocesso.

Il motivo è spioegato dal diverso comportamento dei SO Microsoft. Ancora una volta vogliono complicarci la vita. Infatti la stessa funzione dentro la stessa Dll ha un comportamento completamente diverso in Win98 piuttosto che in WinNT (o Win2000). Infatti uProcess.szExeFile restituisce il nome del processo in winNT e restituisce il nome del processo con relativo percorso in Win98:

esempio:

Win98

"c:\programmazione\VisualBasic\vb5.exe************"

WinNT/2000

"vb5.exe***********"

dove al posto degli asterischi abbiamo caratteri nulli, cioé Chr(0)

Avrei potuto mettere un vero riconoscimento di SO, cioè se è in esecuzione WinNT fai in un modo se Win98 in un altro, ma perché appesantire il codice?

Se volete approfondire l'argomento scaricate l'esempio seguente, che non è altro l'utilizzo di questa semplice function.

Monitorizza applicazioni - 8 Kb monitorizza.zip



Inviare un file o gruppi di files al cestino

Vediamo quali sono le procedure da seguire per inviare un file o un gruppo di files al cestino.

Sicuramente vi sarà capitato di dover eliminare un file da una vostra applicazione in VB e forse avrete risolto il problema utilizzando il comando Kill. Effettivamente alcune volte si può continuare ad usare quel comando, del resto molto semplice, ad esempio quando dobbiamo eliminare un file creato come scambio di informazioni, oppure un file temporaneo.

Però alcune volte è necessario dare all'utente la possibilità di recuperare questo file, allora viene la necessità di inviarlo al cestino.

Inizio con le dichiarazioni API necessarie:

Public Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Boolean
hNameMappings As Long
lpszProgressTitle As String
End Type
Public Const FOF_ALLOWUNDO As Long = &H40
Public Const FOF_CONFIRMMOUSE As Long = &H2
Public Const FOF_FILESONLY As Long = &H80
Public Const FOF_MULTIDESTFILES As Long = &H1
Public Const FOF_NOCONFIRMATION As Long = &H10
Public Const FOF_NOCONFIRMMKDIR As Long = &H200
Public Const FOF_RENAMEONCOLLISION As Long = &H8
Public Const FOF_SILENT As Long = &H4
Public Const FOF_SIMPLEPROGRESS As Long = &H100
Public Const FOF_WANTMAPPINGHANDLE As Long = &H20
Public Const FO_COPY As Long = &H2
Public Const FO_DELETE As Long = &H3
Public Const FO_MOVE As Long = &H1
Public Const FO_RENAME As Long = &H4
Public Declare Function SHFileOperation Lib "Shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long

quindi realizzate una sub routine InviaCestino nel seguente modo:

Public Sub InviaCestino(nomefile As String)
Dim OperazioneSuFile As SHFILEOPSTRUCT
Dim lReturn As Long
With OperazioneSuFile
.wFunc = FO_DELETE
.pFrom = nomefile
.fFlags = FOF_ALLOWUNDO
End With
lReturn = SHFileOperation(OperazioneSuFile)
End Sub

Come è possibile capire osservando la semplice routine per spedire un file al cestino è sufficiente scrivere:

call InviaCestino(nomefile)

Il nomefile è una stringa che contiene la path completa del file ad esempio: nomefile = "c:\cartella1\file1.ext"

Una volta lanciata la sub il SO effettua la classica domanda:


E se si vuole mandare più file?

Per questa cosa ho dovuto usare un po' di fantasia. Per prima cosa ho provato a costruire un array e a mandarlo alla funzione, ma la dichiarazione API della stessa lasciava poca speranza. Ho provato a modificarla ma niente da fare, fino a quando ho provato a creare una stringa che concatenava più files.

es:

nomefile = file1 & chr(0) & file2 & chr(0) & file3 & chr(0) & file4 & chr(0) ecc.

e sorpresa mi sono visto chiedere: Vuoi mandare gli n oggetti al cestino?

O provato a vedere se c'erano limiti di lunghezza di questa stringa, ma non ci sono riuscito.

Con il programma che vi lascio scaricare genero un numero di files temporanei, contenenti semplice testo, da inviare al cestino. Io ho provato a spedire fino a 1000 oggetti. Il tutto senza problemi.

Veramente niente male.

Scaricate il file sotto e provate a spedire quanti files volete. Attenzione però allo spazio su disco. Per ovvie ragioni ho limitato il numero di files a 10, però nulla vi vieta di intervenire manualmente sul codice per creare un numero un numero molto più grande di files.

Se scoprite il limite fatemelo sapere naturalmente.

Invia al cestino - 12 Kb InviaCestino.zip



Stampare un form o un altro oggetto senza usare printform

Molti di voi si saranno sicuramente scontrati con la necessità di stampare un form o un oggetto in esso contenuto, vi sarete resi conto di come è mal strutturato il printform.

L'esempio che segue è solo un modo per sopperire a questa mancanza.

L'idea è quella di creare una copia Bitmap del form da stampare, copiarla dentro una Picturebox nascosta nel form e mandare in stampa il PictureBox.

Vediamo passo passo il da farsi.

Prima di tutto occorre dichiarare le funzioni API da utilizzare.

Public Declare Function BitBlt Lib "gdi32" (ByVal hDCDest As Long, ByVal XDest As Long, ByVal YDest As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hDCSrc As Long, ByVal XSrc As Long, ByVal YSrc As Long, ByVal dwRop As Long) As Long
Public Declare Function GetDesktopWindow Lib "user32" () As Long
Public Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Public Declare Function ShellExecute Lib "Shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Particolare attenzione alla Funzione BitBlt contenuta nella libreria gdi32.dll.

Nel form che volete stampare create un oggetto PictureBox (qui per semplicità Picture1). E' importante prestare attenzione ad alcune propietà di questo oggetto.

Prima di tutto fatelo di dimensioni opportune, non sopporta essere dimensionato in fase di esecuzione, quindi esagerate pure nella grandezza (meglio abbondare!), meglio se fissate in fase di progetto lo ScaleMode = Pixel [3], quindi posizionatelo in una zona non interna all'area da stampare, quindi non visibile. Impostate però la proprietà visible = true.

Inoltre impostate lo ScaleMode del form su vbTwips [1], questo lo potete fare anche a runtime inserendo nel sub del form_load:

Private Sub Form_Load()
Me.ScaleMode = 1
End Sub



A questo punto se volete stampare l'intero form (naturalmente la parte visibile) procedete come di seguito:

Private Sub Command1_Click()

Dim e As Long
Dim hWndForm As Long
Dim hDCForm As Long
Dim LeftForm As Long
Dim TopForm As Long
Dim WidthForm As Long
Dim HeightForm As Long
LeftForm = 0
TopForm = 0
WidthForm = picture1.ScaleX(Form1.Width, vbTwips, vbPixels)
HeightForm = picture1.ScaleY(Form1.Height, vbTwips, vbPixels)
hWndForm = Form1.hwnd
hDCForm = GetWindowDC(hWndForm)
e = BitBlt(picture1.hdc, 0, 0, WidthForm, HeightForm, hDCForm, LeftForm, TopForm, vbSrcCopy)
picture1.Picture = picture1.Image
Dim posizionex As Long
Dim posizioney As Long
Printer.ScaleMode = PIXEL
posizionex = (Printer.ScaleX(Printer.Width, vbTwips, vbPixels) - Printer.ScaleX(Form1.Width, vbTwips, vbPixels)) / 2
posizioney = (Printer.ScaleY(Printer.Height, vbTwips, vbPixels) - Printer.ScaleY(Form1.Height, vbTwips, vbPixels)) / 2
Printer.PaintPicture picture1.Picture, posizionex, posizioney
Printer.EndDoc

end sub


Nella prima parte usate la funzione BitBlt per creare una copia Bitmap del form nel picture1, successivamente trasferisco il suo contenuto alla stampante:

Printer.PaintPicture picture1.Picture, posizionex, posizioney

Attenzione! non trascurate picture1.Picture = picture1.Image altrimenti tutti gli sforzi saranno vanificati.

Ultima cosa centrate la stampa nel foglio:

posizionex = (Printer.ScaleX(Printer.Width, vbTwips, vbPixels) - Printer.ScaleX(Form1.Width, vbTwips, vbPixels)) / 2
posizioney = (Printer.ScaleY(Printer.Height, vbTwips, vbPixels) - Printer.ScaleY(Form1.Height, vbTwips, vbPixels)) / 2


Se volete stampare un qualunque oggetto che appartiene al form, senza stampare tutto il form, passate l'handle dell' oggetto desiderato

Ad esempio un per un frame dal nome Frame1

WidthForm = picture1.ScaleX(frame.Width, vbTwips, vbPixels)
HeightForm = picture1.ScaleY(frame1.Height, vbTwips, vbPixels)
hWndForm = Frame1.hwnd

Ma anche ad esempio un oggetto MsChart dal nome mschart1

WidthForm = picture1.ScaleX(mschart1.Width, vbTwips, vbPixels)
HeightForm = picture1.ScaleY(mschart1.Height, vbTwips, vbPixels)
hWndForm = mschart1.hwnd

Finalmente risolta una questione spinosa con la stampante.

Attenzione!: in caso di problemi con l'oggetto MSChart leggere il file leggimi.txt contenuto nel file compresso.

 

Stampare oggetti - 38 Kb stampareform.zip


Gestire al meglio la posizione di un form; posizione e dimensioni della barra delle applicazioni

 

Forse a qualcuno di voi sarà capitato di dover disporre un form in una posizione precisa dello schermo, ecco come fare a determinare la dimensione della barra delle applicazioni, quella che contiene la traybar (orologio ed icone) e quella che contiene il tasto start. Infatti, è facilmente possibile reperire le informazioni delle dimensioni dello schermo attraverso:

Larghezza=Screen.Width         altezza= Screen.Height

Però se posizionate una finestra impostando il top, cioè il punto più alto a:

Form1.Top = screen.height - form1.height

succede che parte della vostra finestra rimarrà coperta dalla barra delle applicazioni, quindi occorre ricavare l'altezza della barra di windows. Per fare ciò ricorriamo, oramai è una abitudine, ad alcune comode e semplici API, in particolare: SHAppBarMessage

Attraverso questa comoda funzione è possibile ottenere alcune informazioni sulla barra, dalla posizione alla altezza.

Spesso però occorre gestire la posizione di un form in maniera completa, allora ho pensato bene di rendere pubblico, un piccolo esempio che mostra come riprodurre un piccolo monitor nel quale gestire la posizione di una data finestra, ecco il risultato finale:

Con questo piccolo esempio potete far gestire alla grande la posizione di una finestra ad un vostro utente. 

Tra poco, attualmente è in fase di sviluppo, uscirà un mio controllo che potrete integrare nei vostri progetti, che memorizzerà la posizione di una finestra, in modo da riposizionarla al riavvio successivo.

Scaricate il progetto di esempio, nel quale sono riportati tutte le dichiarazioni API utilizzate. 

Naturalmente fatemi sapere cosa ne pensate.

 

Disponi finestra - 58 Kb posizione.zip

INSERISCI NEI PREFERITI - http://www.visualbasic.subito.cc - INSERISCI NEI PREFERITI

Vai alla terza pagina della rubrica dedicata alla programmazione Visual Basic