Beruflich Dokumente
Kultur Dokumente
Funciones y ejemplos:
'Copiar:
If SendMessage(Screen.ActiveForm.ActiveControl.hWnd,
WM_COPY, 0, ByVal 0&) Then
End If
'Cortar:
If SendMessage(Screen.ActiveForm.ActiveControl.hWnd,
WM_CUT, 0, ByVal 0&) Then
End If
'Borrar:
If SendMessage(Screen.ActiveForm.ActiveControl.hWnd,
WM_CLEAR, 0, ByVal 0&) Then
End If
'Pegar:
If SendMessage(Screen.ActiveForm.ActiveControl.hWnd,
WM_PASTE, 0, ByVal 0&) Then
End If
'Seleccionar Todo:
If SendMessage(Screen.ActiveForm.ActiveControl.hWnd,
EM_SETSEL, 0, ByVal &HFFFF0000) Then
End If
4.bits)
Sleep 0&
End If
On Local Error Resume Next
buf = Space$(300)
buflen = Len(buf)
'Buscar la entrada especificada y devolver el valor
asignado
If RegQueryValue(hKey, Entry, buf, buflen) = 0 Then
If buflen > 1 Then
'El formato devuelto es ASCIIZ, as que
quitar el ltimo caracter
QueryRegBase = Left$(buf, buflen - 1)
Else
QueryRegBase = ""
End If
Else
QueryRegBase = ""
End If
'Desactivar la deteccin de errores
On Local Error GoTo 0
End Function
Para usarla, por ejemplo para saber el programa asociado para abrir una
determinada extensin, de que programa se obtiene el icono y que nmero
de icono es:
NOTA: Para usar este ejemplo, hay que tener un control List2 en el Form y
la rutina mostrada antes.
Private Sub BuscarExtensionID(sExt As String)
Dim lRet As Long
Dim sKey As String
Dim sValue As String
Dim hKey As Long
Dim sExe As String
Dim sIcon As String
Dim lIcon As Long
Dim sProgId As String
Dim i As Integer
Caption = "Mostrar asociaciones de la clave: " &
sExt
List2.Visible = True
List2.Clear
List2.AddItem "Valores del Registro para " & sExt
'
'Buscar en el registro la extensin...
sProgId = QueryRegBase(sExt)
If Len(sProgId) Then
List2.AddItem "Clave: " & sProgId
sKey = sProgId & "\DefaultIcon"
List2.AddItem sKey
sValue = QueryRegBase(sKey)
If Len(sValue) Then
i = InStr(sValue, ",")
If i Then
sIcon = Left$(sValue, i - 1)
lIcon = Val(Mid$(sValue, i + 1))
Else
End If
End If
List2.AddItem "
List2.AddItem "
'
'Obtener el programa asociado por defecto para
Abrir
'no quiere decir que este sea el que se ejecute cuando
se haga doble-click
sKey = sProgId & "\Shell\Open\Command"
sValue = QueryRegBase(sKey)
If Len(sValue) Then
i = InStr(sValue, ".")
If i Then
i = InStr(i, sValue, " ")
If i Then
sExe = Trim$(Left$(sValue, i - 1))
Else
sExe = Trim$(sValue)
End If
Else
sExe = Trim$(sValue)
End If
End If
List2.AddItem sKey
List2.AddItem "
End If
End Sub
Ejemplo para crear claves en el Registro:
Para no alargar demasiado este fichero, aqu slo estn las declaraciones de
las funciones; en los listados del programa gsExecute, hay ejemplos de
cmo crear y borrar claves para asociar/desasociar un programa a una
extensin determinada.
'Claves del Registro
Public Const HKEY_CLASSES_ROOT = &H80000000
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_USERS = &H80000003
'
'Para los valores devueltos por las funciones de manejo
del Registro
Public Const ERROR_SUCCESS = 0&
Public Const ERROR_NO_MORE_ITEMS = 259&
'
' Tipos de datos Reg...
Public Const REG_SZ = 1
'
'Declaraciones del API de Windows para 32 bits
Declare Function RegQueryValue Lib "advapi32.dll" Alias
"RegQueryValueA" (ByVal hKey As Long, ByVal lpSubKey As
String, ByVal lpValue As String, lpcbValue As Long) As
Long
Declare Function RegEnumKey Lib "advapi32" Alias
"RegEnumKeyA" (ByVal hKey As Long, ByVal iSubKey As
Long, ByVal lpszName As String, ByVal cchName As Long)
As Long
Declare Function RegOpenKey Lib "advapi32" Alias
"RegOpenKeyA" (ByVal hKey As Long, ByVal lpszSubKey As
String, phkResult As Long) As Long
Declare Function RegCloseKey Lib "advapi32" (ByVal hKey
As Long) As Long
Long
#Else
Declare Function GetTickCount Lib "User" () As Long
#End If
Para usarlo, hay que crear un Form con los siguientes controles:
'
'Prueba de Timer,
(21:00 14/Ene/96)
Option Explicit
'Declaracin del API
#If Win32 Then
Private Declare Function GetTickCount Lib "Kernel32"
() As Long
#Else
Private Declare Function GetTickCount Lib "User" ()
As Long
#End If
'Para saber que accin debe tomar el botn
Dim Contando As Boolean
'Variables para el GetTickCount
Dim g1 As Long
Dim g2 As Long
Dim g3 As Long
'Variables para el Timer1
Dim t1 As Long
Dim t2 As Long
'valor para el timer
Dim vTimer As Long
'Flag para cancelar el bucle
Dim Cancelar As Boolean
'valor mximo de items a mostrar
Dim MaxBucle As Long
Private Sub cmdIniciar_Click()
Contar
End Sub
Private Sub cmdSalir_Click()
Cancelar = True
DoEvents
Contando = True
Contar
Unload Me
End Sub
Private Sub Form_Load()
'
Timer1.Interval = 1000
Timer1.Enabled = False
Text1 = "1000"
MaxBucle = 20000
End Sub
Private Sub Text1_Change()
'
Dim vTmp
Static YaEstoy As Boolean
'No entrar mientras se procesa...
If YaEstoy Then Exit Sub
YaEstoy = True
vTmp = Val(Text1) \ 10
If vTmp > VScroll1.Min Then
vTmp = VScroll1.Min
End If
If vTmp < VScroll1.Max Then
vTmp = VScroll1.Max
End If
Text1 = CStr(vTmp * 10)
VScroll1.Value = vTmp
YaEstoy = False
End Sub
Private Sub Timer1_Timer()
'nmero de segundos transcurridos
t2 = Timer - t1
Mostrar
DoEvents
End Sub
Private Sub VScroll1_Change()
Static YaEstoy As Boolean
Dim i As Long
List1.Clear
'Inicializar el temporizador "manual"
g1 = GetTickCount()
g3 = 0
Do
i = i + 1
List1.AddItem CStr(i)
List1.ListIndex = List1.ListCount - 1
gTimer
If Cancelar Then Exit Do
If i = MaxBucle Then
Exit Do
End If
Loop
'Detener la accin...
Contando = True
Contar
'Actualizar los resultados
Mostrar
End Sub
Private Sub gTimer()
g2 = GetTickCount() - g1
'Este if, es para que se muestre cada segundo
If g2 > (g3 + 1) * 1000 Then
g3 = g3 + 1
Mostrar
End If
DoEvents
End Sub
Private Sub Mostrar()
Label2(0) = t2
Label2(1) = g3
End Sub
'
ByVal
lpVolumeNameBuffer As String, _
ByVal
nVolumeNameSize As Long, _
lpVolumeSerialNumber
As Long, _
lpMaximumComponentLength As Long, _
lpFileSystemFlags As
Long, _
ByVal
lpFileSystemNameBuffer As String, _
ByVal
nFileSystemNameSize As Long) As Long
Dir.
sTmp = Hex$(lVSN)
Label3(0) = s1
Label3(1) = Left$(sTmp, 4) & "-" & Right$(sTmp, 4)
Label3(2) = s2
End Sub
'Buscar cadena
'Buscar cadena
'Buscar cadena
'Buscar cadena
'Mensaje
'Mensaje
Dim L As Long
If cList.ListCount = 0 Then
'Seguro que no est, as que aadirla
L = -1
Else
'Si el control es un Combo
If TypeOf cList Is ComboBox Then
L = SendMessage(cList.hWnd,
CB_FINDSTRINGEXACT, -1, ByVal sTexto)
'Si el control es un list
ElseIf TypeOf cList Is ListBox Then
L = SendMessage(cList.hWnd,
LB_FINDSTRINGEXACT, -1, ByVal sTexto)
Else
'no es un control List o Combo, salir
ActualizarLista = -1
Exit Function
End If
End If
'Si no est, aadirla
If L = -1 Then
cList.AddItem sTexto
L = ActualizarLista(sTexto, cList)
End If
ActualizarLista = L
End Function
Este otro ejemplo es para efectuar una bsqueda en el Combo/List, al estilo
de la ayuda de Windows, es una versin a la aparecida en los trucos, pero
usando SendMessage.
Para usarlo en un ListBox, debes indicar la constante LB_FINDSTRING, en
lugar de CB_FINDSTRING
(Este "truco" est sacado del MSDN Library: Tip 115: Performing Smart
Searches in Combo Box Controls)
Private Sub Combo1_KeyPress(KeyAscii As Integer)
Dim CB As Long
Dim FindString As String
Const CB_ERR = (-1)
Const CB_FINDSTRING = &H14C
If KeyAscii < 32 Or KeyAscii > 127 Then Exit Sub
If Combo1.SelLength = 0 Then
FindString = Combo1.Text & Chr$(KeyAscii)
Else
FindString = Left$(Combo1.Text, Combo1.SelStart)
& Chr$(KeyAscii)
End If
CB = SendMessage(Combo1.hWnd, CB_FINDSTRING, -1,
ByVal FindString)
If CB <> CB_ERR Then
Combo1.ListIndex = CB
Combo1.SelStart = Len(FindString)
'Disquetes, etc
End Function
'Nmero de lneas
'Posicin del
'Longitud de una
'...
Next
a0@null.net
********************************************************
**
Option Explicit
Private Declare Function ShellExecute Lib "shell32.dll"
Alias _
"ShellExecuteA" (ByVal hwnd As Long, ByVal
lpOperation As String, _
As Long
23/09/97 0:48:04
5
;Nmero de trozos
32
Versin 16 bits
'
' (c) Guillermo Som Cerezo
(18/May/95)
'
' Utilidad para reiniciar windows.
' Muestra tambin la memoria y recursos libres. ( 1/Sep/96)
'
'---------------------------------------------------------Option Explicit
Declare Function ExitWindows Lib "User" (ByVal ReStartCode As Long, ByVal
DosReturnCode As Integer) As Integer
'Obtener la memoria y recursos libres
( 1/Sep/96)
End Sub
( 8/Nov/95)
'
'Finaliza Windows
'
'Reinicia el equipo
'
Public Const EWX_FORCE = 4
responde
End If
End Sub
Esta versin es para 16 bits y tiene unas cuantas cosas interesantes, creo...
Entre otras cosas, vuelvo a recordar que slo la he probado en Windows 3.1x.
En este programa se cambia el "grfico" del control box de la ventana, esto en Windows95 no
tiene sentido, pero en Windows 3.1x si que lo tiene, ya no muestra el icono de la aplicacin.
De todas formas, tambin es til para poder usar el dibujo que quieras usar.
Acabo de probarlo, desde VB3 y me he dado cuenta que ya por esta poca tena en los
botones (no en los grficos, sino en las etiquetas) unos efectos esos de que se activa cuando
pasas por encima de ellos...
Tambin tiene, entre otras cosas, el mtodo que usaba para saber el Ejecutable asociado con
una extensin determinada, es que en aquellos tiempos no haba caido en mis manos ningn
cdigo que lo hiciera, as que lo hice "por la cuenta de la vieja", mira el cdigo de
BuscarExtensin y vers porqu lo digo.
A lo mejor todo esto te parece complicado, pero... es cuestin de tomar la parte que te
interese. ;-)
Veamos la pantalla de inicio:
Ahora el cdigo:
Ya que es un poco largo, te recomiendo que "bajes" el archivo ZIP (gswexit.zip 13.8 KB)
Aqu slo voy a poner un par de cosillas.
Realmente, despus de ver el cdigo, mi intencin con este programa fue el de distribuirlo de
forma gratuita, lo que ocurre es que nunca llegu a hacerlo, echale un vistazo a lo que
pretenda ser el Acerca de... (pero que nunca fu)
Insisto: esto era para el Windows 3.1x
'
Sub mnuGuille_Click ()
'Este ser el About...
'La idea de hacer esta utilidad, surgi de poder
'reiniciar Windows, sin tener que salir de Windows.
'Ya que cuando se est programando, es necesario dejar
'Windows como estaba al cargar, sin libreras que se
'quedan 'colgadas' cuando no terminas correctamente el
'programa y otras malas pasadas, sin ser 'desequilibradoras'.
'Despus fu aadiendo opciones, tal como guardar una
'lista de los ltimos programas ejecutados; porque
'tambin es desesperante el tener que probar un msmo
'programa y por no crear un icono, estar siempre 'Examinando'
'la localizacin del msmo. As como querer ejecutar
'los programas que vas 'descomprimiendo' en un directorio
'temporal, para ir viendo si son interesantes...
'No s si este programa llegar a 'distribuirlo', pero
'que conste que cada da que pasa voy cambiando cosas,
'segn la informacin que voy 'acumulando'.
'Informacin que viene de los programas Share, etc.
'
'Si tienes alguna rutina o truco del Api de Windows
Gracias.
End Sub
'Esta es la parte que dibuja el bitmap en el sitio del Men de Control
'No recuerdo de dnde saque esta informacin:
Sub DrawBitmapNCArea (hWindow As Integer, hbmp As Integer, cxLeft As
Integer, cyTop As Integer)
Dim hdc%, hdcMem%
Dim bmp As BITMAP
Dim hbmpOld%
Dim lprect As RECT
Dim hinst%
Dim rc&
hinst = GetWindowWord(hWindow, GWW_HINSTANCE)
hdc = GetWindowDC(hWindow)
hdcMem = CreateCompatibleDC(hdc)
rc = APIGetObject(hbmp, Len(bmp), bmp)
hbmpOld = SelectObject(hdcMem, hbmp)
rc = BitBlt(hdc, cxLeft, cyTop, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0,
SRCCOPY)
rc = SelectObject(hdcMem, hbmpOld)
rc = DeleteDC(hdcMem)
rc = ReleaseDC(hWnd, hdc)
End Sub
'Buscar el ejecutable asociado a una extensin (del archivo WIN.INI)
Function BuscarExtension (QueExt As String) As String
'---------------------------------------------------------'Buscar una extensin en el fichero WIN.INI
( 7/Nov/94)
nf = GetWindowsDirectory(WinDir, Len(WinDir))
WinDir = Left$(WinDir, nf)
nf = FreeFile
Open WinDir + "\WIN.INI" For Input As nf
Do While Not EOF(nf)
Line Input #nf, stmp
If EnExtensions Then
stmp = UCase$(LTrim$(stmp))
'comprobar si no es otro grupo
If Left$(stmp, 1) = "[" Then
EnExtensions = False
stmp = ""
Exit Do
End If
If Left$(stmp, 3) = QueExt Then
'Extensin hallada
'Quitar los caracteres no vlidos
i = InStr(stmp, "^")
If i Then
stmp = Left$(stmp, i - 1)
End If
i = InStr(stmp, "=")
If i Then
stmp = LTrim$(Mid$(stmp, i + 1))
End If
Exit Do
End If
End If
If InStr(stmp, "[Extensions]") Then
EnExtensions = True
End If
Loop
Close nf
'Si no est definida esa extensin, usar el bloc
If EnExtensions Then
BuscarExtension = stmp
Else
BuscarExtension = "notepad"
End If
End Function
'Salir de Windows
ExitWin 3
Case 2
'Reiniciar Windows
ExitWin 2
Case 3
'Reiniciar el ordenador
ExitWin 1
Case 4
'Ejecutar un programa...
Form2.Show 1
Case 6
'Terminar el programa
( 8/Nov/94)
Unload Me
End Select
End Sub
Voy a preparar un ejemplo/utilidad para poder usar las funciones del API
para copiar/mover/borrar, etc. que es lo que ms o menos se explica en el
primero de los dos artculos mencionados, pero no lo veo lo suficientemente
claro como para que sea fcilmente "usable" y entendible... (a lo mejor es
que soy demasiado torpe...)
'Crea un mdulo BAS e inserta estas declaraciones:
Type SHFILEOPSTRUCT
hWnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer ' As Long para que funcione en
Windows XP con VB6
fAborted As Boolean
hNameMaps As Long
sProgress As String
End Type
Public Const FO_DELETE = &H3
Public Const FOF_ALLOWUNDO = &H40
Declare Function SHFileOperation Lib "shell32.dll" Alias
"SHFileOperationA" _
(lpFileOp As SHFILEOPSTRUCT) As Long
Public Function ShellDelete(ParamArray vntFileName() As
Variant) As Long
Dim I As Integer
Dim sFileNames As String
Dim SHFileOp As SHFILEOPSTRUCT
For I = LBound(vntFileName) To UBound(vntFileName)
sFileNames = sFileNames & vntFileName(I) & vbNullChar
Next
sFileNames = sFileNames & vbNullChar
With SHFileOp
.wFunc = FO_DELETE
.pFrom = sFileNames
.fFlags = FOF_ALLOWUNDO
End With
ShellDelete = SHFileOperation(SHFileOp)
End Function
'En un formulario, inserta un botn Command y escribe
esto:
Private Sub Command1_Click()
Dim FileToKill As String
'Escribe aqu el archivo a borrar
FileToKill = "c:\test*.txt"
ShellDelete FileToKill
MsgBox "File(s) deleted"
End Sub
Para probarlo, simplemente pulsa F5, debers tener el archivo que quieres
borrar... sino cmo lo vas a borrar? 8-)
As Long
dwHighDateTime
As Long
End Type
Private Type WIN32_FIND_DATA
dwFileAttributes
As Long
ftCreationTime
As FILETIME
ftLastAccessTime
As FILETIME
ftLastWriteTime
As FILETIME
nFileSizeHigh
As Long
nFileSizeLow
As Long
dwReserved0
As Long
dwReserved1
As Long
cFileName
As String * MAX_PATH
cAlternate
As String * 14
End Type
Private Declare Function FindFirstFile Lib "kernel32"
Alias "FindFirstFileA" _
(ByVal lpFileName As String, lpFindFileData As
WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" _
(ByVal hFindFile As Long) As Long
Public Function FileExist(ByVal sFile As String) As
Boolean
'comprobar si existe este fichero
Dim WFD As WIN32_FIND_DATA
Dim hFindFile As Long
hFindFile = FindFirstFile(sFile, WFD)
'Si no se ha encontrado
If hFindFile = INVALID_HANDLE_VALUE Then
FileExist = False
Else
FileExist = True
'Cerrar el handle de FindFirst
hFindFile = FindClose(hFindFile)
End If
End Function
'Para usarla:
If FileExist("lo que quieras comprobar") Then
'El archivo existe
Else
'El archivo no existe
End If
'El cdigo
' Tipos definidos
Private Type LUID
UsedPart As Long
IgnoredForNowHigh32BitPart As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
TheLuid As LUID
Attributes As Long
End Type
' Las constantes
Private Const EWX_SHUTDOWN As Long = 1
Private Const EWX_FORCE As Long = 4
Private Const EWX_REBOOT = 2
tkp.PrivilegeCount = 1
set
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
' Enable the shutdown privilege in the access
token of this
' process.
AdjustTokenPrivileges hdlTokenHandle, False,
tkp, _
Len(tkpNewButIgnored), tkpNewButIgnored,
lBufferNeeded
End Sub
Private Sub cmdForceShutdown_Click()
AdjustToken
ExitWindowsEx (EWX_SHUTDOWN Or EWX_FORCE Or
EWX_REBOOT), &HFFFF
End Sub
'
'If we couldn't change to the request drive, it's
an error, otherwise return
'the amount of disk space free
'
If Err <> 0 Or (strDrive <> Left$(CurDir$, 2))
Then
lDiskFree = -1
Else
lDiskFree = DiskSpaceFree()
If Err <> 0 Then
couldn't be found
lDiskFree = -1
End If
End If
'
GetDiskSpaceFree = lDiskFree
'
'Cleanup by setting the current drive back to the
original
'
ChDrive strCurDrive
Err = 0
End Function
'que la funcin
sndPlaySound sea llamada de nuevo con un valor nulo
para NombreWav (NULL).
'Para tocar un WAV de forma repetitiva, lo llamas
as:
Call sndPlaySound(Archivo, SND_ASYNC + SND_LOOP)
'Para detener lo que se est tocando
Call sndPlaySound(ByVal "", 0)
21.- Un ejemplo, usando API, de cmo tocar de
forma indefinida un fichero MIDI (10/Abr/98)
Aunque ya he puesto un tip en la seccin del API, aunque slo para WAVs, te muestro aqu
cmo hacer que tambin ser repita un fichero de sonido del tipo MIDI, de camino, en el
ejemplo tambin se incluye ese ejemplo, para que puedas probarlo, ya que entre otras cosas,
lo que si se puede hacer es tocar un fichero WAV y un MIDI al mismo tiempo... lo mismo
ocurrira con una pista de un CD de audio... Aunque este tema es ms laborioso por aquello
de que hay que controlar la pista que se quiere tocar y esas cosas... as que en este ejemplo
slo se contemplan los WAVs y MIDIs.
El ejemplo:
Este ejemplo permite seleccionar dos ficheros de sonido, relamente no permite seleccionar,
sino que debes especificar los que quieres usar.
Tiene dos botones para poder tocar cada uno de ellos, siempre que sean de diferentes tipos,
ya que no se permite tocar dos WAVs al mismo tiempo...
Slo habr un botn de detener, para parar cualquier fichero que se est tocando y para que
se puedan especificar los nombres de esos ficheros a usar, se usan dos TEXTBOXES.
Veamos una "instantnea" del form en tiempo de diseo:
Para los ficheros de tipo WAVs, no hay conplicacin, ya que usando sndPlaySound con los
parmetros: SND_ASYNC + SND_LOOP, se consigue lo deseado.
Sin embargo para los MIDIs, hay que saber cuando termina para volver a tocarlo de nuevo,
esto se soluciona aadiendo un control timer al form y comprobar si se ha terminado de tocar
el fichero, en caso de que sea as, empezar de nuevo... y as hasta que lo detengamos.
Este sera el cdigo del Timer1_Timer:
Private Sub Timer1_Timer()
Dim mciStatusParms As MCI_STATUS_PARMS
'Slo para el MIDI:
If IdMIDI Then
'Obtenemos el estado del dispositivo
mciStatusParms.dwItem = MCI_STATUS_MODE
Call mciSendCommand(IdMIDI, MCI_STATUS, MCI_STATUS_ITEM, _
mciStatusParms)
'Si no se est reproduciendo
If mciStatusParms.dwReturn = MCI_MODE_STOP Then
'Empezar de nuevo
'Posicionar el puntero al principio
Call mciSendCommand(IdMIDI, MCI_SEEK, _
MCI_SEEK_TO_START, 0)
'Empezar de nuevo
Call mciSendCommand(IdMIDI, MCI_PLAY, 0, 0)
End If
End If
End Sub
Es decir, se comprueba el estado del dispositivo, si el modo que devuelve es que est parado,
se posiciona el "puntero" de la cancin al principio y se le indica que vuelva a empezar a
tocarlo.
Cuando nos hartemos de que toque... lo paramos y ya est. Esto mismo hay que hacerlo al
cerrar el FORM...
Veamos el cdigo para detener el MIDI:
'Detener el MIDI
Call mciSendCommand(IdMIDI, MCI_STOP, 0, 0)
Call mciSendCommand(IdMIDI, MCI_CLOSE, 0, 0)
IdMIDI = 0
Timer1.Enabled = False
Para detenerlo, le mandamos un comando STOP y de camino cerramos el dispositivo.
Esto lo podemos tener en un procedimiento, para que lo podamos usar de forma genrica, lo
mismo desde un botn que detenga la msica como desde el evento UNLOAD del form.
Lo nico que necesitaramos es usar un SUB que haga lo mismo, es decir: PARE y CIERRE.
Veamos ahora el cdigo para que la cancin empiece a tocar:
'
Private Sub TocarMIDI(ByVal sMID As String)
'Tocar un Mid usando mciSendCommand
'
Dim mciOpenParms As MCI_OPEN_PARMS
If IdMIDI <> 0 Then
Call mciSendCommand(IdMIDI, MCI_CLOSE, 0, 0)
IdMIDI = 0
End If
With mciOpenParms
.lpstrElementName = sMID
End With
Call mciSendCommand(0, MCI_OPEN, _
MCI_OPEN_ELEMENT, _
mciOpenParms)
IdMIDI = mciOpenParms.wDeviceID
Call mciSendCommand(IdMIDI, MCI_PLAY, 0, 0)
Timer1.Enabled = True
End Sub
Aqu se comprueba si ya se est usando otro MIDI, en caso de que sea as, se detiene la
anterior y se empieza con la nueva.
Ahora bien... cmo sabemos si es un fichero MID o uno WAV?
Pues con una simple comparacin... si la extensin es MID, se tocar como MIDI, si es WAV,
como WAV...
Vamos a ver el cdigo completo del botn tocar:
Private Sub cmdTocar_Click(Index As Integer)
Dim Archivo As String
10. Una clase para saber los directorios del Sistema (usando el Registro)
11. Una API para saber los directorios del Sistema
(SHGetSpecialFolderPath)
17. Enumerar las claves o valores de una clave del registro de Windows
(ejemplo usando la clase cQueryReg)
20. Manejar ficheros INIs: leer, guardar, borrar, leer secciones enteras,
leer todas las secciones (06/Mar)
GetDiskFreeSpaceExA(
LPCSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
);
El problema se me present a la hora de convertir el tipo ese
PULARGE_INTEGER, busqu en las definiciones y me encontr con esto en
el fichero WINNT.H:
#if defined(MIDL_PASS)
typedef struct _ULARGE_INTEGER {
#else // MIDL_PASS
typedef union _ULARGE_INTEGER {
struct {
DWORD LowPart;
DWORD HighPart;
};
struct {
DWORD LowPart;
DWORD HighPart;
} u;
#endif //MIDL_PASS
DWORDLONG QuadPart;
} ULARGE_INTEGER;
typedef ULARGE_INTEGER *PULARGE_INTEGER;
La verdad es que no saba que hacer con esto, salvo usar un tipo definido
con dos longs, pero antes de empezar a "probar", rebusqu en los CDs que
tengo del MSDN lo que haba sobre esta funcin, la verdad es que no
encontr demasiado, por no decir nada... salvo un comentario a cmo
poder usar el tipo Currency para valores grandes, ya que es casi un tipo
entero de 8 bits, slo que el resultado obtenido habr que multiplicarlo por
10000, ya que ese tipo de datos contiene un nmero con 4 decimales.
Prob y... funcion! y aqu est la declaracin a usar en Visual Basic:
Private Declare Function GetDiskFreeSpaceEx Lib "kernel32" Alias
"GetDiskFreeSpaceExA" _
(ByVal lpRootPathName As String, _
lpFreeBytesAvailableToCaller As Currency, _
lpTotalNumberOfBytes As Currency, _
lpTotalNumberOfFreeBytes As Currency) As Long
Para usarla, hay que multiplicar por 10000 el valor de los bytes devueltos.
Aqu tienes una funcin que devuelve el espacio total, as como el espacio
libre, todo ello en bytes:
En esta funcin el nombre del path puede estar representado por un
nombre UNC: \\Equipo\recurso\
Private Function EspacioLibreEx(ByVal lpRootPathName As String)
'lpRootPathName= Directorio raiz de la unidad a examinar
'Valores devueltos por la funcin:
Dim ret As Long
Dim lpFreeBytesAvailableToCaller As Currency
Dim lpTotalNumberOfBytes As Currency
Dim lpTotalNumberOfFreeBytes As Currency
'
Dim TotalBytes As Currency
Dim TotalFreeBytes As Currency
ret = GetDiskFreeSpaceEx(lpRootPathName, _
lpFreeBytesAvailableToCaller, _
lpTotalNumberOfBytes, _
lpTotalNumberOfFreeBytes)
TotalBytes = lpTotalNumberOfBytes * 10000
TotalFreeBytes = lpTotalNumberOfFreeBytes * 10000
EspacioLibreEx = Format(TotalBytes, "###,###,###") & " / "
&_
Format(TotalFreeBytes, "###,###,###")
End Function
Este ejemplo muestra como manejar con el API, las barras de scroll en aquellos controles que
no disponen de la propiedad "ScrollBars"
Utiliza la funcin sBarVisible para ocultar/mostrar las barras de desplazamiento de un control, y
la funcin sBarEnabled para habilitarlas/dehabilitarlas.
El siguiente cdigo esta pensado para incluirse como mdulo BAS dentro un proyecto de VB 32
bits
Option Explicit
'Funciones para el manejo de las barras de desplazamiento
'en controloes que no dispones de la propiedad "ScrollBars"
'
'sBarFunciones.bas 2 de Mayo de 1.998 VB5
'Por Jose Montaner 'Satelite' casa2001@apdo.com
' Constantes de barra de desplazamiento
Public Enum eBar
Horizontal = 0
Vertical = 1
Automatico = 2
Ambas = 3
End Enum
Private Declare Function EnableScrollBar Lib "user32" _
(ByVal hwnd As Long, ByVal wSBflags As Long, ByVal wArrows As Long) As Long
Private Declare Function ShowScrollBar Lib "user32" _
(ByVal hwnd As Long, ByVal wBar As Long, ByVal bShow As Long) As Long
Public Sub sBarVisible(ByVal cntrl As Variant, ByVal barras As eBar, ByVal visible As
Boolean)
'Muestra/Oculta barras de desplazamiento
'cntrl: Control que deseamos atacar
'barras: Indica que barras queremos mostrar/ocultar
'Visiable: True/False
Dim ret As Long
ret = ShowScrollBar(cntrl.hwnd, barras, visible)
End Sub
Public Sub sBarEnabled(ByVal cntrl As Variant, ByVal barras As eBar, ByVal enabled
As Boolean)
'Habilita/Deshabilita
'cntrl: Control que deseamos atacar
'barras: Indica que barras queremos habilitar/deshabilitar
'Enabled: True/False
Dim ret As Long
ret = EnableScrollBar(cntrl.hwnd, barras, IIf(enabled, 0, &H3))
End Sub
3.- Generar un nmero nico para cada equipo...
MyGuidString1 = Hex$(lguid.Data1)
StringLen = Len(MyGuidString1)
DataLen = Len(lguid.Data1)
MyGuidString1 = LeadingZeros(2 * DataLen,
StringLen) _
& MyGuidString1 'First 4 bytes (8 hex
digits)
MyGuidString2 = Hex$(lguid.Data2)
StringLen = Len(MyGuidString2)
DataLen = Len(lguid.Data2)
MyGuidString2 = LeadingZeros(2 * DataLen,
StringLen) _
& Trim$(MyGuidString2) 'Next 2 bytes (4 hex
digits)
MyGuidString3 = Hex$(lguid.Data3)
StringLen = Len(MyGuidString3)
DataLen = Len(lguid.Data3)
MyGuidString3 = LeadingZeros(2 * DataLen,
StringLen) _
& Trim$(MyGuidString3) 'Next 2 bytes (4 hex
digits)
error_olemsg:
MsgBox "Error " & Str(Err) & ": " & Error$(Err)
GetGUID = "00000000-0000-0000-0000000000000000"
Exit Function
End Function
Private Function LeadingZeros(ExpectedLen As Integer,
ActualLen As Integer) As String
LeadingZeros = String$(ExpectedLen - ActualLen, "0")
End Function
Cmo usar esta clase?
Para usar esta clase, hazlo de la siguiente forma:
Private Sub cmdGenGUID_Click()
'Creamos una instancia de la clase
Dim tGuid As New cGUID
'Asignamos el nmero generado, en este ejemplo lo
asignamos a un Label
Label2 = tGuid.GetGUID
'Destruimos la referencia al objeto
Set tGuid = Nothing
End Sub
(15/Jun/98)
'
'Microsoft TechNet Knowledge Base, PSS ID Number: Q180936
'HOWTO: Position a MsgBox Using a Windows Hook Procedure
'
'Guillermo 'guille Som, 1998
'-----------------------------------------------------------------Option Explicit
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias
"GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public Declare Function GetWindowRect Lib "user32" _
(ByVal hwnd As Long, lpRect As RECT) As Long
((rectMsg.Right - rectMsg.Left) / 2)
y = (rectForm.Top + (rectForm.Bottom - rectForm.Top) / 2) - _
((rectMsg.Bottom - rectMsg.Top) / 2)
'Position the msgbox
SetWindowPos wParam, 0, x, y, 0, 0, _
SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE
'Release the CBT hook
UnhookWindowsHookEx hHook
End If
WinProc2 = False
End Function
Este es el cdigo que hay que aadir al formulario:
'
'-----------------------------------------------------------------'Ejemplo para posicionar un MsgBox
(15/Jun/98)
'
'Microsoft TechNet Knowledge Base, PSS ID Number: Q180936
'HOWTO: Position a MsgBox Using a Windows Hook Procedure
'
'Guillermo 'guille Som, 1998
'-----------------------------------------------------------------Option Explicit
Private Sub Command1_Click()
Dim hInst As Long
Dim Thread As Long
'Set up the CBT hook
hInst = GetWindowLong(Me.hwnd, GWL_HINSTANCE)
Thread = GetCurrentThreadId()
hHook = SetWindowsHookEx(WH_CBT, AddressOf WinProc1, hInst,
Thread)
'Display the message box
MsgBox "This message box has been positioned at (0,0)."
End Sub
Private Sub Command2_Click()
Ahora vamos a ver cmo funciona todo esto, aunque antes un par de
consejos y un poco de explicacin.
Antes de empezar a "recibir" o procesar los mensajes recibidos, hay que
indicarle a Windows que empiece la funcin, esto se hace mediante un
"gancho" (Hook que llaman los ingleses a esto); esto siempre hay que
hacerlo antes de nada y para indicarle a Windows que deje de estar
enganchados a nosotros, debemos quitar ese gancho.
Para estas dos tareas, el mdulo BAS tiene dos procedimientos: HookForm
y unHookForm, (ahora explicar cmo usarlos).
Lo importante de todo esto es que se debe llamar a unHookForm cuando no
necesitemos que Windows nos enve los mensajes. Si estamos probando en
el IDE es importantsimo quitar el gancho, sino el VB se quedar ms
colgado que... (busca tu un ejemplo, no lo voy a hacer yo todo...), as que
si te pones a experimentar con esto de la subclasificacin y esas cosas, es
recomendable que le des a guardar de continuo, sobre todo antes de darle
a F5 y tambin te recomendara que compilaras de forma completa, bien
pulsando Ctrl+F5 o bien modificando el modo de compilacin en el men
Herramientas/Opciones solapa General y en el cuadro Compilar quitar la
marca en Compilar bajo peticin, si tienes la versin inglesa del VB, ser:
Tools/Options/General/Compile on Demand
Con esto lo que consigues es que si hay alguna variable no declarada o algo
"raro", lo detecte antes de ejecutar la aplicacin.
'----------------------------------------------------------------'Prueba de subclasificacin
(26/Jun/98)
'Se comprobarn los mensajes enviados por cambio en la
seleccin
'de los mens
'
'Guillermo 'guille' Som, 1998
'----------------------------------------------------------------Option Explicit
'Este es el mensaje enviado por Windows cuando se
selecciona
'un men
Const WM_MENUSELECT As Long = &H11F&
'Para el men del sistema
Const SC_RESTORE
As Long = &HF120&
Const SC_MOVE
As Long = &HF010&
Const SC_SIZE
As Long = &HF000&
As Long = &HF060&
Case 2
sMsg = "Has seleccionado Abrir..."
Case 3
sMsg = "Has seleccionado Guardar"
Case 4
sMsg = "Has seleccionado Guardar
como..."
Case 6
sMsg = "Has seleccionado Imprimir..."
Case 8
sMsg = "Has seleccionado Salir"
'
'Case 9
'
Case 10
sMsg = "Has seleccionado Deshacer"
Case 12
sMsg = "Has seleccionado Copiar"
Case 13
sMsg = "Has seleccionado Cortar"
Case 14
sMsg = "Has seleccionado Pegar"
Case 16
todo..."
programa"
Case Else
sMsg = ""
End Select
'Mostrar el mensaje en el Label
Label1 = sMsg
End If
End Sub
Lo que quiero decir con todo este rollo, es que debemos ser generosos con la
longitud de las cadenas pasadas a funciones del API, si sabemos que son directorios
o archivos los valores que van a devolver, con una longitud de 260, sera ms que
suficiente, ya que este valor es el mximo soportado por los nombres largo. Este
valor, est definido en la constante MAX_PATH del SDK del API de Windows.
Por cierto en el fichero Win32API.TXT est mal, ya que indica que son 32
caracteres, cualdo deberan ser 260.
BIF_DONTGOBELOWDOMAIN = &H2
de red
BIF_STATUSTEXT = &H4
BIF_RETURNFSANCESTORS = &H8
BIF_BROWSEFORCOMPUTER = &H1000
BIF_BROWSEFORPRINTER = &H2000
'Buscar PCs
'Buscar impresoras
End Enum
Private Type BrowseInfo
hwndOwner
pIDLRoot
empezar a mostrar
pszDisplayName
As Long
As Long
As Long
lpszTitle
As Long
ulFlags
As Long
lpfnCallback
As Long
lParam
As Long
iImage
As Long
End Type
'Especifica dnde se
(27/Oct/97)
#Else
Dim hWnd%, hMenu%, Success%
#End If
Dim i%
hWnd = Me.hWnd
hMenu = GetSystemMenu(hWnd, 0)
'Quitar todos (va de 0 a 8)
For i = 8 To 0 Step -1
Success = DeleteMenu(hMenu, i, MF_BYPOSITION)
Next
Exit Sub
'Usa esto para quitar los mens que te interesen:
Success = DeleteMenu(hMenu, SC_SIZE, MF_BYCOMMAND)
'Success = DeleteMenu(hMenu, SC_MOVE, MF_BYCOMMAND)
Success = DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND)
Success = DeleteMenu(hMenu, SC_MINIMIZE,
MF_BYCOMMAND)
'Success = DeleteMenu(hMenu, SC_MAXIMIZE,
MF_BYCOMMAND)
'Success = DeleteMenu(hMenu, SC_RESTORE,
MF_BYCOMMAND)
End Sub
dentro de una coleccin con los valores) o bien una cadena con el nombre del directorio que
queremos; los valores de estas cadenas son los nombres usados en el registro de Windows
para nombrarlos.
Por ejemplo para obtener el directorio en el que est el Men de Inicio habr que usar como
"cadena" Start Menu.
En el form de prueba, se usa un combo para contener los diferentes valores que se pueden
usar para conseguir ese directorio.
Adems de obtener los nombres de los directorios, esta clase tiene una funcin/mtodo que
devuelve un valor de una entrada del registro, (del tipo cadena, DWORD o Binary), no voy a
explicar cmo usarla porque estoy preparando otra clase ms genrica para manipular los
datos del registro, por ahora slo tengo la parte de obtener los valores, pero si todo va bien,
tambin se podrn crear claves y (espero) cambiar los valores de las claves.
Aqu tienes los listados del form de prueba y los de la clase. Espero que te sea til.
Si quieres los listados, aqu los tienes: (OSFolders.zip 5.55 KB)
El formulario:
'-----------------------------------------------------------------'
(13/Ago/98)
End Sub
Private Sub Combo1_Click()
cmdMostrar_Click
End Sub
Private Sub Form_Load()
Set tOSF = New cOSFolders
Dim col As New Collection
Dim i As Long
'Devolver slo las claves de los directorios
Set col = tOSF.ShellFolders(bSoloClaves:=True)
With Combo1
.Clear
For i = 1 To col.Count
.AddItem col(i)
Next
If .ListCount Then
.ListIndex = 0
End If
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set tOSF = Nothing
End Sub
La Clase:
'
'-----------------------------------------------------------------'cOSFolders
(13/Ago/98)
'
'Guillermo 'guille' Som, 1998
'email: mensaje@elguille.info / mensaje@elguille.info
'
'Funciones/Mtodos de la clase:
'
GetReg
'
GetFolder
'
ShellFolders
'
'-----------------------------------------------------------------Option Explicit
Dim colShellFolders As Collection
Dim colShellFoldersKey As Collection
Private Declare Function GetWindowsDirectory Lib "kernel32" Alias
"GetWindowsDirectoryA" _
(ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Declare Function GetSystemDirectory Lib "kernel32" Alias
"GetSystemDirectoryA" _
(ByVal lpBuffer As String, ByVal nSize As Long) As Long
' Registry manipulation API's (32-bit)
'Claves del Registro
Public Enum eHKEY
HKEY_CLASSES_ROOT = &H80000000
HKEY_CURRENT_USER = &H80000001
HKEY_LOCAL_MACHINE = &H80000002
HKEY_USERS = &H80000003
End Enum
'
Private Enum eHKEYError
ERROR_SUCCESS = 0
ERROR_MORE_DATA = 234&
ERROR_NO_MORE_ITEMS = 259&
End Enum
'
'Los tipos de datos posibles
Private Enum eHKEYDataType
REG_NONE = 0&
REG_SZ = 1&
REG_BINARY = 3
REG_DWORD = 4
'32-bit number
End Enum
'
Private Enum eREGSAM
KEY_QUERY_VALUE = &H1
End Enum
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Declare Function RegQueryInfoKey Lib "advapi32.dll" Alias
"RegQueryInfoKeyA" _
_
sKey
'
'
'
sValue
'
hKey
'
bAsString
'Devuelve:
'
'
Dim ret As Long
Dim hKey2 As Long
Dim rDT As eHKEYDataType
Dim retDT As eHKEYDataType
Dim lSize As Long
Dim sData As String
Dim aData() As Byte
Dim lDWord As Long
Dim i As Long
Dim sTmp As String
'Nos aseguramos que hKey tenga el valor correcto
Select Case hKey
Case HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
HKEY_USERS
'nada que hacer, todo correcto
Case Else
'Asignamos el valor por defecto
hKey = HKEY_CLASSES_ROOT
End Select
hKey = ParseKey(sKey, hKey)
End If
End If
'Cerrar la clave abierta
RegCloseKey hKey2
End If
'Devolver el valor ledo
If retDT = REG_BINARY Then
If bAsString Then
'Al estilo de como se muestra con RegEdit
For i = 0 To UBound(aData) - 1
sTmp = sTmp & Hex$(aData(i)) & " "
Next
GetReg = sTmp
Else
GetReg = aData
End If
ElseIf retDT = REG_DWORD Then
If bAsString Then
'Al estilo de como se muestra con RegEdit
GetReg = "0x" & Format$(Hex$(lDWord), "00000000") & " ("
& lDWord & ")"
Else
GetReg = lDWord
End If
ElseIf retDT = REG_SZ Then
GetReg = sData
End If
End Function
Private Function ParseKey(sKey As String, Optional ByVal hKey As
eHKEY = HKEY_CURRENT_USER) As eHKEY
Dim i As Long
Dim sRootKey As String
'Comprobar si se indica la clave principal en sKey
i = InStr(sKey, "HKEY_")
If i Then
i = InStr(sKey, "\")
If i Then
sRootKey = Left$(sKey, i - 1)
sKey = Mid$(sKey, i + 1)
Else
sRootKey = sKey
sKey = ""
End If
If Len(sRootKey) Then
Select Case sRootKey
Case "HKEY_CLASSES_ROOT"
hKey = HKEY_CLASSES_ROOT
Case "HKEY_CURRENT_USER"
hKey = HKEY_CURRENT_USER
Case "HKEY_LOCAL_MACHINE"
hKey = HKEY_LOCAL_MACHINE
Case "HKEY_USERS"
hKey = HKEY_USERS
Case Else
hKey = HKEY_CLASSES_ROOT
End Select
End If
End If
ParseKey = hKey
End Function
Private Function EnumValueString(ByVal hKey As Long, ByVal dwIndex
As Long, _
lpValueName As String, lpcbValueName As Long, _
lpReserved As Long, lpType As Long, lpData As String, _
lpcbData As Long) As Long
EnumValueString = RegEnumValue(hKey, dwIndex, _
lpValueName, lpcbValueName, _
lpReserved, lpType, ByVal lpData, _
lpcbData)
End Function
Private Function EnumValue(ByVal hKey As Long, ByVal dwIndex As
Long, _
lpValueName As String, lpcbValueName As Long, _
lpReserved As Long, lpType As Long, lpData As Byte, _
lpcbData As Long) As Long
EnumValue = RegEnumValue(hKey, dwIndex, _
lpValueName, lpcbValueName, _
lpReserved, lpType, lpData, _
lpcbData)
End Function
'buf = "WindowsDir"
'colShellFoldersKey.Add buf, buf
'colShellFolders.Add "Windows", buf
'
'Para el directorio de System
'buf = "SystemDir"
'colShellFoldersKey.Add buf, buf
'colShellFolders.Add "System", buf
'
'==============================================================
For iCount = 0 To 1
'Enumerar el contenido de Shell Folders
If iCount = 0 Then
hKey = HKEY_USERS
Entry =
".Default\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell
Folders"
Else
hKey = HKEY_LOCAL_MACHINE
Entry = "Software\Microsoft\Windows\CurrentVersion"
End If
If RegOpenKeyEx(hKey, Entry, 0&, KEY_QUERY_VALUE, phkResult)
= ERROR_SUCCESS Then
lRet = QueryInfoKey(phkResult, maxBufLen)
L = -1
Do
L = L + 1
buf = String$(maxBufLen + 1, 0)
buflen = Len(buf)
'Para enumerar los valores y las claves
retDT, 0&, i)
Entry, buf
Else
Else
GetFolder = GetReg(sKey, sData)
End If
If Err Then
GetFolder = ""
End If
Err = 0
On Local Error GoTo 0
End Function
11.- Una API para saber los directorios del Sistema (20/Ago)
Siguiendo con la racha de los ltimos das de saber dnde estn los
distintos directorios del sistema, no slo Windows ni el System, que esos ya
tienen sus correspondientes funciones del API, sino para otros directorios
como el de los Archivos de programa, el Men de Inicio, el Escritorio, los
Cookies, etc.
Esta funcin no la he visto documentada para usarla en Visual Basic, pero
gracias a Francisco Charte que respondiendo en las news dio su direccin de
internet (La Torre de Babel) en la que haba un pequeo ejemplo para
Delphi, pues me "calent" y la convert en VB y aqu est, con un pequeo
ejemplo en el que se dan todas las constantes para poder usarla con esta
funcin para obtener los distintos directorios.
En este "trozo" de espacio de esta pgina slo dar algunas de las
constantes y la forma general de obtener los directorios, pero en el ejemplo
estn todas las constantes que he encontrado en la documentacin de
Microsoft.
Si quieres los listados con el form de ejemplo, pulsa este link.
(SHGetSFP.zip 2.65 KB)
'La longitud mxima de un directorio puede ser 260
Const MAX_PATH = 260
'Algunas de las constantes
Const CSIDL_DESKTOP = 0
Const CSIDL_PROGRAMS = 2
Const CSIDL_STARTUP = 7
Const CSIDL_STARTMENU = 11
'La declaracin del API:
'
Dim oQR As cQueryReg
Set oQR = New cQueryReg
Label1.Caption = oQR.GetFolder("ProgramFilesDir")
Que lo disfrutes!
'
'
'
'
'
'
'
'
'
'
'
'Preparing to start the process with redirected
handles
'
start.hStdOutput = hWritePipe1
'
start.hStdError = hWritePipe2
'
start.hStdInput = hReadPipe3
'
'
'
ReadFile(hReadPipe1, mybuff1, 100, bytesread, ByVal
0&)
'
'
'
ReadFile(hReadPipe2, mybuff2, 100, bytesread, ByVal
0&)
'
'
'
WriteFile(hWritePipe3, mybuff3, 100, byteswritten,
ByVal 0&)
'
Private Declare Function CreatePipe Lib "kernel32" ( _
phReadPipe As Long, _
phWritePipe As Long, _
lpPipeAttributes As Any, _
ByVal nSize As Long) As Long
Private Declare Function ReadFile Lib "kernel32" ( _
ByVal hFile As Long, _
ByVal lpBuffer As String, _
ByVal nNumberOfBytesToRead As Long, _
lpNumberOfBytesRead As Long, _
ByVal lpOverlapped As Any) As Long
pero no en la prctica
'
mybuff = String(10 * 1024, Chr$(65))
sa.nLength = Len(sa)
sa.bInheritHandle = 1&
sa.lpSecurityDescriptor = 0&
ret = CreatePipe(hReadPipe, hWritePipe, sa, 0)
If ret = 0 Then
'===Error
ExecCmd = "Error: CreatePipe failed. " &
Err.LastDllError
Exit Function
End If
start.cb = Len(start)
start.hStdOutput = hWritePipe
start.dwFlags = STARTF_USESTDHANDLES +
STARTF_USESHOWWINDOW
start.wShowWindow = SW_SHOWMINNOACTIVE
' Start the shelled application:
ret& = CreateProcessA(0&, CmdLine$, sa, sa, 1&, _
NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
If ret <> 1 Then
'===Error
sReturnStr = "Error: CreateProcess failed. " &
Err.LastDllError
End If
' Wait for the shelled application to finish:
ret = WaitForSingleObject(proc.hProcess, INFINITE)
'En el original, slo leian 100 caracteres
bSuccess = ReadFile(hReadPipe, mybuff, Len(mybuff),
bytesread, 0&)
If bSuccess = 1 Then
sReturnStr = Left(mybuff, bytesread)
Else
'===Error
sReturnStr = "Error: ReadFile failed. " &
Err.LastDllError
End If
ret = CloseHandle(proc.hProcess)
ret = CloseHandle(proc.hThread)
ret = CloseHandle(hReadPipe)
ret = CloseHandle(hWritePipe)
ExecCmd = sReturnStr
End Function
Private Sub Command1_Click()
Text1 = ExecCmdPipe(Command$)
End Sub
Private Sub Form_Load()
'
Text1 = ""
'
Show
'Asigna al TextBox lo que se introduzca en la lnea
de comandos
Text1 = ExecCmdPipe(Command$)
Text1.Refresh
End Sub
'
sKey
informacin
'
'Devolver True si todo va bien
'
'Revisado para Array y buen funcionamiento (espero)
(14/Oct/98)
'--------------------------------------------------------------------Dim dwIndex
As Long
Dim ret
As Long
Dim hKey2
As Long
Dim hKey
As Long
Dim lpName
As String
Dim lpftLastWriteTime
As FILETIME
Dim colItems
As Long
Dim lSize
As Long
Dim SubKeysNum
As Long
Dim MaxSubKeyLen
As Long
Dim numValues
As Long
Dim MaxValueNameLen
As Long
Dim MaxDataLen
As Long
colItems = 0
ReDim colKeys(0)
'Si se pasa una cadena en sKey, esta funcin la convierte
'en un valor vlido para la clave principal
hKey = ParseKey(sKey, hKey)
'Abrir la clave indicada
ret = RegOpenKeyEx(hKey, sKey, 0&, KEY_ENUMERATE_SUB_KEYS,
hKey2)
EnumKeys = True
'Si todo va bien (se ha podido abrir la clave)
If ret = ERROR_SUCCESS Then
'Obtener informacin de la clave y datos, devolver:
'SubKeysNum
Nmero de subclaves
'MaxSubKeyLen
'numValues
'MaxValueNameLen
'MaxDataLen
'
Public Function EnumValues(ByRef colKeys() As String, ByVal sKey As
String) As Boolean
'--------------------------------------------------------------------'Enumera todos los valores de la clave indicada en sKey
(12/Oct/98)
'
'Parmetros:
'
colKeys()
halladas
'
a
'
tener
'
informacin.
'
'
sKey
informacin
'
'Devolver True si todo va bien
'
'Revisado para Array y buen funcionamiento (espero)
(14/Oct/98)
'--------------------------------------------------------------------'Para recuperar la informacin de colKeys(), hacer esto:
'
'If .EnumValues(colKeys(), sKey) Then
'
'
'colKeys(i)
ser el nombre
'
'colKeys(i + 1)
'
Next
'End If
'--------------------------------------------------------------------'
Dim dwIndex
As Long
Dim ret
As Long
Dim hKey2
As Long
Dim hKey
As Long
Dim lpName
As String
Dim lpftLastWriteTime
As FILETIME
Dim retDT
As eHKEYDataType
Dim lSize
As Long
Dim sData
As String
Dim aData()
As Byte
Dim lDWord
As Long
Dim i
As Long
Dim colItems
As Long
Dim SubKeysNum
As Long
Dim MaxSubKeyLen
As Long
Dim numValues
As Long
Dim MaxValueNameLen
As Long
Dim MaxDataLen
As Long
Nmero de subclaves
'MaxSubKeyLen
'numValues
'MaxValueNameLen
'MaxDataLen
'Datos binarios
Case Else
'Tratarlo como Binary
If lSize Then
ReDim aData(lSize)
'Leer los datos binarios
ret = RegEnumValue(hKey2, dwIndex, lpName,
Len(lpName), 0&, retDT, aData(0), lSize)
lpName = RTrimZero(lpName)
'Al estilo de como se muestra con RegEdit
sData = ""
For i = 0 To UBound(aData) - 1
sData = sData & Format$(Hex$(aData(i)),
"00") & " "
Next
ReDim Preserve colKeys(colItems + 2)
colKeys(colItems + 1) = lpName
colKeys(colItems + 2) = sData
colItems = colItems + 2
End If
End Select
End If
Next
Else
EnumValues = False
End If
'Cerrar la clave abierta
ret = CloseKey(hKey2)
End Function
Ahora veamos el cdigo que se usa al iniciarse el formulario, el cual llena el combo con las
diferentes conexiones, obtenidas de la siguiente clave del registro:
HKEY_USERS\.Default\RemoteAccess\Addresses
'
'------------------------------------------------------------------------'Ejemplo para conectarse usando Acceso Telefnico a Redes
(09/Oct/98)
'
(13/Oct/98)
'
'Guillermo 'guille' Som, 1998
'------------------------------------------------------------------------Option Explicit
Private m_QR As cQueryReg
'
'------------------------------------------------------------------------'tEnumReg
(14/Oct/98)
'Prueba para usar la enumeracin de claves y valores del registro
'
'Guillermo 'guille' Som, 1998
'------------------------------------------------------------------------Option Explicit
Private m_QR As cQueryReg
.SortKey = 0
End With
'Esto enumera las sub-claves que hay en esta clave
sKey =
"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion"
If m_QR.EnumKeys(colKeys(), sKey) Then
For i = 1 To UBound(colKeys)
cboKeys.AddItem colKeys(i)
Next
cboKeys.ListIndex = 0
End If
End Sub
If cboKeys.ListCount Then
cboKeys.ListIndex = 0
End If
End If
End If
End Sub
'
Option Explicit
Private m_QR As cQueryReg
registro
Private colKeys() As String
nombres/contenidos
(06/Dic/98)
hWnd As Long
message As Long
wParam As Long
lParam As Long
time As Long
pt As POINTAPI
End Type 'MSG
Private Const PM_REMOVE = &H1
'funciones para recibir los mensajes de windows
Private Declare Function PeekMessage Lib "user32" Alias
"PeekMessageA" _
(lpMsg As Msg, ByVal hWnd As Long, ByVal wMsgFilterMin As
Long, _
ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As
Long
Private Declare Function WaitMessage Lib "user32" () As Long
Private Termina As Boolean
'Else
'
'End If
'Hay que mostrar el form
'sino entrar en el bucle de espera de mensajes sin mostrarse
Show
ProcesaMensajes
End Sub
Private Sub Form_Unload(Cancel As Integer)
Termina = True
'Quitar la Hot-Key registrada
Call UnregisterHotKey(Me.hWnd, &HBFFF&)
End Sub
Pues eso... que intentando mejorar el acceso a los ficheros INIs me "entretuve" en
leer la ayuda del API para 32 bits y vi un par de funciones que... al menos en
teora, slo servan para el Windows NT... y mira t por dnde... tambin sirven
para el Windows 98... no las he probado para el Windows 95, as que si lo haces y
funciona, me lo cuentas... vale? Gracias.
El cdigo:
El cdigo que te voy a mostrar ahora tiene dos funciones que ya habrs visto en
algn otro sitio de mis pginas, son las funciones para leer y escribir en ficheros
INIs; pero ahora te voy a dar otras tres que de seguro te interesarn:
Borrar claves o secciones de un fichero INI.
Leer todos las claves y valores de una seccin.
Leer todas las secciones.
Decirte que de esta ltima, no viene la declaracin del API en el fichero que se
incluye con el VB, as que toma nota, porque es interesante.
Las declaraciones de las funciones del API
'
'--- Declaraciones para leer ficheros INI --'
' Leer todas las secciones de un fichero INI, esto seguramente no
funciona en Win95
' *** Esta funcin no estaba en las declaraciones del API que se
incluye con el VB ***
Private Declare Function GetPrivateProfileSectionNames Lib
"kernel32" Alias "GetPrivateProfileSectionNamesA" _
(ByVal lpszReturnBuffer As String, ByVal nSize As Long, _
ByVal lpFileName As String) As Long
' Leer una seccin completa
Private Declare Function GetPrivateProfileSection Lib "kernel32"
Alias "GetPrivateProfileSectionA" _
(ByVal lpAppName As String, ByVal lpReturnedString As String, _
ByVal nSize As Long, ByVal lpFileName As String) As Long
' Leer una clave de un fichero INI
Private Declare Function GetPrivateProfileString Lib "kernel32"
Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal lpKeyName As Any, _
ByVal lpDefault As String, ByVal lpReturnedString As String, _
ByVal nSize As Long, ByVal lpFileName As String) As Long
' Escribir una clave de un fichero INI (tambin para borrar claves y
secciones)
String
'
'lpAppName:
'lpKeyName:
Clave
'lpDefault:
la clave.
'
Dim LTmp As Long
Dim sRetVal As String
sRetVal = String$(255, 0)
LTmp = GetPrivateProfileString(lpAppName, lpKeyName, lpDefault,
sRetVal, Len(sRetVal), lpFileName)
If LTmp = 0 Then
IniGet = lpDefault
Else
IniGet = Left(sRetVal, LTmp)
End If
End Function
lpFileName
'
lpAppName
' Devuelve:
'
'
'
'
sClave = tContenidos(i)
'
sValor = tContenidos(i+1)
'
Next
'
Dim tContenidos As Collection
Dim nSize As Long
Dim i As Long
Dim j As Long
Dim sTmp As String
Dim sClave As String
Dim sValor As String
If i Then
sTmp = LTrim$(Left$(sBuffer, i - 1))
If Len(sTmp) Then
' Comprobar si tiene el signo igual
j = InStr(sTmp, "=")
If j Then
sClave = Left$(sTmp, j - 1)
sValor = LTrim$(Mid$(sTmp, j + 1))
' Asignar la clave y el valor
tContenidos.Add sClave
tContenidos.Add sValor
End If
End If
sBuffer = Mid$(sBuffer, i + 1)
End If
Loop While i
' Por si an queda algo...
If Len(sBuffer) Then
j = InStr(sBuffer, "=")
If j Then
sClave = Left$(sBuffer, j - 1)
sValor = LTrim$(Mid$(sBuffer, j + 1))
tContenidos.Add sClave
tContenidos.Add sValor
End If
End If
End If
Set IniGetSection = tContenidos
End Function
' Esta funcin devolver una coleccin con todas las secciones
del fichero
' Parmetros de entrada:
'
lpFileName
' Devuelve:
'
'
Dim tContenidos As Collection
Dim nSize As Long
Dim i As Long
Dim sTmp As String
' El tamao mximo para Windows 95
sBuffer = String$(32767, Chr$(0))
' Esta funcin del API no est definida en el fichero TXT
nSize = GetPrivateProfileSectionNames(sBuffer, Len(sBuffer),
lpFileName)
If nSize Then
' Crear una coleccin del tipo cParrafos que es una
coleccin
' con elementos del tipo cContenido
Set tContenidos = New Collection
' Cortar la cadena al nmero de caracteres devueltos
sBuffer = Left$(sBuffer, nSize)
' Quitar los vbNullChar extras del final
i = InStr(sBuffer, vbNullChar & vbNullChar)
If i Then
sBuffer = Left$(sBuffer, i - 1)
End If
' Cada una de las entradas estar separada por un Chr$(0)
Do
i = InStr(sBuffer, Chr$(0))
If i Then
sTmp = LTrim$(Left$(sBuffer, i - 1))
If Len(sTmp) Then
tContenidos.Add sTmp
End If
sBuffer = Mid$(sBuffer, i + 1)
End If
Loop While i
If Len(sBuffer) Then
tContenidos.Add sBuffer
End If
End If
Set IniGetSections = tContenidos
End Function
Bueno... eso es todo lo que se necesita para usar esas funciones, en este caso, si
te fijas, las funciones son Private, ya que las he "modificado" para usar en un Form
directamente, pero si las quieres "encapsular" en una clase o en un mdulo BAS,
deberas cambiar las declaraciones a Public, pero no las de las funciones del API...
esas pueden (y deberan) seguir siendo Privadas.
Del cdigo para usar estas funciones slo te voy a ensear parte... el resto te lo
imaginas... que con un poco de imaginacin seguro que eres capaz de crear el
ejemplo para que funcione... je, je... no es mala "leche", es que as te esfuerzas
un poco... que os estoy acostumbrando a darlo todo hecho y eso no ayuda
demasiado a aprender...
Aqu estn los trozos del Form y una imagen de cmo queda en modo de diseo.
El form de prueba
'
' Leer todas las secciones del fichero indicado y guardarlas en el
cboSecciones
Aqu tienes una captura del form, en tiempo de diseo y el listado, creo que
no necesita ms comentarios... espero que te sea de utilidad.
Nota del 26/Mayo/2004:
La declaracin de fFlags del tipo SHFILEOPSTRUCT la he cambiado a Long
ya que fallaba en Windows XP. Usndola como Long tambin funciona en
Windows 98.
Tambin he aadido un zip con el cdigo y el ejecutable para VB6 SP5
(SHCopiar.zip 8.74 KB)
'----------------------------------------------------------------------------Option Explicit
' Variables para el programa de prueba
Private sFicOri As String
Private sFicDes As String
Private iFlags As Long
' Constantes para el orden de los chkOpciones
Private Enum eOpciones
cFOF_ALLOWUNDO
cFOF_FILESONLY
cFOF_MULTIDESTFILES
cFOF_NOCONFIRMATION
cFOF_NOCONFIRMMKDIR
cFOF_RENAMEONCOLLISION
cFOF_SILENT
cFOF_SIMPLEPROGRESS
End Enum
' Variables, constantes y declaraciones para el API
Private Type SHFILEOPSTRUCT
hWnd As Long
formulario
wFunc As Long
usar: FO_COPY, etc.
' Funcin a
pFrom As String
origen
' Fichero(s) de
pTo As String
destino
' Fichero(s) de
' fFlags
Long
'
'
aunque tambin funciona si se declara
como Long (al menos en W98)
'fFlags As Integer
' Opciones
fFlags As Long
fAnyOperationsAborted As Boolean
cancelado
hNameMappings As Long
lpszProgressTitle As String
FOF_SIMPLEPROGRESS
' Si se ha
'
' Slo si se usa
End Type
' Constantes para FileOperation
Private Enum eFO
FO_COPY = &H2&
' Copiar
FO_DELETE = &H3&
' Borrar
FO_MOVE = &H1&
' Mover
FO_RENAME = &H4&
' Renombrar
'
FOF_MULTIDESTFILES = &H1&
archivos de destino
' Multiples
FOF_CONFIRMMOUSE = &H2&
implementada
' No est
FOF_SILENT = &H4&
progreso
' No mostrar el
FOF_RENAMEONCOLLISION = &H8&
' Cambiar el
nombre si el archivo de destino ya existe
FOF_NOCONFIRMATION = &H10&
confirmacin
' No pedir
FOF_WANTMAPPINGHANDLE = &H20&
SHFILEOPSTRUCT.hNameMappings
'// Fill in
'// Must be
' Permitir
FOF_FILESONLY = &H80&
' Si se
especifica *.*, hacerlo slo con archivos
FOF_SIMPLEPROGRESS = &H100&
nombres de los archivos
FOF_NOCONFIRMMKDIR = &H200&
la creacin de directorios
' No confirmar
FOF_NOERRORUI = &H400&
error UI
FOF_NOCOPYSECURITYATTRIBS = &H800&
NT file Security Attributes
End Enum
Private Declare Function SHFileOperation Lib
"shell32.dll" Alias "SHFileOperationA" _
(lpFileOp As SHFILEOPSTRUCT) As Long
Private Sub cmdCopiar_Click()
' Copiar
Dim SHFileOp As SHFILEOPSTRUCT
End Sub
Private Sub AsignarFlags()
' Ajusta el valor del flag, segn las opciones
seleccionadas
iFlags = 0
If chkOpciones(cFOF_ALLOWUNDO) Then _
iFlags = iFlags + FOF_ALLOWUNDO
If chkOpciones(cFOF_FILESONLY) Then _
iFlags = iFlags + FOF_FILESONLY
If chkOpciones(cFOF_MULTIDESTFILES) Then _
iFlags = iFlags + FOF_MULTIDESTFILES
If chkOpciones(cFOF_NOCONFIRMATION) Then _
iFlags = iFlags + FOF_NOCONFIRMATION
If chkOpciones(cFOF_NOCONFIRMMKDIR) Then _
iFlags = iFlags + FOF_NOCONFIRMMKDIR
If chkOpciones(cFOF_RENAMEONCOLLISION) Then _
iFlags = iFlags + FOF_RENAMEONCOLLISION
If chkOpciones(cFOF_SILENT) Then _
iFlags = iFlags + FOF_SILENT
If chkOpciones(cFOF_SIMPLEPROGRESS) Then _
iFlags = iFlags + FOF_SIMPLEPROGRESS
End Sub
22.- Seleccionar carpetas e incluso ficheros, usando SHBrowseForFolder
(13/May)
Otra funcin del API de Windows que puede darle un "look" ms apropiado
a nuestras aplicaciones:
Mostrar el cuadro de dilogo de seleccionar carpetas (o directorios) que usa
el propio Windows.
La funcin del API que se encarga de hacerlo es: SHBrowseForFolder,
aunque para poder sacarle el jugo nos tendremos que apoyar en otras
funciones, una de ellas no es "redistribuible" y debe estar ya instalada en el
sistema, de hecho todas las DLLs del API de Windows ya deben estar
instaladas en el sistema... por tanto slo podremos usar estas funciones si
previamente estn instaladas... el que avisa.
Dejemos las partes "legalistas" a un lado y vamos a centrarnos en lo que
interesa: saber cmo usarla.
Esta funcin no es tan "intuitiva" como el resto y se basa, como otras
muchas de la librera Shell, en unos parmetros que se pasan en forma de
datos asignados a un tipo definido, en este caso es: Browseinfo.
En este tipo definido (UDT), asignaremos lo que queremos que ese cuadro
de dilogo nos muestre, por ejemplo se le puede decir que tambin nos
permita seleccionar ficheros, adems de carpetas, el ttulo que queramos
que tenga, etc.
Lo que es un poco ms complicado de indicarle es el directorio por el que
debe empezar a mostrar, (por defecto empieza en el Escritorio); para
indicarle el directorio por defecto hay que recurrir a la subclasificacin, por
suerte, desde la versin 5.0 del Visual Basic es algo ms fcil, ya que
disponemos de AddressOf, el problema es que la subclasificacin se hace
asignando a uno de los parmetros del tipo definido la direccin de la
funcin que se encargar de procesar esos mensajes... por desgracia
AddressOf no devuelve ningn valor, y lo que necesitamos es poder asignar
a una variable la direccin de memoria de una funcin creada en Visual
Basic... Cmo lo solucionaremos? Creando una funcin que devuelva ese
valor... ya vers el cdigo y lo comprenders mejor.
Aqu tienes el cdigo y una "foto" del formulario de prueba en pleno
funcionamiento.
Como puedes comprobar, puedes especificar si quieres empezar a
"browsear" por una carpeta determinada y tambin si quieres seleccionar
ficheros, adems de poder seleccionar carpetas.
Nos vemos.
Guillermo
P.S.
Por suerte, con el Visual Basic 6.0 se incluyen los CDs de la MSDN Library
de Microsoft, que es de dnde he sacado parte del cdigo que he usado... el
problema es que los artculos estn en ingls... pero algo es algo...
Espero que te sea de utilidad...
'
'///////////////////////////////////////////////////////
///////////////////////
'/////
BAS
'///////////////////////////////////////////////////////
///////////////////////
'
'----------------------------------------------------------------------------' Mdulo con las declaraciones y funciones para
BrowseForFolder
(12/May/99)
'
As Long
' hWnd
pIDLRoot
As Long
Especifica el pID de la carpeta inicial
'
pszDisplayName
del item seleccionado
As String
' Nombre
lpszTitle
a mostrar encima del rbol
As String
' Ttulo
ulFlags
As Long
'
lpfnCallback
Funcin CallBack
As Long
'
lParam
As Long
'
Informacin extra a pasar a la funcin Callback
iImage
As Long
'
End Type
'
'// Browsing for directory.
Public Const BIF_RETURNONLYFSDIRS = &H1&
finding a folder to start document searching
'// For
'// For
'//
'
Public Const BIF_BROWSEFORCOMPUTER = &H1000&
Browsing for Computers.
'//
'//
'//
'
'// message from browser
Public Const BFFM_INITIALIZED = 1
Public Const BFFM_SELCHANGED = 2
Public Const BFFM_VALIDATEFAILED = 3
lParam:szPath ret:1(cont),0(EndDialog)
'//
'//
'
'// messages to browser
Public Const BFFM_SETSTATUSTEXT = (WM_USER + 100)
Public Const BFFM_ENABLEOK = (WM_USER + 101)
Public Const BFFM_SETSELECTION = (WM_USER + 102)
'Public Const BFFM_SETSELECTIONW = (WM_USER + 103&)
'Public Const BFFM_SETSTATUSTEXTW = (WM_USER + 104&)
'
Private Declare Function SHBrowseForFolder Lib
"shell32.dll" _
(lpbi As BrowseInfo) As Long
'
Private Declare Sub CoTaskMemFree Lib "OLE32.DLL" _
(ByVal hMem As Long)
'
Private Declare Function SHGetPathFromIDList Lib
"shell32.dll" _
(ByVal pidList As Long, ByVal lpBuffer As
String) As Long
'
Private Declare Function SendMessage Lib "user32.dll"
Alias "SendMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
ser TRUE
si se especifica un path.
'
Case BFFM_SELCHANGED
szDir = String$(MAX_PATH, 0)
' Notifica a la ventana del directorio
actualmente seleccionado,
' (al menos en teora, ya que no lo hace...)
If SHGetPathFromIDList(lParam, szDir) Then
'Debug.Print szDir
Call SendMessage(hWndOwner,
BFFM_SETSTATUSTEXT, 0&, ByVal szDir)
End If
Call CoTaskMemFree(lParam)
End Select
Err = 0
BrowseFolderCallbackProc = 0
'----------------------------------------------------------------------------' Este es el cdigo de C en el que est basada esta
funcin Callback
' Cdigo obtenido de la MSDN Library de Microsoft:
' HOWTO: Browse for Folders from the Current Directory
' Article ID: Q179378
'
'
TCHAR szDir[MAX_PATH];
'
'
'
switch(uMsg) {
case BFFM_INITIALIZED: {
'
if
GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR),
'
szDir)) {
'
passing a path.
'
passing a pidl.
'
SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)szDir);
'
'
break;
'
'
case BFFM_SELCHANGED: {
'
// Set the status window to the
currently selected path.
'
lp ,szDir)) {
if (SHGetPathFromIDList((LPITEMIDLIST)
'
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
'
'
break;
'
'
default:
'
break;
'
'
return 0;
'----------------------------------------------------------------------------End Function
El hWnd de la ventana
'
El ttulo a mostrar
'
'
En lFlags se puede especificar lo que se podr
seleccionar:
'
BIF_BROWSEINCLUDEFILES, etc.
'
'
Dim iNull As Integer
Dim lpIDList As Long
Dim lResult As Long
Dim sPath As String
Dim udtBI As BrowseInfo
On Local Error Resume Next
With udtBI
.hWndOwner = hWndOwner
' Ttulo a mostrar encima del rbol de seleccin
.lpszTitle = sPrompt & vbNullChar
' Que es lo que debe devolver esta funcin
.ulFlags = lFlags
'.ulFlags = lFlags Or BIF_RETURNONLYFSDIRS
'
' Si se especifica el directorio por el que se
empezar...
If Len(sInitDir) Then
' Asignar la variable que contendr el
directorio de inicio
sFolderIni = sInitDir
' Indicar la funcin Callback a usar.
' Como hay que asignar esa direccin a una
variable,
' se usa una funcin "intermedia" que
devuelve el valor
' del parmetro pasado... es decir: la
direccin de la funcin!
.lpfnCallback = rtnAddressOf(AddressOf
BrowseFolderCallbackProc)
End If
End With
Err = 0
On Local Error GoTo 0
' Mostramos el cuadro de dilogo
lpIDList = SHBrowseForFolder(udtBI)
'
If lpIDList Then
' Si se ha seleccionado un directorio...
'
' Obtener el path
sPath = String$(MAX_PATH, 0)
lResult = SHGetPathFromIDList(lpIDList, sPath)
Call CoTaskMemFree(lpIDList)
' Quitar los caracteres nulos del final
iNull = InStr(sPath, vbNullChar)
If iNull Then
sPath = Left$(sPath, iNull - 1)
End If
Else
' Si se ha pulsado en cancelar...
'
' Devolver una cadena vaca y asignar un error
sPath = ""
With Err
.Source = "MBrowseFolder::BrowseForFolder"
.Number = 32755
.Description = "Cancelada la operacin de
BrowseForFolder"
End With
End If
BrowseForFolder = sPath
End Function
'///////////////////////////////////////////////////////
///////////////////////
' Este cdigo insertalo en un formulario que tenga un
botn llamado cmdSelDir,
End If
If Err = 0 Then
Text1 = sDir
Else
MsgBox "Se ha cancelado la operacin, el error
devuelto es:" & vbCrLf & _
"Source: " & Err.Source & vbCrLf &
"Description: " & Err.Description
End If
' Pero si es conveniente poner de nuevo el valor a
cero
Err = 0
End Sub
Long, _
ByVal lParam As
Long, _
ByVal pData As
Long) As Long
ser TRUE
si se especifica un
'
path.
pIDL.
Call SendMessage(hWndOwner,
BFFM_SETSELECTION, 1&, ByVal szDir)
End If
' Si se ha especificado el ttulo de la ventana
If Len(sBFFCaption) Then
' Cambiar el ttulo de la ventana.
' Aunque parezca que se cambia el ttulo de
la ventana "propietaria",
seleccin.
El hWnd de la ventana
'
'
'
En lFlags se puede especificar lo que se podr
seleccionar:
'
BIF_BROWSEINCLUDEFILES, etc.
'
'
El Caption de la ventana
'
Dim iNull As Integer
Dim lpIDList As Long
Dim lResult As Long
Dim sPath As String
Dim udtBI As BrowseInfo
On Local Error Resume Next
With udtBI
.hWndOwner = hWndOwner
' Ttulo a mostrar encima del rbol de seleccin
.lpszTitle = sPrompt & vbNullChar
' Que es lo que debe devolver esta funcin
.ulFlags = lFlags
'
' Asignar el caption de la ventana
sBFFCaption = sCaption
'
' Asignar la variable que contendr el
directorio de inicio
sFolderIni = sInitDir
'
' Indicar la funcin Callback a usar.
'
Nota:
cambiar el caption
'
y especificar el directorio de
inicio.
'
' Como hay que asignar esa direccin a una
variable,
' se usa una funcin "intermedia" que devuelve
el valor
End If
BrowseForFolder = sPath
End Function
Err = 0
If Check1 Then
sDir = BrowseForFolder(Me.hWnd, "Seleccionar
Directorio empezando en " & Text1, Text1, _
lFlags, "Ttulo de la ventana")
Else
sDir = BrowseForFolder(Me.hWnd, "Seleccionar
Directorio", , _
lFlags, "Ttulo de la ventana")
End If
23.- cQueryReg: Revisin de la clase para manejar el registro del sistema
(12/Jun/99)
Ya he probado esta clase con el Windows NT (realmente con el Windows
2000 Professional Beta 3) y aqu estn los cambios de los "apaillos" que le
he tenido que hacer... espero que funcione bien en los dems NTs... ya me
contars si no es as... aunque preferira esos comentarios con las
soluciones... je, je...
No te voy a explicar mucho... slo pondr el cdigo y el link para los
ejemplos, que sern casi los mismos que en las revisiones anteriores... Los
fallillos que he encontrado era de que los parmetros no eran los correctos,
as que he intentado solucionarlo, con algn que otro cuelgue de por
medio... pero al final he conseguido que funcione...
Otra de las cosillas que ahora contempla es que acepta y "casi" entiende,
dos nuevos tipos de datos del registro:
REG_EXPAND_SZ y REG_MULTI_SZ.
El primero, son cadenas con referencias de variables del entorno, por ahora
slo se leen, pero no se interpretan esas variables del entorno... eso puede
que en otra revisin.
El segundo es un tipo especial de cadenas, realmente mltiples cadenas...
'
'----------------------------------------------------------------------------' cQueryReg
(13/Ago/98)
' Clase para obtener valores del Registro del Sistema
'
' Revisin 0.01 (18/Ago/98) Funciones de crear/borrar
claves/valores
' Revisin 0.02 (12/Oct/98) Nueva funcin para
enumeracin de claves
' Revisin 0.03 (15/Oct/98) Importar/Exportar claves del
registro
'
(slo exportar...)
'
de usarlas.
no se ha cambiado la forma
'
' Revisin 0.10 (12/Jun/99) Probado en Windows 2000
Professional Beta 3
'
bien...
'
' La informacin para crear las funciones estn tomadas
de ejemplos
' y valores obtenidos en el cdigo del Setup1.vbp
' y de artculos incluidos en los CDs del MSDN Library.
'
' De algn sitio tena que sacar la
informacin... !!!
'
' Guillermo 'guille' Som, 1998-99
<mensaje@elguille.info>
'
'----------------------------------------------------------------------------'
Mtodo
Descripcin
'
------
-----------
'
AsociarExt
programa
'
Tambin sirve para aadir comandos a
extensiones existentes
'
CloseKey
Cierra la clave abierta usando el
handle pasado como parmetro
'
DeleteKey
especificado
'
DeleteKeyNT
Borra la clave especificada y sus
subclaves y valores, para usar con Windows NT y Windows
98
'
DeleteKeyWin95 En Windows 95, borra la clave
especificada y sus subclaves y valores. En Windows NT y
Windows 98 no funcionar si la clave indicada tiene
subclaves.
'
DesasociarExt
del registro)
'
EnumKeys
Enumera todas las subclaves de la
clave indicada y las devuelve en un array de tipo String
que se pasa como parmetro.
'
EnumValues
Enumera todos los valores de la
clave indicada y las devuelve en un array de tipo String
que se pasa como parmetro.
'
GetFolder
Devuelve el path de la carpeta
"especial" del sistema.
'
El parmetro espera un nombre del
tipo de carpeta a obtener,
'
sistema
'
GetReg
Obtener un valor, de cualquier tipo,
de una entrada del registro
'
GetRegBinary
Obtener un valor binario de una
entrada del registro
'
GetRegDWord
Obtener un valor DWORD de una
entrada del registro
'
GetRegString
Obtener un valor cadena de una
entrada del registro
'
QueryRegBase
'
RegSaveKey
Guarda en un fichero el contenido de
una clave, las subclaves y datos.
'
El formato no es ASCII, es un
formato "propio" que se puede usar con la funcin
RegLoadKey (an no implementada)
'
RTrimZero
Chr$(0)
'
SetReg
la clave indicada.
'
ShellFolders
Devuelve una coleccin con los
Nombres de directorios del sistema
'
referencia.
'
'
paths
'
' Estas funciones simplemente llaman a la funcin del
API de windows, (el nombre de la funcin del API empieza
con Reg, salvo que se indique lo contrario)
'
EnumKeyEx
'
EnumValue
RegEnumValue, usarla para tipos
diferentes de String
'
EnumValueString RegEnumValue, usarla para tipos
String
'
OpenKeyEx
'
OpenKeyQuery
RegOpenKeyEx, abre una clave para
consultar informacin
'
QueryInfoKey
'
RegSetValue2
con cadenas.
'
Esta funcin asigna el valor por
defecto de la clave indicada.
'
"Default".
Es decir, el "Predeterminado" o
'=======================================================
=================
'=== NOTA: Las he dejado para poder ver cmo se usaran
segn el tipo ===
'=======================================================
=================
'----------------------------------------------------------------------------Option Explicit
Long
Long
HKEY_CURRENT_CONFIG = &H80000005
HKEY_DYN_DATA = &H80000006
'
HKEY_FIRST = HKEY_CLASSES_ROOT
HKEY_LAST = HKEY_DYN_DATA
End Enum
'
'
HKEY_CLASSES_ROOT es un duplicado de
HKEY_LOCAL_MACHINE\Software\Classes
'
HKEY_CURRENT_USER es un duplicado de HKEY_USERS\
[Usuario]
'
'
Public Enum eHKEYError
ERROR_SUCCESS = 0
error
ERROR_NONE = 0
"
"
'The configuration
registry...
'ERROR_BADDB = 1
corrupt
'database is
'1009&
'ERROR_BADKEY = 2
'key is invalid
'1010&
'Tambin declarada como:
ERROR_FILE_NOT_FOUND = 2&
cuando se abre
existe
'ERROR_CANTOPEN = 3
opened
'1011&
'ERROR_CANTREAD = 4
read
'1012&
'ERROR_CANTWRITE = 5
written
'1013&
'Tambin declarada como:
ERROR_ACCESS_DENIED = 5&
ERROR_OUTOFMEMORY = 6&
'
ERROR_INVALID_PARAMETER = 7&
'
'ERROR_ACCESS_DENIED = 8&
ERROR_INVALID_PARAMETERS = 87&
'
'
'
ERROR_MORE_DATA = 234&
available
'More data is
ERROR_NO_MORE_ITEMS = 259&
available
ERROR_BADKEY = 1010&
se intenta acceder
est abierta
'KEY_ALL_ACCESS = &H3F
'REG_OPTION_NON_VOLATILE = 0
End Enum
'
' Los tipos de datos posibles, algunos slo para Windows
NT
REG_SZ = 1&
string
REG_EXPAND_SZ = 2
string
variable references)
REG_BINARY = 3
REG_DWORD = 4
'32-bit number
'32-bit number
REG_LINK = 6
REG_MULTI_SZ = 7
strings
'Multiple Unicode
REG_RESOURCE_LIST = 8
resource map
REG_FULL_RESOURCE_DESCRIPTOR = 9
in the hardware description
'Resource list
REG_RESOURCE_REQUIREMENTS_LIST = 10
End Enum
' Standard rights, used later below
Const SYNCHRONIZE = &H100000
Const READ_CONTROL = &H20000
Const STANDARD_RIGHTS_ALL = &H1F0000
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const STANDARD_RIGHTS_EXECUTE = (READ_CONTROL)
Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
' Security Access Mask
Public Enum eREGSAM
'Permission to:
KEY_QUERY_VALUE = &H1
'
query subkey
KEY_SET_VALUE = &H2
'
KEY_CREATE_SUB_KEY = &H4
'
create subkeys
KEY_ENUMERATE_SUB_KEYS = &H8
subkeys
'
enumerate
KEY_NOTIFY = &H10
notification
'
for change
data
KEY_CREATE_LINK = &H20
symbolic link
'
create a
KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS,
'
KEY_NOTIFY access.
and
KEY_READ = ((STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE
Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY) And (Not
SYNCHRONIZE))
'KEY_WRITE Combination of:
'
access.
'
Private Declare Function RegDeleteKey Lib "advapi32.dll"
Alias "RegDeleteKeyA" _
Long
Long
'
'lpValueName:
' Pointer to a string containing the name of the value
to set.
' If a value with this name is not already present in
the key,
' the function adds it to the key.
' If lpValueName is NULL or an empty string, "", the
function sets
' the type and data for the key's unnamed or default
value.
'
'On Windows 95, the type of a key's default value is
always REG_SZ,
' so the dwType parameter must specify REG_SZ for an
unnamed value.
'On Windows 98, an unnamed value can be of any type.
'
Private Declare Function RegSetValueEx Lib
"advapi32.dll" Alias "RegSetValueExA" _
(ByVal hKey As Long, ByVal lpszValueName As String,
_
ByVal dwReserved As Long, ByVal fdwType As Long, _
lpbData As Any, ByVal cbData As Long) As Long
'
' Funciones del API para guardar y recuperar informacin
del registro.
'
'Private Type SECURITY_ATTRIBUTES
'
nLength As Long
'
lpSecurityDescriptor As Long
'
bInheritHandle As Long
'End Type
'
' RegSaveKey:
' El nombre guardado en Windows 95 slo permite nombres
cortos,
' si no se especifica el path se guardar en el
directorio del Windows.
' Adems se guardar con los atributos Hidden, Read-Only
y System
'
'
cbMaxSubKeyLen = cbMaxSubKeyLen + 1
+1 for the null terminator
'
'
Do
cbSubKeyLen = cbMaxSubKeyLen
cbSubKeyLen)
'
Call RegCloseKey(hKey)
lRet = RegDeleteKey(hParentKey, szKey)
'If Not lRet = ERROR_SUCCESS Then
'
Exit Sub
'End If
DeleteKeyNT = lRet
End Function
Public Function GetRegDWord(ByVal sKey As String,
Optional ByVal sValue As String = "", Optional ByVal
hKey As eHKEY = HKEY_CURRENT_USER, Optional ByVal
bAsString As Boolean = False) As Variant
' Obtener un valor DWORD de una entrada del registro
'
' Parmetros de entrada:
'
sKey
'
sValue
obtener
'
hKey
'
bAsString
RegEdit
' Devuelve:
'
'
Dim ret As Long
Dim hKey2 As Long
'
' Parmetros de entrada:
'
sKey
'
clave raiz
'
'
sValue
obtener
'
hKey
'
Si en sKey se incluye, no es
necesario especificarla
'
Nota: este valor se obvia si se
indica la raiz en sKey.
'
bAsString
de RegEdit
' Devuelve:
'
'
' Revisado para usarlo con Windows NT (Win2000 Pro
Beta 3)
(12/Jun/99)
'------------------------------------------------------------------------Dim lRet As Long
Dim hKey2 As Long
Dim rDT As eHKEYDataType
Dim retDT As eHKEYDataType
Dim lSize As Long
Dim sData As String
Dim aData() As Byte
Dim lDWord As Long
Dim i As Long
Dim sTmp As String
hKey = ParseKey(sKey, hKey)
' Valores por defecto
ReDim aData(0)
lDWord = 0
sData = ""
' Abrir la clave indicada
GetReg = lDWord
End If
Case REG_EXPAND_SZ, REG_SZ
GetReg = sData
Case REG_MULTI_SZ
' Mltiples cadenas, separadas por Chr$(0)
(12/Jun/99)
' La cadena termina en el ltimo Chr$(0)
'
'
'
sData = Left$(sData, i - 1)
'
Exit For
'
End If
'
Next
'
'
For i = 1 To Len(sData)
'
'
'
'
End If
Next
GetReg = RTrimZero(sData, True)
Case Else ' REG_BINARY
If bAsString Then
' Al estilo de como se muestra con RegEdit
For i = 0 To UBound(aData) - 1
'sTmp = sTmp & Hex$(aData(i)) & " "
' Los nmeros formateados a dos cifras
(12/Oct/98)
GetReg = sTmp
Else
GetReg = aData
End If
End Select
End Function
Public Function GetRegBinary(ByVal sKey As String,
Optional ByVal sValue As String = "", Optional ByVal
sKey
'
sValue
obtener
'
hKey
'
bAsString
de RegEdit
' Devuelve:
'
'
Dim ret As Long
Dim hKey2 As Long
Dim rDT As eHKEYDataType
Dim lSize As Long
Dim aData() As Byte
Dim i As Long
Dim sTmp As String
hKey = ParseKey(sKey, hKey)
ReDim aData(0)
' Abrir la clave indicada
'ret = RegOpenKeyEx(hKey, sKey, 0&, KEY_QUERY_VALUE,
hKey2)
ret = RegOpenKeyEx(hKey, sKey, 0&, KEY_READ, hKey2)
' Si todo va bien (se ha podido abrir la clave)
If ret = ERROR_SUCCESS Then
' Leer esa entrada y obtener el tipo de dato,
longitud, etc.
ret = RegQueryValueEx(hKey2, sValue, 0&, rDT,
0&, lSize)
' Si es un valor binario
If rDT = REG_BINARY Then
If lSize Then
ReDim aData(lSize)
sKey
'
sValue
obtener
'
hKey
' Devuelve:
'
'
Dim ret As Long
Dim hKey2 As Long
Dim rDT As eHKEYDataType
Dim sData As String
Dim lSize As Long
hKey = ParseKey(sKey, hKey)
'--------------------------------------------------------------------Dim i As Long
Dim sRootKey As String
' Comprobar si se indica la clave principal en sKey
i = InStr(sKey, "HKEY_")
If i Then
i = InStr(sKey, "\")
If i Then
sRootKey = Left$(sKey, i - 1)
sKey = Mid$(sKey, i + 1)
Else
sRootKey = sKey
sKey = ""
End If
' Por si se usan abreviaturas de las claves
ElseIf Left$(sKey, 5) = "HKCR\" Then
sRootKey = "HKEY_CLASSES_ROOT"
sKey = Mid$(sKey, 6)
correcto
hKey = HKEY_LOCAL_MACHINE
Case "HKEY_USERS"
hKey = HKEY_USERS
Case "HKEY_CURRENT_CONFIG"
hKey = HKEY_CURRENT_CONFIG
Case "HKEY_DYN_DATA"
hKey = HKEY_DYN_DATA
Case "HKEY_PERFORMANCE_DATA"
hKey = HKEY_PERFORMANCE_DATA
Case Else
hKey = HKEY_CLASSES_ROOT
End Select
End If
ParseKey = hKey
End Function
Public Function OpenKeyEx(ByVal hKey As Long, ByVal
lpSubKey As String, _
ByVal ulOptions As Long, _
ByVal samDesired As eREGSAM,
phkResult As Long) As Long
' Abre una clave del registro, en phkResult devuelve
el handle de
' la clave abierta y se usar para los siguientes
accesos.
'
' ulOptions es un valor reservado que debe ser 0&
'
API
_
lpReserved, lpType, ByVal
lpData, _
lpcbData)
End Function
Public Function EnumValue(ByVal hKey As Long, ByVal
dwIndex As Long, _
lpValueName As String, lpcbValueName As Long, _
_
API
lpcbData)
End Function
Public Function CloseKey(ByVal hKey As Long) As Long
' Cierra la clave abierta usando el handle hKey
'
' Esta funcin simplemente llama a la original del
API
'
CloseKey = RegCloseKey(hKey)
End Function
Public Function QueryInfoKey(ByVal hKey As Long,
lpcbMaxValueNameLen As Long) As Long
'
API
'=======================================================
=======
'
'=== NOTA CACHONDA === por lo incomprensible...
' Es curioso, pero si utilizo estas intrucciones
aqu
'buf = "WindowsDir"
'colShellFoldersKey.Add buf, buf
'colShellFolders.Add "Windows", buf
'
'Para el directorio de System
'buf = "SystemDir"
'colShellFoldersKey.Add buf, buf
'colShellFolders.Add "System", buf
'
'=======================================================
=======
For iCount = 0 To 1
' Enumerar el contenido de Shell Folders
If iCount = 0 Then
sKey =
"HKEY_USERS\.Default\Software\Microsoft\Windows\CurrentV
ersion\Explorer\Shell Folders"
Else
sKey =
"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVe
rsion"
End If
' Usar la funcin EnumValues
If EnumValues(colKeys(), sKey) Then
For i = 1 To UBound(colKeys) Step 2
' colKeys(i)
ser el nombre de la
' colKeys(i + 1)
clave
almacenado
If iCount = 0 Then
colShellFoldersKey.Add colKeys(i),
colKeys(i)
colKeys(i)
Else
colShellFoldersKey.Add
colShellFolders.Add colKeys(i +
End If
End If
Next
End If
Next
' Obtener el directorio de windows
buf = String$(300, Chr$(0))
i = GetWindowsDirectory(buf, Len(buf))
sValue = Left$(buf, i)
buf = "WindowsDir"
colShellFoldersKey.Add buf, buf
colShellFolders.Add sValue, buf
' Obtener el directorio de System
buf = String$(300, Chr$(0))
i = GetSystemDirectory(buf, Len(buf))
sValue = Left$(buf, i)
buf = "SystemDir"
colShellFoldersKey.Add buf, buf
colShellFolders.Add sValue, buf
If bSoloClaves Then
Set ShellFolders = colShellFoldersKey
Else
Set ShellFolders = colShellFolders
End If
Set colShellFoldersKey = Nothing
End Function
Private Sub Class_Initialize()
Set colShellFolders = New Collection
'Set colShellFoldersKey = New Collection
End Sub
Private Sub Class_Terminate()
Set colShellFolders = Nothing
'Set colShellFoldersKey = Nothing
End Sub
'------------------------------------------------------------------------cbData = Len(lpData)
' Hay que usar ByVal porque est definida "As Any"
-------v
RegSetValue2 = RegSetValueEx(hKey, lpSubKey, 0&,
REG_SZ, ByVal lpData, cbData)
End Function
Public Sub AsociarExt(ByVal sExt As String, _
Optional ByVal sExe As String =
"", _
= "open", _
= True, _
"", _
String = "")
sExt
Extensin a asociar
'
sExe
'
sProgId
'
sDescription
Descripcin de la extensin
'
sCommand
Abrir (open)
'
bDefault
se usar por defecto
'
'------------------------------------------------------------------------'Para probar:
'tQR.AsociarExt ".cIt", "C:\Vb5_L\Cut-It\CutIt.exe", "open", False, "gsCutIt", "Cut-It (trocear y
unir archivos)"
niveles
Chr$(34)
Exit Sub
'AsociarExtErr:
'
Debug.Print "AsociarExt, error # " & Err.Number & "
" & Err.Description
'
Err = 0
End Sub
Public Function DeleteKeyWin95(ByVal hKey As Long, ByVal
szKey As String) As Long
' Esta no funciona en Windows NT y parece que
tampoco en Win98
' Slo en Windows 95
DeleteKeyWin95 = RegDeleteKey(hKey, szKey)
'Dim lRet As eHKEYError
'Dim phkResult As Long
'lRet = RegOpenKeyEx(hKey, szKey, 0&,
KEY_ALL_ACCESS, phkResult)
'If lRet = ERROR_SUCCESS Then
'
'
Call RegCloseKey(phkResult)
'End If
'DeleteKeyWin95 = lRet
End Function
Public Sub DesasociarExt(ByVal sExt As String)
Call DeleteKeyWin95(HKEY_CLASSES_ROOT,
sProgId)
'End If
' Esto funciona en Windows 98 y Windows NT,
' tambin en Win95, aunque algo ms lento...
Call DeleteKeyNT(HKEY_CLASSES_ROOT, sExt)
Call DeleteKeyNT(HKEY_CLASSES_ROOT, sProgId)
End If
End Sub
Public Function SetReg(ByVal sKey As String, ByVal sName
As String, _
Optional ByVal vValue As Variant,
HKEY_CURRENT_USER, _
sKey
'
valor
sName
'
vValue
Valor a asignar, el tipo se debe
corresponder con el
'
RegDataType
'
hKey
'
Si en sKey se incluye, no es
necesario especificarla
'
'
bCreateKey
'
' Devolver un valor del tipo: eHKEYError
'
Dim lRet As Long
Dim hKey2 As Long
Dim cbData As Long
Dim aData() As Byte
Dim sData As String
Dim lData As Long
' Convertimos la clave indicada en un valor
correcto,
' para el caso que se indique la clave raiz en sKey
hKey = ParseKey(sKey, hKey)
' Abrir la clave indicada
lRet = RegOpenKeyEx(hKey, sKey, 0&, KEY_WRITE,
hKey2)
' Si da error, comprobar si se crea la clave
If lRet <> ERROR_SUCCESS Then
If bCreateKey Then
lRet = RegCreateKey(hKey, sKey, hKey2)
End If
End If
' Si se produce error, salir
If lRet <> ERROR_SUCCESS Then
SetReg = lRet
Exit Function
End If
' Asignar el valor
'
Select Case RegDataType
Case REG_BINARY
aData = vValue
cbData = UBound(aData)
lRet = RegSetValueEx(hKey2, sName, 0&,
RegDataType, aData(0), cbData)
Case REG_DWORD
cbData = 4
lData = CLng(vValue)
lRet = RegSetValueEx(hKey2, sName, 0&,
RegDataType, lData, cbData)
Case REG_SZ
sData = CStr(vValue)
If Len(sData) = 0 Then
sData = ""
End If
cbData = Len(sData) + 1
Any---v
sKey
'
clave raiz
'
'
sValue
borrar.
'
clave.
Si no se especifica, se borrar la
'
hKey
'
Si en sKey se incluye, no es
necesario especificarla
' Devuelve:
'
1 y UBound(colKeys)
Clave completa de la que se quiere
'
' Devolver True si todo va bien
'
' Revisado para Array y buen funcionamiento (espero)
(14/Oct/98)
' Revisado para funcionar en Windows NT (Win2000
Prof Beta 3)
(12/Jun/99)
'------------------------------------------------------------------------Dim dwIndex
As Long
Dim ret
As Long
Dim hKey2
As Long
Dim hKey
As Long
Dim lpName
As String
Dim lpftLastWriteTime
As FILETIME
Dim colItems
As Long
Dim lSize
As Long
Dim SubKeysNum
As Long
Dim MaxSubKeyLen
As Long
Dim numValues
As Long
Dim MaxValueNameLen
As Long
Dim MaxDataLen
As Long
colItems = 0
ReDim colKeys(0)
' Si se pasa una cadena en sKey, esta funcin la
convierte
' en un valor vlido para la clave principal
hKey = ParseKey(sKey, hKey)
' Abrir la clave indicada
'///////////////////////////////////////////////////////
///////////////////
'
Para que en Windows 2000 funcione,
(12/Jun/99)
'
he cambiado el tipo de acceso de
KEY_ENUMERATE_SUB_KEYS a KEY_READ
'///////////////////////////////////////////////////////
///////////////////
'ret = RegOpenKeyEx(hKey, sKey, 0&,
KEY_ENUMERATE_SUB_KEYS, hKey2)
ret = RegOpenKeyEx(hKey, sKey, 0&, KEY_READ, hKey2)
EnumKeys = True
' Si todo va bien (se ha podido abrir la clave)
If ret = ERROR_SUCCESS Then
' Obtener informacin de la clave y datos,
devolver:
clave
clave
valor
' SubKeysNum
Nmero de subclaves
' MaxSubKeyLen
' numValues
' MaxValueNameLen
' MaxDataLen
'
' Probado para Windows 2000 Professional
(12/Jun/99)
'ret = RegQueryInfoKey(hKey2, vbNullString, 0&,
0&, _
SubKeysNum, MaxSubKeyLen, _
0&, numValues,
MaxValueNameLen, _
MaxDataLen, 0&,
lpftLastWriteTime)
' Slo nos interesa el nmero de subclaves y la
longitud mxima
ret = RegQueryInfoKey(hKey2, vbNullString, 0&,
0&, _
SubKeysNum, MaxSubKeyLen, _
0&, 0&, 0&, _
0&, 0&, lpftLastWriteTime)
' Se empieza desde cero
For dwIndex = 0 To SubKeysNum
lSize = MaxSubKeyLen
lpName = String$(lSize + 1, 0)
' Slo nos interesa los nombres de las
subclaves
ret = RegEnumKeyEx(hKey2, dwIndex, lpName,
lSize, _
0&, vbNullString, 0&,
lpftLastWriteTime)
If ret = ERROR_MORE_DATA Or ret =
ERROR_SUCCESS Then
' Redimensionar el array
colItems = colItems + 1
ReDim Preserve colKeys(colItems)
' lSize tiene el nmero de caracteres
devuelto,
Call CloseKey(hKey2)
End Function
Private Function RTrimZero(ByVal sString As String, _
Optional ByVal PorElFinal As
Boolean = False) As String
' Devuelve una cadena hasta el primer Chr$(0)
(12/Oct/98)
' Ampliada para poder devolver hasta el ltimo
(12/Jun/99)
Dim i As Long
' Si se quitan los ltimos Chr$(0)
If PorElFinal Then
' La cadena termina en el ltimo Chr$(0)
For i = Len(sString) To 1 Step -1
If Mid$(sString, i, 1) = Chr$(0) Then
sString = Left$(sString, i - 1)
Exit For
End If
Next
' Sustituir los Chr$(0) por espacios
For i = 1 To Len(sString)
If Mid$(sString, i, 1) = Chr$(0) Then
Mid$(sString, i, 1) = " "
End If
Next
'
i = Len(sString)
'
'
i = i - 1
'
Loop
'
Chr$(0)
'
If i > 0 Then
'
sString = Left$(sString, i)
'
End If
Else
i = InStr(sString, Chr$(0))
If i Then
sString = Left$(sString, i - 1)
End If
End If
RTrimZero = sString
End Function
Public Function EnumValues(ByRef colKeys() As String,
ByVal sKey As String) As Boolean
'------------------------------------------------------------------------' Enumera todos los valores de la clave indicada en
(12/Oct/98)
sKey
'
' Parmetros:
'
colKeys()
Array unidimensional que contendr
las claves halladas
'
del valor y a
'
continuacin el valor en si, por
tanto hay que tener
'
esto en cuenta a la hora de
recuperar la informacin.
'
Los valores estarn comprendidos
entre 1 y UBound(colKeys)
'
valor
'
poco ms abajo.
'
sKey
la informacin
'
' Devolver True si todo va bien
'
' Revisado para Array y buen funcionamiento (espero)
(14/Oct/98)
'------------------------------------------------------------------------'Para recuperar la informacin de colKeys(), hacer
esto:
'
'If .EnumValues(colKeys(), sKey) Then
'
'
ser el nombre
'
almacenado
'
'colKeys(i + 1)
Next
'End If
'--------------------------------------------------------------------'
Dim dwIndex
As Long
Dim ret
As Long
Dim hKey2
As Long
Dim hKey
As Long
Dim lpName
As String
Dim lpftLastWriteTime
As FILETIME
Dim retDT
As eHKEYDataType
Dim lSize
As Long
Dim sData
As String
Dim aData()
As Byte
Dim lDWord
As Long
Dim i
As Long
Dim colItems
As Long
Dim SubKeysNum
As Long
Dim MaxSubKeyLen
As Long
Dim numValues
As Long
Dim MaxValueNameLen
As Long
Dim MaxDataLen
As Long
EnumValues = True
ReDim aData(0)
lDWord = 0
sData = ""
' Inicializar el array
colItems = 0
ReDim colKeys(colItems)
' Si todo va bien (se ha podido abrir la clave)
If ret = ERROR_SUCCESS Then
' Obtener la informacin de esta clave,
devolver:
' SubKeysNum
Nmero de subclaves
' MaxSubKeyLen
' numValues
' MaxValueNameLen
' MaxDataLen
clave
clave
valor
'ret = RegQueryInfoKey(hKey2, 0&, 0&, 0&,
SubKeysNum, MaxSubKeyLen, _
MaxValueNameLen, _
lpftLastWriteTime)
0&, numValues,
MaxDataLen, 0&,
0&, numValues,
MaxDataLen, 0&,
GoTo SalirEnumValues
End If
lpName = String$(MaxValueNameLen + 1, 0)
' Hacer un bucle para el nmero de valores
posibles
For dwIndex = 0 To numValues
lpName = String$(MaxValueNameLen + 1, 0)
' Llamarlo primero para saber el tipo de
datos,
' el cual estar en retDT
'///////////////////////////////////////////////////////
///////////
' De esta forma en Win2000 produce un error
de proteccin
'ret = RegEnumValue(hKey2, dwIndex, ByVal
0&, ByVal 0&, 0&, retDT, ByVal 0&, ByVal 0&)
'ret = RegEnumValue(hKey2, dwIndex,
vbNullString, ByVal 0&, 0&, retDT, ByVal 0&, ByVal 0&)
'///////////////////////////////////////////////////////
///////////
ret = RegEnumValue(hKey2, dwIndex, 0&, 0&,
0&, retDT, 0&, 0&)
'ret = RegEnumValue(hKey2, dwIndex, lpName,
Len(lpName), 0&, retDT, ByVal sData, lSize)
' la primera vez, cuando dwIndex = cero,
devuelve ERROR_SUCCESS,
' pero despus devuelve ERROR_MORE_DATA
mientras haya datos.
If ret = ERROR_MORE_DATA Or ret =
ERROR_SUCCESS Then
lSize = MaxDataLen
Select Case retDT
Case REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ
' Datos de cadena
sData = String$(lSize, 0)
ret = RegEnumValue(hKey2, dwIndex,
lpName, Len(lpName), 0&, retDT, ByVal sData, lSize)
If retDT = REG_MULTI_SZ Then
sData = RTrimZero(sData, True)
Else
sData = RTrimZero(sData)
End If
lpName = RTrimZero(lpName)
ReDim Preserve colKeys(colItems + 2)
colKeys(colItems + 1) = lpName
colKeys(colItems + 2) = sData
colItems = colItems + 2
Case REG_DWORD
' Datos numricos (long)
ret = RegEnumValue(hKey2, dwIndex,
lpName, Len(lpName), 0&, retDT, lDWord, lSize)
sData = CStr(lDWord)
lpName = RTrimZero(lpName)
ReDim Preserve colKeys(colItems + 2)
colKeys(colItems + 1) = lpName
colKeys(colItems + 2) = sData
colItems = colItems + 2
'Case REG_BINARY
'
'Datos binarios
Case Else
' Tratarlo como Binary
If lSize Then
ReDim aData(lSize)
' Leer los datos binarios
ret = RegEnumValue(hKey2,
dwIndex, lpName, Len(lpName), 0&, retDT, aData(0),
lSize)
lpName = RTrimZero(lpName)
' Al estilo de como se muestra
con RegEdit
sData = ""
For i = 0 To UBound(aData) - 1
sData = sData & Format$(Hex$
End If
Next
Else
EnumValues = False
End If
SalirEnumValues:
' Cerrar la clave abierta
ret = CloseKey(hKey2)
End Function
Public Function RegSaveKey(ByVal sKey As String, ByVal
lpFile As String) As Long
' Guarda en un fichero el contenido de una clave,
las subclaves y datos.
' Y funcionar, funciona, pero el fichero que da como
resultado no es
' un fichero de texto...
' No he probado a asignar de nuevo el valor
guardado, pero seguramente
' funcionar, lo que pasa es que no tiene un formato
reconocido por
' RegEdit.exe (extensin .REG)
'
'$Por hacer: comprobar si esta funcin est bien...
'
' Los atributos de seguridad se ignoran en Win95/98
(0&)
'
'----------------------------------------------------------------------------Option Explicit
Private Declare Function WNetAddConnection2 Lib "mpr.dll" Alias
"WNetAddConnection2A" _
(lpNetResource As NETRESOURCE, ByVal lpPassword As String, _
ByVal lpUserName As String, ByVal dwFlags As Long) As Long
Private Declare Function WNetCancelConnection2 Lib "mpr.dll" Alias
"WNetCancelConnection2A" _
(ByVal lpName As String, ByVal dwFlags As Long, ByVal fForce As
Long) As Long
Private Type NETRESOURCE
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
lpLocalName As String
lpRemoteName As String
lpComment As String
lpProvider As String
End Type
Private Const NO_ERROR = 0
Private Const CONNECT_UPDATE_PROFILE = &H1
' The following includes all the constants defined for NETRESOURCE,
' not just the ones used in this example.
Private Const RESOURCETYPE_DISK = &H1
Private Const RESOURCETYPE_PRINT = &H2
Private Const RESOURCETYPE_ANY = &H0
Private Const RESOURCE_CONNECTED = &H1
Private Const RESOURCE_REMEMBERED = &H3
Private Const RESOURCE_GLOBALNET = &H2
Private Const RESOURCEDISPLAYTYPE_DOMAIN = &H1
Private Const RESOURCEDISPLAYTYPE_GENERIC = &H0
Private Const RESOURCEDISPLAYTYPE_SERVER = &H2
Private Const RESOURCEDISPLAYTYPE_SHARE = &H3
Private Const RESOURCEUSAGE_CONNECTABLE = &H1
Private Const RESOURCEUSAGE_CONTAINER = &H2
' Error Constants:
Private Const ERROR_ACCESS_DENIED = 5&
Private Const ERROR_ALREADY_ASSIGNED = 85&
Private Const ERROR_BAD_DEV_TYPE = 66&
Private Const ERROR_BAD_DEVICE = 1200&
Private Const ERROR_BAD_NET_NAME = 67&
Private Const ERROR_BAD_PROFILE = 1206&
Private Const ERROR_BAD_PROVIDER = 1204&
Private Const ERROR_BUSY = 170&
Private Const ERROR_CANCELLED = 1223&
Private Const ERROR_CANNOT_OPEN_PROFILE = 1205&
Private Const ERROR_DEVICE_ALREADY_REMEMBERED = 1202&
Private Const ERROR_EXTENDED_ERROR = 1208&
Private Const ERROR_INVALID_PASSWORD = 86&
Private Const ERROR_NO_NET_OR_BAD_PATH = 1203&
' If the UserName and Password arguments are NULL, the user
context
' for the process provides the default user name.
ErrInfo = WNetAddConnection2(NetR, MyPass, MyUser,
CONNECT_UPDATE_PROFILE)
If ErrInfo = NO_ERROR Then
lblStatus = " Conexin realizada con xito"
sPath = txtLocal
Else
lblStatus = " ERROR al intentar realizar la conexin"
MsgBox "ERROR: " & ErrInfo & " - Net Connection Failed!",
vbExclamation, "Share not Connected"
End If
' Rellenar el DirBox
Dir1.Path = sPath
End Sub
'
Fade
'
MaxVol
'
MinVol
'
Volumen
'
CambioVolumen
'
' Guillermo 'guille' Som, 1999
'----------------------------------------------------------------------------' El cdigo est basado en un ejemplo de la Knowledge Base de Microsoft:
'
'
'----------------------------------------------------------------------------Option Explicit
' Evento para notificar el cambio del volumen
Public Event CambioVolumen(ByVal VolumenActual As Long)
Private ok As Boolean
(MIXERLINE_COMPONENTTYPE_DST_FIRST + 4)
Private Const MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE = _
(MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3)
Private Const MIXERLINE_COMPONENTTYPE_SRC_LINE = _
(MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2)
Private Const MIXERCONTROL_CT_CLASS_FADER = &H50000000
Private Const MIXERCONTROL_CT_UNITS_UNSIGNED = &H30000
Private Const MIXERCONTROL_CONTROLTYPE_FADER = _
(MIXERCONTROL_CT_CLASS_FADER Or _
MIXERCONTROL_CT_UNITS_UNSIGNED)
Private Const MIXERCONTROL_CONTROLTYPE_VOLUME = _
(MIXERCONTROL_CONTROLTYPE_FADER + 1)
Private Declare Function mixerClose Lib "winmm.dll" _
(ByVal hmx As Long) As Long
Private Declare Function mixerGetControlDetails Lib "winmm.dll" _
Alias "mixerGetControlDetailsA" _
(ByVal hmxobj As Long, _
pmxcd As MIXERCONTROLDETAILS, _
ByVal fdwDetails As Long) As Long
Private Declare Function mixerGetDevCaps Lib "winmm.dll" _
Alias "mixerGetDevCapsA" _
(ByVal uMxId As Long, _
ByVal pmxcaps As MIXERCAPS, _
ByVal cbmxcaps As Long) As Long
Private Declare Function mixerGetID Lib "winmm.dll" _
(ByVal hmxobj As Long, _
pumxID As Long, _
ByVal fdwId As Long) As Long
Private Declare Function mixerGetLineControls Lib "winmm.dll" _
Alias "mixerGetLineControlsA" _
(ByVal hmxobj As Long, _
pmxlc As MIXERLINECONTROLS, _
'
manufacturer id
wPid As Integer
'
product id
vDriverVersion As Long
'
'
product name
fdwSupport As Long
'
cDestinations As Long
'
count of destinations
End Type
Private Type MIXERCONTROL
cbStruct As Long
'
dwControlID As Long
'
dwControlType As Long
'
MIXERCONTROL_CONTROLTYPE_xxx
fdwControl As Long
'
MIXERCONTROL_CONTROLF_xxx
cMultipleItems As Long
'
if MIXERCONTROL_CONTROLF_MULTIPLE set
lMinimum As Long
'
Minimum value
lMaximum As Long
'
Maximum value
reserved(10) As Long
'
End Type
Private Type MIXERCONTROLDETAILS
cbStruct As Long
'
dwControlID As Long
'
cChannels As Long
'
item As Long
'
hwndOwner or cMultipleItems
cbDetails As Long
'
paDetails As Long
'
End Type
Private Type MIXERCONTROLDETAILS_UNSIGNED
dwValue As Long
End Type
'
'
dwDestination As Long
'
dwSource As Long
'
dwLineID As Long
'
fdwLine As Long
'
dwUser As Long
'
dwComponentType As Long
'
cChannels As Long
'
cConnections As Long
'
cControls As Long
'
As Integer
wPid As Integer
vDriverVersion As Long
szPname As String * MAXPNAMELEN
End Type
Private Type MIXERLINECONTROLS
cbStruct As Long
'
dwLineID As Long
'
'
MIXER_GETLINECONTROLSF_ONEBYID or
dwControl As Long
'
MIXER_GETLINECONTROLSF_ONEBYTYPE
cControls As Long
'
cbmxctrl As Long
'
pamxctrl As Long
'
End Type
Private Sub Class_Initialize()
' Abrir el mezclador?
Call AbrirMixer
End Sub
Private Sub Class_Terminate()
On Local Error Resume Next
' Cerrar el mixer
Call mixerClose(hMixer)
Err = 0
End Sub
Public Sub Fade(Optional ByVal Segundos As Long = 3&, _
Optional ByVal Pasos As Long = 8&, _
Optional ByVal Restaurar As Boolean = True, _
Optional ByVal Inverso As Boolean = True, _
Optional ByVal VolMin As Long = 1000&)
'-------------------------------------------------------------------------' Hacer fade llevando el volumen hasta cero
( 1/Ago/98)
'
' Parmetros:
'
Segundos
'
Pasos
'
Restaurar
'
Inverso
VolMin
'
Fade
'-------------------------------------------------------------------------Dim i As Long
Dim horaActual As Date
Static tmpVolActual As Long
Dim j As Long, k As Long
' Siempre debe ser un nmero negativo
Pasos = -Abs(Pasos)
horaActual = Now
'
tmpVolActual = ObtenerVolumen(hMixer, volCtrl)
'
If Inverso Then
' Obtener el valor actual del volumen, por si se cambia
' mientras se est tocando
VolActual = ObtenerVolumen(hMixer, volCtrl)
tmpVolActual = VolActual
j = tmpVolActual
If VolMin < 0 Then VolMin = 0
k = VolMin
Else
j = tmpVolActual
k = VolActual
Pasos = Abs(Pasos)
End If
For i = j To k Step Pasos
Call SetVolumeControl(hMixer, volCtrl, i)
DoEvents
If Second(Now - horaActual) >= Segundos Then
Exit For
End If
Next
tmpVolActual = ObtenerVolumen(hMixer, volCtrl)
If Restaurar Then
Call SetVolumeControl(hMixer, volCtrl, VolActual)
End If
End Sub
Private Function GetVolumeControl(ByRef hMixer As Long, _
ByVal componentType As Long, _
ByVal ctrlType As Long, _
ByRef mxc As MIXERCONTROL) As Boolean
' This function attempts to obtain a mixer control.
' Returns True if successful.
Dim mxlc As MIXERLINECONTROLS
Dim mxl As MIXERLINE
Dim hMem As Long
mxl.cbStruct = Len(mxl)
mxl.dwComponentType = componentType
' Obtain a line corresponding to the component type
rc = mixerGetLineInfo(hMixer, mxl, MIXER_GETLINEINFOF_COMPONENTTYPE)
If (MMSYSERR_NOERROR = rc) Then
mxlc.cbStruct = Len(mxlc)
mxlc.dwLineID = mxl.dwLineID
mxlc.dwControl = ctrlType
mxlc.cControls = 1
mxlc.cbmxctrl = Len(mxc)
' Allocate a buffer for the control
( 1/Ago/98)
mxcd.cChannels = 1
' Get the control value
rc = mixerGetControlDetails(hMixer, _
mxcd, _
MIXER_GETCONTROLDETAILSF_VALUE)
'
' Copy the data into the control value buffer
CopyStructFromPtr vol, mxcd.paDetails, Len(vol)
'
GlobalFree (hMem2)
If (rc = MMSYSERR_NOERROR) Then
ObtenerVolumen = vol.dwValue
RaiseEvent CambioVolumen(vol.dwValue)
Else
ObtenerVolumen = -1&
RaiseEvent CambioVolumen(-1&)
End If
End Function
Private Function SetVolumeControl(ByVal hMixer As Long, _
mxc As MIXERCONTROL, _
ByVal volume As Long) As Boolean
' This function sets the value for a volume control.
' Returns True if successful
Dim mxcd As MIXERCONTROLDETAILS
Dim vol As MIXERCONTROLDETAILS_UNSIGNED
Dim hMem As Long
mxcd.item = 0
mxcd.dwControlID = mxc.dwControlID
mxcd.cbStruct = Len(mxcd)
mxcd.cbDetails = Len(vol)
' Allocate a buffer for the control value buffer
hMem = GlobalAlloc(&H40, Len(vol))
mxcd.paDetails = GlobalLock(hMem)
mxcd.cChannels = 1
vol.dwValue = volume
( 1/Ago/98)
'
'
'
// Open the mixer. This opens the mixer with a deviceID of 0. If you
'
// have a single sound card/mixer, then this will open it. If you have
'
'
// so on.
'
rc = mixerOpen(&hMixer, 0,0,0,0);
'
if (MMSYSERR_NOERROR == rc) {
'
'
'
' Open the mixer with deviceID 0.
rc = mixerOpen(hMixer, 0, 0, 0, 0)
If ((MMSYSERR_NOERROR <> rc)) Then
AbrirMixer = -1
Exit Function
End If
' Get the waveout volume control
ok = GetVolumeControl(hMixer, _
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, _
MIXERCONTROL_CONTROLTYPE_VOLUME, _
volCtrl)
If (ok = True) Then
AbrirMixer = ObtenerVolumen(hMixer, volCtrl)
Else
AbrirMixer = -1
End If
End Function
Private Sub CerrarMixer()
' Cerrar el mixer
Call mixerClose(hMixer)
End Sub
Public Property Get Volumen() As Long
' Obtener el volumen del sistema
Volumen = ObtenerVolumen(hMixer, volCtrl)
End Property
Public Property Let Volumen(ByVal NewValue As Long)
' Asignar un nuevo valor para el volumen
'
' Los valores mximo y mnimo estarn dentro del rango de:
' volCtrl.lMinimum y volCtrl.lMaximum
If Not (NewValue > volCtrl.lMaximum Or NewValue < volCtrl.lMinimum) Then
Call SetVolumeControl(hMixer, volCtrl, NewValue)
End If
End Property
Public Property Get MinVol() As Long
' Devuelve el valor mnimo del volumen (suele ser cero)
MinVol = volCtrl.lMinimum
End Property
Public Property Get MaxVol() As Long
' Devuelve el valor mximo del mixer, normalmente 65535
MaxVol = volCtrl.lMaximum
End Property
'
'----------------------------------------------------------------------------' Prueba de la clase cVolumen
(09/Jul/99)
'
' Guillermo 'guille' Som, 1999
'----------------------------------------------------------------------------Option Explicit
Private WithEvents m_cVol As cVolumen
el volumen
Private m_VolIni As Long
el programa
el volumen
If Index = 0 Then
m_cVol.Fade Restaurar:=False, Inverso:=True, VolMin:=4000
'm_cVol.Fade 3, 8, False, True, 4000
Else
m_cVol.Fade Segundos:=2, Pasos:=16, Inverso:=False
'm_cVol.Fade 2, 16, True, False
End If
' Mostrar el volumen actual
With txtAlpha
.Tag = .Text
End With
' Para que no se ponga negra antes de empezar el fade,
' seguramente es una chapuza, pero funciona!
Hide
txtAlpha = "1"
cmdLayered_Click 0
Show
'// Set WS_EX_LAYERED on this window
Call SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd,
GWL_EXSTYLE) Or WS_EX_LAYERED)
' Empezar el efecto desde 20% de transparencia
Const cAlpha As Long = 20
mAlpha = cAlpha
Timer1.Interval = txtInterval
Timer1.Enabled = True
Else
cmdFade.Caption = "Hacer &Fade"
Timer1.Enabled = False
' Quitar el efecto Layered
cmdLayered_Click 1
' Volver a dejar el valor que haba
With txtAlpha
.Text = .Tag
End With
End If
End Sub
tAlpha = Val(txtAlpha)
If tAlpha < 1 Or tAlpha > 100 Then
tAlpha = 70
End If
'// Set WS_EX_LAYERED on this window
Call SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd,
GWL_EXSTYLE) Or WS_EX_LAYERED)
'// Make this window tAlpha% alpha
Call SetLayeredWindowAttributes(hWnd, 0, (255 * tAlpha) /
100, LWA_ALPHA)
Else
Cdigo de ejemplo:
Crea un nuevo proyecto, aade un MSFlexGrid (Flex), dos botones (Command1 y
Command2) y aade el siguiente cdigo al formulario (Form1):
'
'----------------------------------------------------------------------------' From: "norberto horacio miras" <nmiras@topmail.com.ar>
' Sent: Friday, August 18, 2000 3:53 PM
' Subject: Te mando un truco de Api de Windows
'
' Descripcin:
' Es una llamada a la api de Windows (send message)
' que lo que hace es mandarte al principio o al final de un control
msflexgrid.
'
' Modificado: Guillermo 'guille' Som, 19/Ago/2000
'----------------------------------------------------------------------------Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
_
'----------------------------------------------------------------------------' CLocaleInfo
(03/Sep/99)
' Clase para obtener la informacin del idioma actual
del sistema
'
dwLowDateTime As Long
'
dwHighDateTime As Long
'End Type
Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
'Private Declare Function GetUserDefaultLangID Lib
"kernel32" () As Integer
Private Declare Function GetSystemDefaultLangID Lib
"kernel32" () As Integer
Private Declare Function SetLocaleInfo Lib "kernel32"
Alias "SetLocaleInfoA" _
(ByVal Locale As Long, ByVal LCType As Long, _
ByVal lpLCData As String) As Long
Private Declare Function GetLocaleInfo Lib "kernel32"
Alias "GetLocaleInfoA" _
(ByVal Locale As Long, ByVal LCType As Long, _
ByVal lpLCData As String, ByVal cchData As Long) As
Long
Long
Long
'----------------------------------------------------------------------------' Constantes
'----------------------------------------------------------------------------' Locale Types.
' These types are used for the GetLocaleInfo NLS API
routine.
'
Public Enum eLocaleInfo
LOCALE_ILANGUAGE = &H1
'
language
LOCALE_SLANGUAGE = &H2
name of language
'
localized
LOCALE_SENGLANGUAGE = &H1001
name of language
'
English
id
LOCALE_SABBREVLANGNAME = &H3
abbreviated language name
'
LOCALE_SNATIVELANGNAME = &H4
name of language
'
native
'
country
LOCALE_SCOUNTRY = &H6
name of country
'
localized
LOCALE_SENGCOUNTRY = &H1002
name of country
'
English
LOCALE_SABBREVCTRYNAME = &H7
abbreviated country name
'
LOCALE_SNATIVECTRYNAME = &H8
name of country
'
native
LOCALE_IDEFAULTLANGUAGE = &H9
language id
'
default
LOCALE_IDEFAULTCOUNTRY = &HA
country code
'
default
LOCALE_IDEFAULTCODEPAGE = &HB
code page
'
default
LOCALE_SLIST = &HC
separator
'
list item
LOCALE_IMEASURE = &HD
metric, 1 = US
'
0 =
LOCALE_SDECIMAL = &HE
separator
'
decimal
LOCALE_STHOUSAND = &HF
separator
'
thousand
LOCALE_SGROUPING = &H10
grouping
'
digit
LOCALE_IDIGITS = &H11
fractional digits
'
number of
LOCALE_ILZERO = &H12
zeros for decimal
'
leading
LOCALE_SNATIVEDIGITS = &H13
ascii 0-9
'
native
LOCALE_SCURRENCY = &H14
monetary symbol
'
local
LOCALE_SINTLSYMBOL = &H15
monetary symbol
'
intl
LOCALE_SMONDECIMALSEP = &H16
decimal separator
'
monetary
LOCALE_SMONTHOUSANDSEP = &H17
thousand separator
'
monetary
LOCALE_ICOUNTRY = &H5
code
'
'
'
LOCALE_SMONGROUPING = &H18
grouping
'
monetary
LOCALE_ICURRDIGITS = &H19
monetary digits
'
# local
LOCALE_IINTLCURRDIGITS = &H1A
monetary digits
'
# intl
LOCALE_ICURRENCY = &H1B
currency mode
'
positive
LOCALE_INEGCURR = &H1C
currency mode
'
negative
LOCALE_SDATE = &H1D
separator
'
date
LOCALE_STIME = &H1E
separator
'
time
LOCALE_SSHORTDATE = &H1F
date format string
'
short
LOCALE_SLONGDATE = &H20
format string
'
long date
LOCALE_STIMEFORMAT = &H1003
format string
'
time
LOCALE_IDATE = &H21
date format ordering
'
short
LOCALE_ILDATE = &H22
format ordering
'
long date
LOCALE_ITIME = &H23
format specifier
'
time
LOCALE_ICENTURY = &H24
format specifier
'
century
LOCALE_ITLZERO = &H25
zeros in time field
'
leading
LOCALE_IDAYLZERO = &H26
zeros in day field
'
leading
LOCALE_IMONLZERO = &H27
zeros in month field
'
leading
LOCALE_S1159 = &H28
designator
'
AM
LOCALE_S2359 = &H29
designator
'
PM
LOCALE_SDAYNAME1 = &H2A
for Monday
'
long name
LOCALE_SDAYNAME2 = &H2B
for Tuesday
'
long name
LOCALE_SDAYNAME3 = &H2C
for Wednesday
'
long name
'
'
LOCALE_SDAYNAME4 = &H2D
for Thursday
'
long name
LOCALE_SDAYNAME5 = &H2E
for Friday
'
long name
LOCALE_SDAYNAME6 = &H2F
for Saturday
'
long name
LOCALE_SDAYNAME7 = &H30
for Sunday
'
long name
LOCALE_SABBREVDAYNAME1 = &H31
abbreviated name for Monday
'
LOCALE_SABBREVDAYNAME2 = &H32
abbreviated name for Tuesday
'
LOCALE_SABBREVDAYNAME3 = &H33
abbreviated name for Wednesday
'
LOCALE_SABBREVDAYNAME4 = &H34
abbreviated name for Thursday
'
LOCALE_SABBREVDAYNAME5 = &H35
abbreviated name for Friday
'
LOCALE_SABBREVDAYNAME6 = &H36
abbreviated name for Saturday
'
LOCALE_SABBREVDAYNAME7 = &H37
abbreviated name for Sunday
'
LOCALE_SMONTHNAME1 = &H38
for January
'
long name
LOCALE_SMONTHNAME2 = &H39
for February
'
long name
LOCALE_SMONTHNAME3 = &H3A
for March
'
long name
LOCALE_SMONTHNAME4 = &H3B
for April
'
long name
LOCALE_SMONTHNAME5 = &H3C
for May
'
long name
LOCALE_SMONTHNAME6 = &H3D
for June
'
long name
LOCALE_SMONTHNAME7 = &H3E
for July
'
long name
LOCALE_SMONTHNAME8 = &H3F
for August
'
long name
LOCALE_SMONTHNAME9 = &H40
for September
'
long name
LOCALE_SMONTHNAME10 = &H41
for October
'
long name
LOCALE_SMONTHNAME11 = &H42
for November
'
long name
LOCALE_SMONTHNAME12 = &H43
for December
'
long name
LOCALE_SABBREVMONTHNAME1 = &H44
abbreviated name for January
'
LOCALE_SABBREVMONTHNAME2 = &H45
abbreviated name for February
'
LOCALE_SABBREVMONTHNAME3 = &H46
abbreviated name for March
'
LOCALE_SABBREVMONTHNAME4 = &H47
abbreviated name for April
'
LOCALE_SABBREVMONTHNAME5 = &H48
abbreviated name for May
'
LOCALE_SABBREVMONTHNAME6 = &H49
abbreviated name for June
'
LOCALE_SABBREVMONTHNAME7 = &H4A
abbreviated name for July
'
LOCALE_SABBREVMONTHNAME8 = &H4B
abbreviated name for August
'
LOCALE_SABBREVMONTHNAME9 = &H4C
abbreviated name for September
'
LOCALE_SABBREVMONTHNAME10 = &H4D
abbreviated name for October
'
LOCALE_SABBREVMONTHNAME11 = &H4E
abbreviated name for November
'
LOCALE_SABBREVMONTHNAME12 = &H4F
abbreviated name for December
'
LOCALE_SABBREVMONTHNAME13 = &H100F
'
LOCALE_SPOSITIVESIGN = &H50
'
positive
'
negative
LOCALE_IPOSSIGNPOSN = &H52
sign position
'
positive
LOCALE_INEGSIGNPOSN = &H53
sign position
'
negative
LOCALE_IPOSSYMPRECEDES = &H54
precedes pos amt
'
mon sym
LOCALE_IPOSSEPBYSPACE = &H55
sep by space from pos amt
'
mon sym
LOCALE_INEGSYMPRECEDES = &H56
precedes neg amt
'
mon sym
LOCALE_INEGSEPBYSPACE = &H57
sep by space from neg amt
'
mon sym
sign
LOCALE_SNEGATIVESIGN = &H51
sign
End Enum
' Time Flags for GetTimeFormatW.
Private Const TIME_NOMINUTESORSECONDS = &H1 '
use minutes or seconds
do not
do not
'
'
do not
'
always
'
use short
'
use long
Else
DateFormatOrder = "YMD"
End If
End Function
'Text1(3) = .LocaleInfo(LOCALE_SNATIVECTRYNAME)
Text1(4) = .sDecimal
Text1(5) = .Thousands
Text1(6) = .ShortDateFormat
Text1(7) = .LongDateFormat
Text1(8) = .DateFormatOrder '& " , " &
.LongDateFormatOrder
Text1(9) = .LocaleInfo(LOCALE_SINTLSYMBOL)
Text1(10) = .LocaleInfo(LOCALE_SCURRENCY)
End With
End Sub
El formulario en ejecucin
Hay ocasiones en las que necesitamos saber que unidades tenemos instaladas
en nuestro equipo e incluso puede que lo que necesitemos saber sea las letras
mapeada
Combo1.ListIndex = 0
End If
End If
En el cdigo mostrado, se hace una comprobacin de los 26 primeros bits
(empiezan a contar por cero), si el contenido de dicho bit es UNO, quiere decir que
la unidad comprobada est asignada, sin embargo, si el contenido de ese bit es
CERO, es que dicha unidad no est asignada, por tanto, est disponible.
Adems de esta funcin, existe otra: GetLogicalDriveStrings, con la que se
pueden obtener las unidades disponibles, pero el resultado se devuelve como una
cadena de caracteres; cada una de esas unidades estarn separadas por un valor
Chr$(0).
Aqu te dejo la declaracin de dicha funcin:
Combo1.AddItem Left$(s, i - 1)
s = Mid$(s, i + 1)
End If
Loop While i
' Mostrar la primera letra disponible
If Combo1.ListCount > 0 Then
Combo1.ListIndex = 0
End If
End If
Fjate que en esete caso se incluye la barra junto al nombre de la unidad.
Estas funciones podemos usarlas junto a GetDriveType, para saber de que tipo,
(Fija, extraible, CD-ROM, etc.), es cada una de las unidades que tenemos
instaladas.
Aqu tienes el cdigo de la funcin (en C/C++), as como el que habra que
usar desde Visual Basic.
/
*---------------------------------------------------------------------------gsPrinterJobs.dll
(08/Jun/01)
DLL para devolver el nmero de trabajos pendiente de
una impresora
Basado en un ejemplo de la MSDN Library
Guillermo 'guille' Som, 2001
//---------------------------------------------------------------------------*/
#include <windows.h>
/*
Devuelve el nmero de trabajos pendientes de la
impresora indicada
o -1 si se produce algn error.
El parmetro ser el nombre de la impresora
(Printer.DeviceName)
*/
extern "C" WINBASEAPI DWORD WINAPI FAR PASCAL _export
GetPrinterJobs(BSTR bstrDeviceName)
{
HANDLE
hPrinter;
DWORD
cByteNeeded;
PRINTER_INFO_2
*pPrinterInfo = NULL;
LPSTR
strSrcByVal;
DWORD
Fallo = -1;
// Abrir la impresora
if (!OpenPrinter(strSrcByVal, &hPrinter, NULL))
return Fallo;
// Obtener el tamao del buffer
if (!GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded))
{
// Si da otro error distinto del esperado...
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return Fallo;
}
// Reserva memoria para el buffer
pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
if (!(pPrinterInfo))
// fallo en la reserva de memoria
return Fallo;
// Obtener la informacin de la impresora
if (!GetPrinter(hPrinter,
2,
(LPSTR)pPrinterInfo,
cByteNeeded,
&cByteNeeded))
{
// fallo en el acceso al puntero
free(pPrinterInfo);
pPrinterInfo = NULL;
return Fallo;
}
// Cerrar la impresora
ClosePrinter(hPrinter);
// Devolver el valor de cJobs
return (DWORD)pPrinterInfo->cJobs;
}
Ejemplo de cmo usar esta funcin en Visual Basic:
& n
End If
End Sub
Private Sub Form_Load()
' Enumerar las impresoras disponibles
Dim tPrinter As Printer
'
' Aadir las impresoras disponibles
For Each tPrinter In Printers
cboPrinters.AddItem tPrinter.DeviceName
Next
' Asignar la variable de la impresora seleccionada
Set tPrinter = Printer
If cboPrinters.ListCount > 0 Then
cboPrinters.Text = tPrinter.DeviceName
End If
End Sub
Este es el aspecto del formulario:
/*
Funcin para leer el nmero de pginas pendientes de
imprimir
(11/Jun/01)
Basado en un ejemplo de la MSDN Library:
How To Call Win32 Spooler Enumeration APIs Properly
*/
// Devuelve el nmero de pginas por imprimir y en el
segundo parmetro,
// (por referencia) el nmero de trabajos pendientes
extern "C" WINBASEAPI DWORD WINAPI FAR PASCAL _export
GetNumPages(BSTR bstrDeviceName, DWORD *NumJobs)
{
HANDLE
hPrinter;
DWORD
dwNeeded, dwReturned, i;
JOB_INFO_1
*pJobInfo;
LPTSTR
szPrinterName;
DWORD
Fallo = -1;
DWORD
TotalPaginas=0;
return Fallo;
}
}
// Allocate enough memory for the JOB_INFO_1 structures
plus
// the extra data - dwNeeded from the previous call
tells you
// the total size needed
if( (pJobInfo = (JOB_INFO_1 *)malloc( dwNeeded )) ==
NULL )
{
ClosePrinter( hPrinter );
return Fallo;
}
// Call EnumJobs() again and let it fill out our
structures
if( ! EnumJobs( hPrinter, 0, 0xFFFFFFFF, 1,
(LPBYTE)pJobInfo,
dwNeeded, &dwNeeded, &dwReturned ) )
{
ClosePrinter( hPrinter );
free( pJobInfo );
return Fallo;
}
// You're done with the printer handle, close it
ClosePrinter( hPrinter );
// dwReturned tells how many jobs there are
// Here, you'll simply display the number of jobs found
*NumJobs = dwReturned;
TotalPaginas = 0;
// It's easy to loop through the jobs and access each
one
for(i=0;i<dwReturned;i++)
{
// pJobInfo[i] is a JOB_INFO_1 struct for that job
// so here you could do whatever you want for each job
TotalPaginas = TotalPaginas +
pJobInfo[i].TotalPages;
}
// Clean up
free( pJobInfo );
return (DWORD)TotalPaginas;
}
'
Private Const MF_BYCOMMAND = &H0&
Private Const MF_ENABLED = &H0&
Private Const MF_GRAYED = &H1&
'
Private Const SC_CLOSE = &HF060&
Private Sub Form_Load()
' Deshabilitar el botn de cerrar el formulario
Dim hMenu As Long
'
hMenu = GetSystemMenu(hWnd, 0)
' Deshabilitar el men cerrar del formulario
Call ModifyMenu(hMenu, SC_CLOSE, MF_BYCOMMAND Or MF_GRAYED, -10,
"Close")
'
End Sub
Private Sub cmdDeshabilitar_Click()
' Deshabilitar el botn de cerrar el formulario
Dim hMenu As Long
'
hMenu = GetSystemMenu(hWnd, 0)
' Deshabilitar el men cerrar del formulario
Call ModifyMenu(hMenu, SC_CLOSE, MF_BYCOMMAND Or MF_GRAYED, -10,
"Close")
'
' Si esta llamada se hace dentro del Form_Load,
' no es necesario redibujar los mens
' Redibujar los mens, para que se muestre deshabilitado
Call DrawMenuBar(hWnd)
'
End Sub
Private Sub cmdHabilitar_Click()
' Habilitar el botn de cerrar el formulario
Dim hMenu As Long
'
hMenu = GetSystemMenu(hWnd, 0)
' Esto lo habilita, pero sigue en gris...
End Type
Private Declare Function GetMenuItemInfo Lib "user32" Alias
"GetMenuItemInfoA" _
(ByVal hMenu As Long, ByVal uItem As Long, _
ByVal fByPosition As Boolean, lpMenuItemInfo As MENUITEMINFO) As
Long
'
'
.fState = MF_GRAYED
'
.dwItemData = SC_CLOSE
'
.wID = hSC_Close
'
.fType = MF_STRING
'
'
.cch = Len(sTextClose) + 1
'
'
'
End Sub
.fType = MF_STRING
.dwTypeData = sTextClose & Chr$(0)
.cch = Len(sTextClose) + 1
End With
Call SetMenuItemInfo(hMenu, hSC_Close, False, tMenuItemInfo)
'
' Redibujar los mens, para que se muestre habilitado
Call DrawMenuBar(hWnd)
'
End Sub
Y eso es todo. Prueba a ejecutar el proyecto, vers que el botn se muestra
deshabilitado y no permite cerrar el formulario.
Pulsa en el botn Habilitar y ya estar habilitado y operativo, si pulsas en el botn
Deshabilitar, se deshabilitar el botn y se mostrar gris.
La explicacin de porqu se usa el valor -10, para cambiar de habilitado a
deshabilitado, est explicado en el artculo de la KB del que he usado parte de la
informacin aqu mostrada:
(Q82876) How to Disable Close Command in VB Control Menu (System Menu)
Bjate el cdigo de ejemplo de las dos formas mostradas: deshabilitarCerrar.zip
4.54 KB
Funciones y ejemplos:
1. Cmo usar los objetos del Shell Windows (ShellObjects) (07/Sep/01)
2. Cambiar el texto de los botones de un MsgBox (14/Sep/01)
3. Saber el directorio de Windows y el System (15/Oct/01)
4. Especial Resolucin de Pantalla: (04/Nov/01)
Averiguar la resolucin actual y nmero de colores, usando API.
Cambiar/restaurar la resolucin de forma rpida.
Enumerar las resoluciones disponibles y cambiar/restaurar la
resolucin de la pantalla.
Explicacin
Application
Varias funciones...
GetSystemInformation Ver el cdigo de ejemplo
BrowseForFolder
CascadeWindows
TileHorzontally
TileVertically
MinimizeAll
UndoMinimizeAll
ControlPanelItem
EjectPC
Explore
FileRun
FindComputer
FindFiles
Help
Namespace
Open
RefreshMenu
SetTime
ShutDownWindows
Suspend
"Suspende" el equipo
TryProperties
Windows
ssfRECENT = &H8
ssfSENDTO = &H9
ssfBITBUCKET = &HA
ssfSTARTMENU = &HB
ssfDESKTOPDIRECTORY = &H10
ssfDRIVES = &H11
ssfNETWORK = &H12
ssfNETHOOD = &H13
ssfFONTS = &H14
ssfTEMPLATES = &H15
ssfCOMMONSTARTMENU = &H16
ssfCOMMONPROGRAMS = &H17
ssfCOMMONSTARTUP = &H18
ssfCOMMONDESKTOPDIR = &H19
ssfAPPDATA = &H1A
ssfPRINTHOOD = &H1B
ssfLOCALAPPDATA = &H1C
ssfALTSTARTUP = &H1D
ssfCOMMONALTSTARTUP = &H1E
ssfCOMMONFAVORITES = &H1F
ssfINTERNETCACHE = &H20
ssfCOOKIES = &H21
ssfHISTORY = &H22
ssfCOMMONAPPDATA = &H23
ssfWINDOWS = &H24
ssfSYSTEM = &H25
ssfPROGRAMFILES = &H26
ssfMYPICTURES = &H27
ssfPROFILE = &H28
End Enum
Private Sub cmdSalir_Click()
Unload Me
End Sub
Private Sub Form_Load()
Dim s As String
'
' Crear el objeto Shell
End Sub
Private Sub mnuShell_Click(Index As Integer)
lblInfo.Caption = mnuShell(Index).Tag
lblInfo.Refresh
EjecutarShellObject Trim$(mnuShell(Index).Caption)
End Sub
Private Sub mnuShell2_Click(Index As Integer)
lblInfo.Caption = mnuShell2(Index).Tag
lblInfo.Refresh
EjecutarShellObject Trim$(mnuShell2(Index).Caption)
End Sub
Private Sub AsignarMenuShellObjects()
' Asignar (y crear) los submens de Shell Objects
Dim i As Long
'
' Asignar al Caption lo que muestra el men y
' al Tag el texto a mostrar en la etiqueta de
informacin
'
' El ndice 0 ya estar creado
i = 0
With mnuShell(0)
.Caption = "BrowseForFolder"
.Tag = "Creates a dialog box that allows the
user to select a folder and then returns the selected
folder's Folder object."
End With
'
' Ir creando el resto de los elementos
' usamos deteccin de errores por si ya estuviesen
creados en tiempo de diseo
On Error Resume Next
'
i = i + 1
Load mnuShell(i)
With mnuShell(i)
.Caption = "MinimizeAll"
.Caption = "EjectPC"
.Tag = "Ejects the computer from its docking
station."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "Explore"
.Tag = "Explores a folder."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "FileRun"
.Tag = "Displays the Run dialog to the user."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "FindComputer"
.Tag = "Displays the Find: Computer dialog box."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "FindFiles"
.Tag = "Displays the Find: All Files dialog
box."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "Help"
.Tag = "Displays Microsoft Windows Help."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "NameSpace"
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "SetTime"
.Tag = "Displays the Date/Time Properties dialog
box."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "ShutdownWindows"
box."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "Suspend"
.Tag = "Suspends the computer."
End With
i = i + 1
Load mnuShell2(i)
With mnuShell2(i)
.Caption = "TrayProperties"
object."
End With
'
Err = 0
End Sub
Private Sub EjecutarShellObject(ByVal sMethod As String)
Dim tFolder As Shell32.Folder
Dim s As String
'
On Error Resume Next
'
s = Text1
'
Select Case sMethod
Case "BrowseForFolder" ' Examinar Archivos de
Programas...
Set tFolder = oShell.BrowseForFolder(0,
"Seleccionar carpeta", 0) ', "C:\Program Files"
If Not tFolder Is Nothing Then
s = s & vbCrLf & vbCrLf & "Ttulo: " &
tFolder.Title & " Ttulo del padre: " &
tFolder.ParentFolder.Title
End If
Case "CascadeWindows"
oShell.CascadeWindows
Case "ControlPanelItem"
oShell.ControlPanelItem "" '"INETCPL.cpl"
Case "EjectPC"
oShell.EjectPC
Case "Explore"
oShell.Explore ssfDRIVES
'oShell.Explore "C:\"
Case "FileRun"
oShell.FileRun
Case "FindComputer"
oShell.FindComputer
Case "FindFiles"
oShell.FindFiles
Case "Help"
oShell.Help
Case "MinimizeAll"
oShell.MinimizeAll
Case "NameSpace"
oShell.NameSpace ssfPROGRAMS
'oShell.NameSpace "C:\"
Case "Open"
oShell.Open ssfSTARTUP
Case "RefreshMenu"
oShell.RefreshMenu
Case "SetTime"
oShell.SetTime
Case "ShutdownWindows"
oShell.ShutdownWindows
Case "Suspend"
oShell.Suspend
Case "TileHorizontally"
oShell.TileHorizontally
Case "TileVertically"
oShell.TileVertically
Case "TrayProperties"
oShell.TrayProperties
Case "UndoMinimizeALL"
oShell.UndoMinimizeALL
Case "Windows"
oShell.Windows
End Select
'
Text1 = s
'
Err = 0
End Sub
'----------------------------------------------------------------------------' MSubclassMsgBox
(14/Sep/01)
Exit Function
End If
'
' Convertir lParam en una estructura
Call CopyMemory(s, ByVal lParam, Len(s))
'
If (s.message = WM_INITDIALOG) Then
' Modificar el texto de los botones
Call SetDlgItemText(s.hWnd, IDYES, "Alta")
Call SetDlgItemText(s.hWnd, IDNO, "Modificacin")
' Release the CBT hook
UnhookWindowsHookEx hHook
lr = 0&
End If
CallWndRetProc = lr
End Function
Ejectalo con F5 y pulsa en el botn, te mostrar un cuadro de dilogo
como este que te muestro:
Y ya est.
Precauciones:
No interrumpas el programa mientras se muestra el cuadro de
dilogo, (aunque en teora no debera pasar nada si lo hicieras), pero
sobre todo "procura" que el Visual Basic no se pare dentro de la
funcin CallWndRetProc, ya que se colgara dando error de
proteccin o algo por el estilo.
Tampoco aadas ningn Debug.Print ni nada que pudiera hacer que
se detenga el VB.
Una vez compilado estas precauciones no son aplicables.
Gracias Hernn por ese cdigo en C.
Nota:
He probado el cdigo en Windows XP y no funciona, al
menos no cambia la resolucin.
Aunque si que muestra la resolucin actual, as como el
nmero de colores.
Tambin muestra todos los valores disponibles, antes te
coment que no lo haca y era porque hice la prueba desde
un "terminal" y no desde el equipo en el que est instalado
el XP, y al estar el equipo conectado al Windows XP slo
trabaja con una resolucin!
Al final de la pgina te muestro la imagen del formulario
funcionando en el Windows XP.
dmDisplayFrequency As Long
End Type
'----------------------------------------------------------------------------Option Explicit
Private mResolucionCambiada As Boolean
Private mResAlto As Long
Private mResAncho As Long
Private mResBits As Long
Private DevM As DevMode
' API para cambiar la resolucin de la pantalla
Private Declare Function ChangeDisplaySettings Lib
"user32" Alias "ChangeDisplaySettingsA" _
(lpDevMode As Any, ByVal dwFlags As Long) As Long
' API para saber los formatos de resoluciones posibles
Private Declare Function EnumDisplaySettings Lib
"user32" Alias "EnumDisplaySettingsA" _
(ByVal lpszDeviceName As Long, ByVal iModeNum As
Long, _
lpDevMode As DevMode) As Boolean
Const ENUM_CURRENT_SETTINGS As Long = -1&
Const ENUM_REGISTRY_SETTINGS As Long = -2&
'
Const CCHDEVICENAME = 32
Const CCHFORMNAME = 32
' Las declaraciones de estas constantes estn en:
Wingdi.h
Const DM_BITSPERPEL = &H40000
Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Private Type DevMode
dmDeviceName As String * CCHDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
'
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
'
dmFormName As String * CCHFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Private Sub cmdCambiarRes_Click()
' Cambiar la resolucin a 800x600 colores de 32bits
' o a la indicada en los textboxes
CambiarRes txtResNueva(0), txtResNueva(1),
txtResNueva(2)
End Sub
Private Sub cmdRestaurarRes_Click()
' Poner la resolucin que haba antes,
' si se ha cambiado...
If mResolucionCambiada Then
CambiarRes mResAncho, mResAlto, mResBits
End If
End Sub
Private Sub cmdSalir_Click()
Unload Me
End Sub
Private Sub Form_Load()
mResolucionCambiada = False
'
' Esta llamada a EnumDisplay es para obtener la
resolucin actual
' mediante una llamada al API.
DevM.dmSize = Len(DevM)
Call EnumDisplaySettings(0&, ENUM_CURRENT_SETTINGS,
DevM)
'
mResAncho = DevM.dmPelsWidth
mResAlto = DevM.dmPelsHeight
mResBits = DevM.dmBitsPerPel
'
' La he probado en Windows 2000,
' si no funciona en Windows 9x usa esta otra forma:
'
With Screen
'
'
'
End With
'
mResBits = 32&
'
'
' Mostrar la resolucin actual
With Screen
'
'
'
End With
'
mResBits = 32&
'
' La posicin cero es para la resolucin actual
ReDim Disponibles(0)
With Disponibles(0)
.Width = mResAncho
.Height = mResAlto
.Bits = mResBits
End With
'
' Mostrar la resolucin actual
End If
End Sub
Private Sub ResolucionesDisponibles()
Dim i As Long
Dim a As Long
Dim s As String
'
' Vaciar el combo y el array
lstResoluciones.Clear
' El valor de la posicin CERO es la actual
ReDim Preserve Disponibles(0)
'
DevM.dmSize = Len(DevM)
i = 0
Do
a = EnumDisplaySettings(0&, i&, DevM)
i = i + 1
If a Then
disponibles
" & _
" & _
Sigue este link si quieres saber cmo usar los temas de Windows XP
desde los lenguajes de .NET Framework (Visual Basic .NET, C#,
etc.).
21/Ago/2003:
Si quieres "automatizar" tus formularios de VB para usar los temas
de Windows XP, sigue este link.
9. El fichero .manifest que se use para que Windows XP sepa que tiene
que usar los temas en la aplicacin no debe contener caracteres
acentuados ni ees... si no tienes esto en cuenta, la aplicacin no se
cargar, adems de que dar error.
10. La declaracin de la funcin del API es:
Private Declare Sub InitCommonControls Lib "comctl32.dll" ()
11. En Visual Basic podemos usar dos libreras de controles comunes de
Windows: Windows Common Controls 6.0 basados en mscomctl.ocx y
Windows Common Controls 5.0 basados en Comctl32.ocx, pues bien,
los basados en mscomctl.ocx no "adoptarn" el look de los temas de
XP, para que as sea, habr que usar los basados en Comctl32.ocx.
Aqu tienes un par de capturas para que veas lo que ocurre al usar los
Options, Commands y Frames dentro de un Frame:
(y cmo quedara si esos controles estuviesen contenidos en un picture)
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
Aqu tienes el zip con el cdigo del ejecutable con los dos formularios de
ejemplo, as como el .manifest correspondiente, tanto al del ejecutable
como al del Visual Basic 6.0: temasXPvb.zip 12.3 KB
Deshacer
Private Sub deshacerCmd_Click()
Const EM_CANUNDO As Long = &HC6
Const EM_UNDO As Long = &HC7
'
' se comprueba si se puede deshacer
If SendMessage(Text1.hWnd, EM_CANUNDO, 0&, 0&) Then
' si es as, se deshace
SendMessage Text1.hWnd, EM_UNDO, 0&, 0&
End If
End Sub
Funcin
Comentario
SetWindowsHookEx
UnhookWindowsHookEx
CallNextHookEx
GetAsyncKeyState
tecla
CopyMemory
Constante
Valor
WH_KEYBOARD_LL
VK_TAB
13&
9&
Comentario
para indicar a SetWindowsHookEx que el
gancho ser para el teclado
la tecla TAB
VK_CONTROL
&H11
VK_ESCAPE
&H1B
LLKHF_ALTDOWN
&H20
0&
HC_ACTION
LowLevelKeyboardProc(
// hook code
// message identifier
// pointer to structure with message data
Ahora veremos cmo declararla y usarla desde una aplicacin de VB6 o VB5, pero
no anteriores, ya que se utiliza AddressOf y esa instruccin no existe en las
versiones anteriores a Visual Basic 5.0
Vamos a crear un nuevo proyecto, al cual aadiremos un mdulo BAS.
En el formulario que se incluye, aade dos botones que tendrn estos nombres:
cmdHook y cmdUnHook, desde estos botones se activar y desactivar la
intercepcin de las teclas.
En el mdulo BAS incluiremos las declaraciones del API y dems constantes y tipos,
as como la funcin que ser llamada por el sistema operativo cuando el gancho del
teclado est activo.
era el que puse en el mensaje ese que te coment al principio, el cual a su vez
estaba tomado de un artculo de la Knowledge Base titulado: HOWTO: Disable Task
Switching on Win32 Platforms.
Para terminar, decirte que si este cdigo lo usas en Windows NT, debes tener como
mnimo el SP3.
11. Revisin del cdigo para leer ficheros INI desde Visual Basic
(14/Sep/03)
Introduccin:
Pues eso... que intentando mejorar el acceso a los ficheros INIs me "entretuve" en
leer la ayuda del API para 32 bits y vi un par de funciones que... al menos en
teora, slo servan para el Windows NT... y mira t por dnde... tambin sirven
para el Windows 98... no las he probado para el Windows 95, as que si lo haces y
funciona, me lo cuentas... vale? Gracias.
El cdigo:
El cdigo que te voy a mostrar ahora tiene dos funciones que ya habrs visto en
algn otro sitio de mis pginas, son las funciones para leer y escribir en ficheros
INIs; pero ahora te voy a dar otras tres que de seguro te interesarn:
Borrar claves o secciones de un fichero INI.
Leer todos las claves y valores de una seccin.
Leer todas las secciones.
Decirte que de esta ltima, no viene la declaracin del API en el fichero que se
incluye con el VB, as que toma nota, porque es interesante.
Las declaraciones de las funciones del API
'
'--- Declaraciones para leer ficheros INI --'
' Leer todas las secciones de un fichero INI, esto seguramente no
funciona en Win95
' *** Esta funcin no estaba en las declaraciones del API que se
incluye con el VB ***
Private Declare Function GetPrivateProfileSectionNames Lib
"kernel32" Alias "GetPrivateProfileSectionNamesA" _
(ByVal lpszReturnBuffer As String, ByVal nSize As Long, _
ByVal lpFileName As String) As Long
' Leer una seccin completa
Private Declare Function GetPrivateProfileSection Lib "kernel32"
Alias "GetPrivateProfileSectionA" _
(ByVal lpAppName As String, ByVal lpReturnedString As String, _
String
'
'lpAppName:
'lpKeyName:
Clave
'lpDefault:
la clave.
'
Dim LTmp As Long
Dim sRetVal As String
sRetVal = String$(255, 0)
LTmp = GetPrivateProfileString(lpAppName, lpKeyName, lpDefault,
sRetVal, Len(sRetVal), lpFileName)
If LTmp = 0 Then
IniGet = lpDefault
Else
IniGet = Left(sRetVal, LTmp)
End If
End Function
String)
'
lpFileName
'
lpAppName
' Devuelve:
'
'
'
'
sClave = tContenidos(i)
'
sValor = tContenidos(i+1)
'
Next
'
Dim tContenidos As Collection
Dim nSize As Long
Dim i As Long
Dim j As Long
Dim sTmp As String
Dim sClave As String
Dim sValor As String
lpFileName
' Devuelve:
'
'
Dim tContenidos As Collection
Dim nSize As Long
Dim i As Long
Dim sTmp As String
' El tamao mximo para Windows 95
sBuffer = String$(32767, Chr$(0))
' Esta funcin del API no est definida en el fichero TXT
nSize = GetPrivateProfileSectionNames(sBuffer, Len(sBuffer),
lpFileName)
If nSize Then
' Crear una coleccin del tipo cParrafos que es una
coleccin
' con elementos del tipo cContenido
Set tContenidos = New Collection
' Cortar la cadena al nmero de caracteres devueltos
sBuffer = Left$(sBuffer, nSize)
' Quitar los vbNullChar extras del final
i = InStr(sBuffer, vbNullChar & vbNullChar)
If i Then
sBuffer = Left$(sBuffer, i - 1)
End If
' Cada una de las entradas estar separada por un Chr$(0)
Do
i = InStr(sBuffer, Chr$(0))
If i Then
sTmp = LTrim$(Left$(sBuffer, i - 1))
If Len(sTmp) Then
tContenidos.Add sTmp
End If
sBuffer = Mid$(sBuffer, i + 1)
End If
Loop While i
If Len(sBuffer) Then
tContenidos.Add sBuffer
End If
End If
Set IniGetSections = tContenidos
End Function
Bueno... eso es todo lo que se necesita para usar esas funciones, en este caso, si
te fijas, las funciones son Private, ya que las he "modificado" para usar en un Form
directamente, pero si las quieres "encapsular" en una clase o en un mdulo BAS,
deberas cambiar las declaraciones a Public, pero no las de las funciones del API...
esas pueden (y deberan) seguir siendo Privadas.
Del cdigo para usar estas funciones slo te voy a ensear parte... el resto te lo
imaginas... que con un poco de imaginacin seguro que eres capaz de crear el
ejemplo para que funcione... je, je... no es mala "leche", es que as te esfuerzas
un poco... que os estoy acostumbrando a darlo todo hecho y eso no ayuda
demasiado a aprender...
Aqu estn los trozos del Form y una imagen de cmo queda en modo de diseo.
El form de prueba
'
' Leer todas las secciones del fichero indicado y guardarlas en el
cboSecciones
Private Sub LeerSecciones()
Dim tContenidos As Collection
Dim i As Long
' Llenar las secciones de este fichero
Set tContenidos = IniGetSections(txtFicIni)
If Not tContenidos Is Nothing Then
cboSecciones.Clear
For i = 1 To tContenidos.Count
cboSecciones.AddItem tContenidos(i)
Next
cboSecciones.ListIndex = 0
txtValor = ""
End If
End Sub
En estos dos ZIPs tienes los dos ejemplos, uno usando Variant y otro usando un
Array del tipo String:
Usando Variant: INIVariant.zip 9.62 KB
Usando Array de String: INIArray.zip 13.7 KB
12. Especial Docking:
Poner un formulario dentro de un control picture (25/Ene/04)
En este ejemplo te voy a mostrar cmo hacer que un formulario se pueda "meter"
en un control PictureBox, con idea de poder simular acoplamiento de formularios
con otros controles, es decir, tener un formulario con varios controles, por ejemplo
un ToolBar, StatusBar, un TreeView, etc. y en otro de los controles tener un
formulario.
De paso veremos cmo hacer que se pueda cambiar el tamao de dos de esos
controles (los que estn en el centro del formulario) mediante una barra de
divisin (Split). Aunque esto ltimo est en otra pgina/artculo, sigue este link
para verlo.
Normalmente tendremos un formulario principal, el cual puede tener un men
principal y tambin en la parte superior un ToolBar. Por otro lado, en la parte
inferior tambin tendremos un StatusBar. En el centro, (en la parte principal del
formulario), tendremos dos "paneles", uno a la izquierda y otro a la derecha. En el
panel izquierdo podramos insertar un control al estilo del Outlook con una serie de
botones de opciones, etc. y en el panel derecho podramos tener el contenido de
otro formulario de nuestra aplicacin.
Todo esto son "deseos", ya que en el ejemplo que te voy a mostrar, todos estos
"posibles" controles sern del tipo PictureBox, aunque realmente el nico que
"debera" ser un PictureBox es el panel de la derecha, el que contendr el "otro"
formulario. Pero, para no complicar demasiado el ejemplo, he preferido dejarlos
todos como controles Picture. Sigue las "recomendaciones" de los comentarios del
ejemplo y vers que te resultar fcil usar otros controles.
'----------------------------------------------------------------------------'
' Para hacer ventanas hijas
Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
'
' Para mostrar una ventana segn el handle (hwnd)
' ShowWindow() Commands
Private Enum eShowWindow
HIDE_eSW = 0&
SHOWNORMAL_eSW = 1&
NORMAL_eSW = 1&
SHOWMINIMIZED_eSW = 2&
SHOWMAXIMIZED_eSW = 3&
MAXIMIZE_eSW = 3&
SHOWNOACTIVATE_eSW = 4&
SHOW_eSW = 5&
MINIMIZE_eSW = 6&
SHOWMINNOACTIVE_eSW = 7&
SHOWNA_eSW = 8&
RESTORE_eSW = 9&
SHOWDEFAULT_eSW = 10&
MAX_eSW = 10&
End Enum
Private Declare Function ShowWindow Lib "user32" _
(ByVal hWnd As Long, ByVal nCmdShow As eShowWindow) As Long
'
' Para posicionar una ventana segn su hWnd
Private Declare Function MoveWindow Lib "user32" _
(ByVal hWnd As Long, ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As
Long) As Long
'
' Para cambiar el tamao de una ventana y asignar los valores
mximos y mnimos del tamao
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECTAPI
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type WINDOWPLACEMENT
Length As Long
Flags As Long
ShowCmd As Long
ptMinPosition As POINTAPI
ptMaxPosition As POINTAPI
rcNormalPosition As RECTAPI
End Type
Private Declare Function GetWindowPlacement Lib "user32" _
(ByVal hWnd As Long, ByRef lpwndpl As WINDOWPLACEMENT) As Long
Ahora, simplemente haremos que el formulario se "meta" en el contenedor y que
al cambiar el tamao del formulario, tambin se cambie el tamao del formulario
"incrustado".
En el siguiente cdigo se supone que el formulario que queremos mostrar se llama
"Form2" y que el control que contendr dicho formulario se llama Picture1.
Tambin tendremos un botn que se usar para mostrar dicho formulario.
Para que se vea el "efecto", tendremos a la izquierda un segundo control, en este
ejemplo es otro PictureBox, pero, como te comentaba antes, puede ser cualquier
otro control que queramos tener acoplado a la parte izquierda del formulario. En
este caso ese control se llama picIzq y haremos que se acople a la izquierda,
asignando a la propiedad Align el valor vbAlignLeft.
El formulario "normal"
'
End Sub
Para poder hacer que se pueda cambiar el tamao, necesitamos que alguno
de los controles se entere de que estamos moviendo la barra de
desplazamiento, adems de que debemos mostrar grficamente que
estamos "moviendo" dicha barra de desplazamiento. Esto ltimo lo haremos
en los eventos MosuseDown, MouseUp y MouseMove del control imgSplitter.
Private Sub imgSplitter_MouseDown(Button As Integer,
Shift As Integer, x As Single, y As Single)
With imgSplitter
picSplitter.Move .Left, .Top, .Width \ 3,
.Height - 20
End With
picSplitter.Visible = True
moviendo = True
End Sub
Private Sub imgSplitter_MouseMove(Button As Integer,
Shift As Integer, x As Single, y As Single)
Dim sglPos As Single
'
If moviendo Then
sglPos = x + imgSplitter.Left
If sglPos < splitLimit Then
picSplitter.Left = splitLimit
ElseIf sglPos > Me.Width - splitLimit Then
picSplitter.Left = Me.Width - splitLimit
Else
picSplitter.Left = sglPos
End If
End If
End Sub
Private Sub imgSplitter_MouseUp(Button As Integer, Shift
As Integer, x As Single, y As Single)
sizeControls picSplitter.Left
picSplitter.Visible = False
moviendo = False
End Sub
En esta pgina encontrars las declaraciones tanto para VB .NET como para
C# de algunas de las funciones del API de Windows, adems de las
constantes y tipos de datos usados habitualmente por el API de Windows.
Si viene al caso, tambin te pondr un link al artculo en el que se utiliza
dicha API, para que tengas un ejemplo prctico y "realista" de cmo usarla,
ya que aqu simplemente te mostrar la forma de declarar la funcin,
constante o tipo de datos, sin ningn ejemplo de cmo usarla.
En el caso de que no exista un artculo publicado que la utilice, procurar
aadir un link a una pgina con un ejemplo "prctico" para usar la funcin
del API y, si es posible o viene al caso, tambin te indicar la clase de .NET
que podemos usar para realizar la misma tarea.
En cada funcin del API de Windows he incluido la definicin de la misma
que aparece en la documentacin del SDK de Windows, as como las
declaraciones para VB6, VB .NET y C#.
Estas son las declaraciones de funciones del API de Windows equivalentes
para Visual Basic .NET y C# (y la misma declaracin para Visual Basic 6.0
-clsico-).
EnumChildWindows
EnumChildWindowsProc (delegado)
EnumWindows
EnumWindowsProc (delegado)
ExtractIcon
ExtractIconEx
FindWindow
GetActiveWindow
GetClassLong
GetClassWord
GetDriveType (*)
GetForegroundWindow
GetLogicalDrives (*)
GetVersion
GetVersionEx
GetLongPathName
GetShortPathName
GetWindowText
IsWindowVisible
MoveWindow
OSVERSIONINFO (tipo)
SendMessage
SetForegroundWindow
SetParent
SetWindowPos
SetWindowText
ShowWindow
Nota:
En las declaraciones aqu mostradas, salvo descuido, he usado la forma
"recomendada" de .NET, es decir: aplicando el atributo DllImport, (definido
en System.Runtime.InteropServices) en caso de que usemos la forma
"clsica" de VB6, el compilador de VB crear una declaracin "parecida" a
la de DllImport, pero usando los valores predeterminados.
A continuacin te muestro la forma de usar el atributo DllImport y los
campos que puedes indicar. En su versin simple, funciona de la siguiente
forma (segn los parmetros usados):
DllImport(String) Se indica el nombre de la Librera de Windows que
contiene la funcin, esta es la forma "recomendable" de usar este atributo
si queremos usar lo valores predeterminados del resto de campos.
DllImport(String, EntryPoint := String) Se indica el nombre de la
librera en el primer parmetro, en el segundo se indicar el nombre de la
funcin tal y como est definida en el fichero de cabecera (.H)
correspondiente.
Habitualmente existen dos nombres de para cada funcin del API,
una acabada con W y otra acabada con A, segn se utilice un
sistema operativo Unicode (Windows NT/2000/XP/2003/CE) o no
(Win95/98/ME). Ver ms abajo la descripcin de CharSet,
EntryPoint y ExactSpelling.
Los otros parmetros de este atributo, que podemos indicar (usando la
forma: nombre_campo := valor en VB o nombre_campo = valor en C#)
son:
CharSet:
El tipo de juego de caracteres a usar.
Puede ser:
EntryPoint:
El valor del campo EntryPoint indica el nombre "exacto" de la
funcin del API que queremos usar.
Si el nombre de la funcin del API tiene el mismo nombre que el
usado en la declaracin, no es necesario indicar este valor.
Como he indicado antes, ese nombre puede acabar con A o W,
segn el tipo de funcin a usar: ANSI o UNICODE respectivamente.
Si no indicamos en EntryPoint el nombre de la funcin, se usar la
que "coincida" con el nombre de la funcin indicada en la
declaracin y segn el valor asignado al campo CharSet (o
ExactSpelling) se aadir la letra A o W (si es que existen dos
versiones diferentes).
Si no se indica ningn valor especfico en CharSet, (el valor
realmente ser Auto), se usar la versin ANSI (acabada en A) o
UNICODE (acabada en W) segn el sistema operativo en el que se
est ejecutando la aplicacin.
ExactSpelling:
Indica si el nombre de la funcin se ha escrito de la misma forma
que en la librera del API. Esto es para cuando no se usa EntryPoint,
ya que en caso de que el valor de este campo sea False, se aadir
una A al nombre de la funcin si CharSet es Ansi y una W si el valor
de Charset es Unicode.
SetLastError:
Ver la documentacin en lnea para ms informacin.
El valor predeterminado para VB y C# es False.
Si en VB utilizamos Declare en lugar de DllImport para declarar la
funcin, el valor de SetLastError es True.
PreserveSig:
Ver la documentacin en lnea para ms informacin.
El valor predeterminado es True.
CallingConvention:
Ver la documentacin en lnea para ms informacin.
El valor predeterminado es WinAPI que se convertir en una llamada
StdCall para plataformas Windows o en Cdecl para CE.
BestFitMapping:
Ver la documentacin en lnea para ms informacin.
El valor predeterminado es True.
Si quieres ver las declaraciones para .NET de muchas de las funciones del
API de Windows, no debes dejar de visitar este sitio: PINVOKE.NET.
Nota:
Debido a que prcticamente todos los tipos del API, salvo
excepciones, se corresponden con un entero de .NET
(Int32), para que la tabla no sea demasiado montona, de
los tipos de .NET slo mostrar los tipos definidos en el
CTS (Common Type System), sistema de tipos comunes
de .NET, es decir los tipos de datos del propio .NET
Framework, ya que no creo que te resulte difcil saber a
que tipo de VB o C# equivale.
Como podrs comprobar, bsicamente con saber que el
tipo Int32 (Integer en VB, int en C#) de .NET equivale a
un LONG del API de Windows, tendramos ms que
suficiente, ya que ese es el tipo de datos (incluso
camuflado) es el que se suele usar en las libreras del API
que estn escritas en C "normal".
Tambin comprobars que .NET dispone de "tipos" para lo
que en el API de Windows se soluciona con "apaos de
andar por casa", tal es el caso de los punteros de C, que
en .NET se solucionan mediante delegados.
Algunos tipos, como el UINT se podran cambiar por el "especfico", pero
tambin funcionar si se cambia por un Int32. El caso de HWND que es el
"handle" de una ventana, se puede cambiar indistintamente por un Int32 o
preferiblemente por System.IntPtr.
Descripcin
.NET
VB6
HWND
Handle de la ventana de
destino
Int32
System.IntPtr
(4)
Long
Int32
Long
UINT
WPARAM
Cuando se usa en
Send/PeekMessage, el
primer mensaje a enviar a
la ventana
Int32
Long
LPARAM
El segundo mensaje a
enviar a la ventana
Int32
Long
DWORD
Int32
Long
BOOL
Boolean
Long/Boolean
HRESULT
Int32
Long
LPCTSTR
String o
ByVal String
StringBuilder (2)
LPTSTR
String o
ByVal String
StringBuilder (2)
LPMSG
--
LPDEVMODE
--
CALLBACK
Definicin de un -delegado
Definicin de la funcin
CallBack (3)
SendMessage
Esta funcin del API se utiliza para muchsimas cosas diferentes y
dependiendo del uso, puede que los parmetros empleados sean de
diferentes tipos, pero gracias a que los lenguajes de .NET permiten la
sobrecarga de funciones, podremos usar el mismo nombre de funcin sin
necesidad de que importe de que tipos son dichos parmetros.
Sin embargo en VB6 al no permitir el mismo nombre de funcin, en
ocasiones tenamos que definirla usando nombres diferentes para usos
diferentes, esa es la razn principal de que los dos ltimos parmetros de
esta funcin se definieran con As Any, que es la declaracin que con ms
frecuencia se utiliza en VB6, pero que en otros casos se puede utilizar con
parmetros diferentes, segn el uso que le fusemos a dar.
Ejemplo (usando una estructura como ltimo parmetro)
UINT Msg,
// message to send
WPARAM wParam,
LPARAM lParam
);
VB6 genrico:
Private Declare Function SendMessage Lib "user32" Alias
"SendMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByRef lParam As Any) As Long
VB .NET:
<System.Runtime.InteropServices.DllImport("user32.DLL")> _
Private Shared Function SendMessage( _
ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, _
ByVal wParam As Integer, ByVal lParam As Integer _
) As Integer
End Sub
C#:
[System.Runtime.InteropServices.DllImport("user32.DLL")]
private extern static int SendMessage(
System.IntPtr hWnd, int wMsg,
int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.DLL")]
private extern static int SendMessage(
System.IntPtr hWnd, int wMsg,
int wParam, string lParam);
GetLongPathName
Esta funcin la podemos usar para convertir un nombre corto (tipo MS-DOS
8.3) en uno largo.
Declaracin en el API de Windows:
DWORD GetLongPathName(
LPCTSTR lpszShortPath,
to be converted
LPTSTR lpszLongPath,
the long path.
);
GetShortPathName
Esta funcin la podemos usar para convertir un nombre largo en uno corto
(tipo MS-DOS 8.3).
Declaracin en el API de Windows:
DWORD GetShortPathName(
LPCTSTR lpszLongPath,
string
LPTSTR lpszShortPath,
path
DWORD cchBuffer
pointed
);
SetForegroundWindow
Trae la ventana indicada al frente y la activa.
Si se pudo traer al frente, devolver un valor Verdadero (<>0 en VB6).
En ocasiones podramos sustituir esta funcin del API usando el mtodo
BringToFront que todos los controles (y/o clases derivadas de Control)
tienen.
Declaracin en el API de Windows:
BOOL SetForegroundWindow(
HWND hWnd
);
FindWindow
Devuelve el "handle" de la ventana que coincida con la clase y nombre
indicados.
Normalmente el primer parmetro se puede omitir.
LPCTSTR lpWindowName
);
ShowWindow
Muestra (cambia) la ventana actual al estado indicado.
Si la ventana ya estaba visible devuelve un valor distinto de cero.
El estado puede ser: maximizada, minimizada, etc.
En .NET sera el equivalente a asignar un valor a la propiedad WindowState
de un formulario.
// handle to window
int nCmdShow
);
IsWindowVisible
Utilizada para saber si una ventana est visible.
// handle to window
);
GetWindowText
Recupera el texto de la barra de ttulos de una ventana o el texto de un
control.
Devuelve el nmero de caracteres copiados en el segundo parmetro o cero
si la ventana o el control no tienen texto que copiar.
Ejemplos:
Con EnumWindows,
con GetForegroundWindow
LPTSTR lpString,
int nMaxCount
);
HWND hWnd,
SetWindowText
Cambia el texto de la barra de ttulos de una ventana o el texto de un
control.
Devuelve un valor verdadero (distinto de cero) si todo funcion bien.
HWND hWnd,
LPCTSTR lpString
// address of string
);
EnumWindows
Se usa para iniciar la enumeracin de ventanas de "mayor" nivel (top level).
En el primer parmetro se indicar un "puntero a una funcin", (ver
EnumWindowsProc), que en .NET se declara como un delegado.
Ejemplo
LPARAM lParam
// application-defined value
);
EnumChildWindows
Enumera las "ventanas" de una ventana "top-level". Es decir las ventanas
pertenecientes a una ventana, por ejemplo los controles que contiene una
ventana... hay que recordar que para Windows todo lo que se muestra es
una ventana (o casi).
En el segundo parmetro se indicar un "puntero a una funcin", (ver
EnumChildProc), que en .NET se declara como un delegado.
Ejemplo
Declaracin en el API de Windows:
BOOL EnumChildWindows(
HWND hWndParent,
WNDENUMPROC lpEnumFunc,
LPARAM lParam
// application-defined value
);
EnumWindowsProc, EnumChildProc
Estas funciones son funciones callback, es decir "un puntero a una funcin".
Realmente no es que se use para "crear" ventanas "callback", sino que es la
"definicin" de cmo debe ser la funcin callback usada con las dos
primeras funciones. Sera el equivalente a un delegado de .NET.
Para usar estos delegados habra que usar las funciones EnumWindows o
EnumChildWindows de la siguiente forma, suponiendo que tenemos un
mtodo con la misma firma del delegado llamado EnumWindowsProc:
En VB .NET:
EnumWindows(AddressOf EnumWindowsProc, 0)
EnumChildWindows(handleParent, AddressOf EnumWindowsProc, 0)
En C#:
EnumWindows(new EnumWindowsDelegate(EnumWindowsProc), 0)
EnumChildWindows(handleParent, new
EnumWindowsDelegate(EnumWindowsProc), 0)
Ejemplo
);
BOOL CALLBACK EnumChildProc(
HWND hwnd,
LPARAM lParam
);
ExtractIcon y ExtractIconEx
Extraer iconos de una aplicacin o fichero (.exe, .dll,. etc.)
GetClassLong
Devuelve un valor de 32 bits (long) de la ventana indicada por el handle del
primer parmetro.
GetForegroundWindow
Esta funcin devuelve el Handle de la venta que est actualmente activa,
(la que el usuario est usando en ese momento).
GetForegroundWindow no es lo mismo que GetActiveWindow, ya que esta
ltima devuelve la relacionada con el mismo thread (hilo) de la aplicacin
actual (la nuestra).
Ejemplo
Declaracin en el API de Windows:
HWND GetForegroundWindow(VOID);
GetActiveWindow
GetActiveWindow devuelve el Handle de la venta activa de nuestra
aplicacin, sera el equivalente a ActiveForm de VB6.
Si quieres averiguar cual es la ventana que actualmente est activa (no
necesariamente de nuestra aplicacin), puedes usar GetForegroundWindow.
Ejemplo
Declaracin en el API de Windows:
HWND GetActiveWindow(VOID);
<System.Runtime.InteropServices.DllImport("user32.dll")> _
Private Shared Function GetActiveWindow() As System.IntPtr
End Function
GetVersion
Ejemplo para Visual Basic 6.0, ejemplo para Visual Basic .NET
y C#
Devuelve la versin actual del sistema operativo.
Declaracin en el API de Windows:
DWORD GetVersion(void);
GetVersionEx
Nota:
En los ejemplos anteriores se explica cmo usar la funcin y
se muestra el cdigo de la declaracin, tanto de la funcin
como de los tipos usados para obtener la informacin.
OSVERSIONINFO y OSVERSIONINFOEX
Nota:
En los ejemplos anteriores se explica cmo usar la funcin y
se muestra el cdigo de la declaracin, tanto de la funcin
como de los tipos usados para obtener la informacin.
MoveWindow
Esta funcin la usaremos para cambiar el tamao y la posicin de una
ventana de la que conocemos el handle.
Si esa ventana est contenida en otra, la posicin ser relativa a la ventana
que la contiene, no al escritorio.
BOOL MoveWindow(
HWND hWnd,
// handle to window
int X,
// horizontal position
int Y,
// vertical position
int nWidth,
int nHeight,
// width
// height
SetParent
Asigna a una ventana el padre o contenedor.
HWND hWndNewParent
);
SetWindowPos
Esta funcin sirve para cambiar el tamao y posicin de una ventana (la
indicada por el handle del primer parmetro), pero tambin se usa para
poner esa venta encima (o debajo) del resto de ventanas.
);
// handle to window
// placement-order handle
int X,
position
// horizontal
int Y,
position
// vertical
int cx,
// width
int cy,
// height
uint uFlags
options
);
// window-positioning
GetLogicalDrives
The GetLogicalDrives function retrieves a bitmask representing the
currently available disk drives.
Que ms o menos quieres decir que devuelve una mscara de bits con los
discos disponibles.
Nota:
Existe un mtodo con el mismo nombre definido en la clase
Environment que sirve para casi lo mismo, bueno, en
realidad es parecido a la funcin del API
GetLogicalDriveStrings.
Ejemplos:
[DllImport("kernel32.dll")]
private extern static int GetLogicalDrives();
GetDriveType
The GetDriveType function determines whether a disk drive is a removable,
fixed, CD-ROM, RAM disk, or network drive.
Pues eso, que esta funcin nos indica el tipo de disco.
Nota:
El valor devuelto por esta funcin usa los valores de las
enumeracin indicada en el ejemplo de VB.NET y C#.
Si quieres ms detalle sobre los tipos de discos USB, busca
info sobre SetupDiGetDeviceRegistryProperty (yo an no
lo he probado, si lo hago, pues te lo pondr por esta pgina
o seccin)
Ejemplos:
<DllImport("kernel32.dll")> _
Private Function GetDriveType(ByVal nDrive As String) As
TipoUnidades
End Function
No_montado
invalid;
' 1 DRIVE_NO_ROOT_DIR
'
is no volume mounted at the path.
Extraible
removable media;
' 2 DRIVE_REMOVABLE
'
floppy drive or flash card reader.
for example, a
'
da como extraibles.
Fijo
media;
' 3 DRIVE_FIXED
'
drive, flash drive, or thumb drive.
'
normales enchufados por USB son fijos.
Remoto
' 4 DRIVE_REMOTE
remote (network) drive.
The drive is a
CDROM
ROM drive.
' 5 DRIVE_CDROM
RAMDISK
disk.
' 6 DRIVE_RAMDISK
End Enum
{
// Indico tambin los valores del API (empiezan por cero y
van de uno en uno)
Desconocido,
// 0 DRIVE_UNKNOWN
cannot be determined.
No_montado,
invalid;
// 1 DRIVE_NO_ROOT_DIR
//
is no volume mounted at the path.
Extraible,
removable media;
// 2 DRIVE_REMOVABLE
//
floppy drive or flash card reader.
for example, a
//
da como extraibles.
Fijo,
fixed media;
// 3 DRIVE_FIXED
//
hard drive, flash drive, or thumb drive.
for example, a
//
normales enchufados por USB son fijos.
Remoto,
// 4 DRIVE_REMOTE
remote (network) drive.
The drive is a
CDROM,
ROM drive.
// 5 DRIVE_CDROM
RAMDISK,
disk.
// 6 DRIVE_RAMDISK
};
MinimizeAll
Utilidad
Devuelve el ClassName del nombre de la ventana
indicada
Cierra la ventana indicada en el parmetro,
opcionalmente se puede especificar el ClassName.
Enumera las ventanas que tienen ttulo y son
visibles, devuelve una coleccin (Variant) con el
ttulo y hWnd de cada ventana, opcionalmente
aade esta informacin a un ListBox (o ComboBox)
indicado en el segundo parmetro.
Minimiza todas las ventanas, si se indica el
ClassName, slo minimiza las ventanas que tengan
ese ClassName.
El primer ejemplo que vamos a ver simplemente cierra todas las carpetas
abiertas, para ello se usa CloseApp con el ClassName "CabinetWClass", que
es como se llaman este tipo de "ventanas", hay que hacer notar que el
navegador Internet Explorer, al menos el que viene con Windows 98, tiene
tambin ese ClassName, por tanto tambin se cerrar, si es que est
abierto.
Veamos el cdigo:
Para crear este ejecutable, aade la clase cWindows y un mdulo BAS, en
las propiedades del proyecto selecciona Sub Main como el objeto de entrada
al programa, e inserta el siguiente cdigo en el mdulo BAS:
'
Public Sub Main()
Dim m_UtilVentanas As cWindows
Dim col As Collection
Dim numItems As Long
Dim i As Long
Dim sTitulo As String
Set m_UtilVentanas = New cWindows
Set col = New Collection
Set col = m_UtilVentanas.EnumTopWindows
numItems = col.Count
For i = 1 To numItems Step 2
sTitulo = col.Item(i)
Call m_UtilVentanas.CloseApp(sTitulo, "CabinetWClass")
Next
Set col = Nothing
Set m_UtilVentanas = Nothing
End
End Sub
Como puedes ver, no tiene mayor misterio, ya que casi todo el trabajo lo
hace la clase.
An as, te explicar un poco el cdigo:
La funcin EnumTopWindows de la clase cWindows, devuelve una coleccin
con el ttulo de cada ventana adems del hWnd, aunque esto ltimo no lo
usamos en este caso.
Como lo que guarda EnumTopWindows son dos datos: el nombre de la
ventana y el handle, los items de la coleccin hay que recorrerlos de dos en
dos, pero como lo que nos interesa es slo el ttulo de la ventana, tomamos
ese valor y se lo pasamos a CloseApp, con el ClassName de las ventanas
del Explorer, para que slo cierre ese tipo de ventanas.
Veamos ahora una utilidad que nos mostrar las ventanas abiertas y nos
dar cierta informacin de cada una de esas ventanas, cosa que se hace al
seleccionar una de las ventanas de la lista, la informacin que nos da es:
El ttulo de la ventana (normalmente es el Caption),
el handle de esa ventana,
el ClassName de la ventana.
Adems del ListBox con los nombres de las ventanas, hay una serie de
botones para cerrar las ventanas seleccionadas del ListBox, Refrescar la
informacin de las ventanas abiertas (cosa que se podra solucionar con un
Timer, pero...), Minimizar las ventanas del IExplorer (incluidas las carpetas)
y otro para Cerrar esas carpetas.
Este es el aspecto del Formulario, (el item seleccionado es el nombre de un
directorio o carpeta):
sTitulo = .List(i)
'No cerrar esta aplicacin
If (sTitulo <> App.Title) And (sTitulo <>
Caption) Then
Call m_UtilVentanas.CloseApp(sTitulo)
DoEvents
End If
End If
Next
End With
'No se refresca bien, as que seguramente tendrs que
pulsar en el botn...
cmdRefrescar_Click
End Sub
Private Sub cmdMinimizeAll_Click()
'Cuidado!
'Si no se especifica el ClassName se minimizan todas las
ventanas,
'si tienes alguna aplicacin de VB, se minimiza una ventana
que no es el form
'y despus no se puede restaurar...
'
'por eso en este ejemplo uso "CabinetWClass" para minimizar
las carpetas
'
Call m_UtilVentanas.MinimizeAll("CabinetWClass")
End Sub
Private Sub cmdRefrescar_Click()
Call m_UtilVentanas.EnumTopWindows(List1)
With List1
Label1(1) = .ListCount
If .ListCount Then
.ListIndex = 0
End If
End With
End Sub
Private Sub cmdSalir_Click()
Unload Me
End
End Sub
Private Sub Form_Load()
Set m_UtilVentanas = New cWindows
If App.PrevInstance Then
Caption = Caption & " (otra ms)"
App.Title = App.Title & " (otra ms)"
End If
Show
cmdRefrescar_Click
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set m_UtilVentanas = Nothing
Set Form1 = Nothing
End Sub
Private Sub List1_Click()
Dim i As Long
With List1
i = .ListIndex
If i > -1 Then
Label2(0) = .List(i)
Label2(1) = .ItemData(i)
Label2(2) = m_UtilVentanas.ClassName(Label2(0))
Else
Label2(0) = ""
Label2(1) = ""
Label2(2) = ""
End If
End With
End Sub
'
'--------------------------------------------------------------------------------'Clase para manipular ventanas de Windows
(01/Ene/99)
'
'Esta clase enumera las ventas visibles, cierra la indicada,
etc.
'
'Guillermo 'guille' Som, 1999
'--------------------------------------------------------------------------------Option Explicit
Private Declare Function IsWindowVisible Lib "user32" _
(ByVal hWnd As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias
"GetWindowTextLengthA" _
(ByVal hWnd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias
"GetWindowTextA" _
(ByVal hWnd As Long, ByVal lpString As String, ByVal cch As
Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As
Long
' GetWindow() Constants
Private Const GW_HWNDFIRST = 0&
Private Const GW_HWNDNEXT = 2&
Private Const GW_CHILD = 5&
Private Declare Function GetWindow Lib "user32" _
(ByVal hWnd As Long, ByVal wFlag As Long) As Long
'
Private Declare Function FindWindow Lib "user32" Alias
"FindWindowA" _
'
numItems = col.Count
'
'
With List2
'
.AddItem col.Item(i)
'
.ItemData(.NewIndex) = col.Item(i + 1)
'
'
End With
Next
'
'Opcionalemente se puede especificar como parmetro un
ListBox o ComboBox
'y los datos se aadirn a ese control
'
Dim sTitulo As String
Dim hWnd As Long
Dim col As Collection
Set col = New Collection
If Not unListBox Is Nothing Then
unListBox.Clear
End If
'Primera ventana
Introduccin:
Aqu tienes la forma de averiguar la versin de Windows en la que se est
ejecutando tu aplicacin.
Te muestro dos formas de averiguarlo, una es usando la funcin GetVersion y la
otra es usando GetVersionEx que utiliza el tipo de datos OSVERSIONINFOEX.
Aunque en realidad son tres formas, pero dos de ellas usan la misma funcin
GetVersionEx aunque con dos versiones diferentes del tipo OSVERSIONINFO.
Para usar la versin GetVersionEx debemos declarar una variable del tipo
OSVERSIONINFO que es donde nos indica los valores de la versin. Aqu te
muestro el cdigo de forma simple, pero en el ZIP con el proyecto completo para
Visual Basic 6.0 tienes ms informacin de cmo identificar el sistema operativo
segn los valores de la versin.
Dim OSInfo As OSVERSIONINFO
Dim ret As Long
Dim s As String
OSInfo.szCSDVersion = Space$(128)
OSInfo.dwOSVersionInfoSize = Len(OSInfo)
ret = GetVersionEx(OSInfo)
s = "MajorVersion
"MinorVersion
"BuildNumber
"PlatformId
"CSDVersion
Me.txtOSVersion.Text = s
Sistema operativo
Mayor
Windows
Windows
Windows
Windows
3
4
5
6
NT 3.51
95, 98, Me y NT 4.0
2000, XP y 2003
Vista/Longhorn
Sistema operativo
Menor
Windows
Windows
Windows
Windows
Windows
Windows
Windows
Windows
Windows
51
0
10
90
0
0
1
2
0
NT 3.51
95
98
Me
NT 4.0
2000
XP
2003
Vista/Longhorn
Dim i As Long
i = InStr(s, vbNullChar)
If i Then
s = Left$(s, i - 1)
End If
s = Trim$(s)
szTrim = s
End Function
Private Function LoWord(ByVal Numero As Long) As Long
' Devuelve el LoWord del nmero pasado como parmetro
LoWord = Numero And &HFFFF&
End Function
Private Function HiWord(ByVal Numero As Long) As Long
' Devuelve el HiWord del nmero pasado como parmetro
HiWord = Numero \ &H10000 And &HFFFF&
End Function
Private Function LoByte(ByVal Numero As Integer) As Integer
' Devuelve el LoByte del nmero pasado como parmetro
LoByte = Numero And &HFF
End Function
Private Function HiByte(ByVal Numero As Integer) As Integer
' Devuelve el HiByte del nmero pasado como parmetro
HiByte = Numero \ &H100 And &HFF
End Function
Introduccion:
Pues eso, aunque estoy seguro que esto que te voy a explicar ya estoy publicado
en otra parte de mi sitio, hace un rato me hizo falta, y la verdad es que no
encontrado nada concreto, o al menos que dejara claro que era para ejecutar un
acceso directo.
Nota:
Aclarar, que al menos en teoria, este codigo vale para cualquier version de
Visual Basic de 32 bits, es decir: Visual Basic 4.0, Visual Basic 5.0 o Visual
Basic 6.0.
Si quieres ver un ejemplo para hacer lo mismo pero con Visual Basic
para .NET (o con C#), mira esto:
Ejecutar un acceso directo desde Visual Basic o C# con la clase
Process
El codigo
Y una vez hechas estas aclaraciones, veamos el codigo para que esto funcione.
Empecemos viendo la declaracion de la funcion del API ShellExecute, que como la
vamos a declarar en el propio formulario, debe estar definida como "privada":
Private 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
Ahora veamos el codigo del boton que ejecutaria lo que haya en la caja de textos
Text1:
Private Sub btnEjecutar_Click()
' Ejecutar un acceso directo
Call ShellExecute(Me.hWnd, "Open", Text1.Text, "", "", 1)
End Sub
A continuacion veamos el codigo que permite aceptar ficheros con Drag & Drop,
para que esto funcione, la propiedad OLEDropMode del formulario y del textBox
debe tener el valor 1 'Manual.
Private Sub Form_OLEDragDrop(Data As DataObject, Effect As Long, _
Button As Integer, Shift As Integer, X As Single, Y As Single)
Text1.Text = Data.Files(1)
End Sub
Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, _
Button As Integer, Shift As Integer, X As Single, Y As Single)
Text1.Text = Data.Files(1)
End Sub
Por Ultimo veremos el codigo del evento Resize del formulario en el que
posicionaremos el boton para que este en la parte de la derecha y el textBox para
que se "alargue". Los valores usados son "manuales", es decir, mira los que tenia
que usar con cada uno de los controles... es lo malo de Visual Basic 6 comparado
con Visual Basic .NET en que esto se hace automticamente, pero... eso es lo que
hay...
Private Sub Form_Resize()
If Me.WindowState = vbNormal Then
Me.Text1.Width = Me.ScaleWidth - 405
Me.btnEjecutar.Left = Me.ScaleWidth - 1470
End If
End Sub
GetCursorPos
Esta funcion sirve para saber la posicion actual del cursor, es una funcion del API
de Windows, en el caso de Visual Basic 6.0 (VB6) o anterior es la unica forma que
tenemos de averiguar ese dato, pero con los lenguajes de .NET Framework,
tambien podemos usar el metodo compartido Position de la clase Cursor que
est definida en System.Windows.Form.
La funcion del API utiliza un parametro por referencia del tipo POINT (POINT_API
que lo llamo en estos ejemplos para que no entre en conflicto con el tipo definido
en System.Drawing).
Mas abajo tienes el codigo de ejemplo para Visual Basic .NET, Visual C# y Visual
Basic 6.0 o anterior (VB6).
Las declaraciones en los tres lenguajes y segun el API de Windows son:
POINT / POINT_API
Esta es una estructura (Type en VB6) para usar con la funcin GetCursorPos.
Las declaraciones en los tres lenguajes y segn el API de Windows son:
Ejemplos
Para crear un proyecto que use este codigo debes tener un formulario con tres
etiquetas en el caso de Visual Basic .NET y Visual C# o con dos etiquetas en el
caso de Visual Basic 6.0 o anterior.
En estos codigos de ejemplo se supone que la definicion de la funcion del API y el
tipo (estructura), estn definidos en un modulo (Module) en el caso de Visual Basic
.NET, en una clase estatica en el caso de Visual C#. En el cdigo de Visual Basic
6.0 (o anterior) incluyo el cdigo completo.
Para interceptar los eventos en Visual C# debes indicarlo expresamente para que
tanto el evento MouseMove del formulario y de las tres etiquetas apunten al
mismo metodo.
En Visual Basic 6.0 y Visual Basic .NET no es necesario hacer nada especial, solo
tienes que copiar el cdigo y pegarlo en un formulario.
' GetCursorPos_VB6
(08/Jul/08)
' Ejemplo de la funcion del API GetCursorPos
'
' Guillermo 'guille' Som, 2008
'----------------------------------------------------------------------------Option Explicit
Private Type POINT_API
X As Long
Y As Long
End Type
Private Declare Function GetCursorPos Lib "user32.dll" ( _
ByRef lpPoint As POINT_API _
) As Long
Private Sub Form_MouseMove( _
Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Dim p As POINT_API
GetCursorPos p
Label1.Caption = _
"Posicion del cursor: " & vbCrLf & _
"x= " & p.X & ", Y = " & p.Y
Label2.Caption = _
"Usando los valores de los parametros: " & vbCrLf & _
"x= " & X & ", Y = " & Y
End Sub
Private Sub Label1_MouseMove( _
Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Form_MouseMove Button, Shift, X, Y
End Sub
Private Sub Label2_MouseMove( _
Label2.Text = _
"Usando GetCursorPos: " & vbCrLf & _
"x= " & p.X & ", Y = " & p.Y
Label3.Text = _
"Usando los valores del parmetro: " & vbCrLf & _
"x= " & e.X & ", Y = " & e.Y
End Sub
End Class
Module WinAPI
Public Structure POINT_API
Public X As Integer
Public Y As Integer
End Structure
'' Usando el formato compatible con VB6
'Declare Function GetCursorPos Lib "user32.dll" ( _
'
'
) As Boolean