Bueno bueno, este post es muy interesante. Está bien el código de Melba. Yo os voy a dar otra solución. Creía que iba a ser efectiva pero me he encontrado con un par de problemas (sobre todo uno) que no me han gustado.
Hace tiempo me bajé una udf de rasim (ayudado por arcker y MrCreatoR). Se trata de una udf que inserta objetos progress en los items de los listview. Logicamente tiene funciones para tratar estos progress. La dirección es:
http://www.autoitscript.com/forum/topic ... w_progress
Bueno, vamos a lo que nos interesa en este post. La forma en la que hace esto es, a groso modo, utilizando el listview con objeto padre, y a los objetos progress como hijos (api de win, mirar el código). Una vez que están insertados, los posiciona y los redimensiona tratando los mensajes de windows $wm_notify y $wm_size que afectan al listview.
Igual que puedes insertar un progress, puedes insertar cualquier objeto (edit, button, combo, etc). En este caso nos interesa insertar edits en cada item/subitem.
Pues variando algo el código de alguna de sus funciones, decidí ver que pasaba si intentaba insertar un edit en cada item. El código es este (está algo chapucerillo
):
Código: Seleccionar todo
; ------ Includes ------
; Para manejar base de datos SQLite
#include <sqlite.au3>
#include <sqlite.dll.au3>
; Constantes de controles
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <winapi.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <GuiEdit.au3>
; Matrices
#include <Array.au3>
; ------ Opciones ------
;~ Opt("MustDeclareVars",1)
Global $aProgress[1][4]
Global Const $SW_HIDE = 0
Global Const $SW_SHOW = 5
Global $NombreBD=@ScriptDir&"\"&'Prueba_inputs.db3'
AbreBD($NombreBD)
Global $aResult, $iRows, $iColumns
Global $sCommand
Global $Tabla="Empresa" ; <<<<<<<<<<<<<<< En la BD de ejemplo están las tablas "Empresa" y "Cliente"
;~ Global $Tabla="Cliente" ; <<<<<<<<<<<<<<< En la BD de ejemplo están las tablas "Empresa" y "Cliente"
Global $Orden="Telefono"
if $Orden<>"" Then
$sCommand="SELECT * FROM " & $Tabla & " ORDER BY "&$Orden&";"
Else
$sCommand="SELECT * FROM " & $Tabla &";"
EndIf
If _SQLite_GetTable2d(-1,$sCommand,$aResult,$iRows,$iColumns) <> $SQLite_OK Then ; no puede hacer la consulta - puede estar encriptada o no ser una base de datos SQLite
MsgBox(16,"Error","Este archivo no parece ser una base de datos SQLite válida.")
Exit
EndIf
ConsoleWrite("Filas="& $iRows & " Columnas=" & $iColumns & @CRLF)
;_ArrayDisplay($aResult)
; GUI Principal
Global $hGUIppal=GUICreate("Principal", 100*$iColumns+130, 550)
GUISetBkColor(0x88AABB, $hGUIppal)
$hListView = GUICtrlCreateListView("", 10, 10, 400, 180, BitOR($LVS_REPORT, $WS_BORDER),$LVS_EX_GRIDLINES)
For $n=0 to $iColumns-1
$item1 = _GUICtrlListView_AddColumn($hlistview,$aResult[0][$n],70)
Next
For $n=0 to $iRows-1
$item1 = _GUICtrlListView_AddItem($hlistview,"")
Next
Global $input[$iRows][$iColumns]
; Añade los Inputs
For $i = 0 To $iRows-1 ; La fila 0 contiene los títulos de las columnas
For $j = 0 To $iColumns-1
$input[$i][$j]=_ListView_InsertProgressBar($hListView, $i, $j)
_GUICtrlEdit_SetText($input[$i][$j],$aResult[$i+1][$j])
;~ If Mod($i, 2) = 0 Then
;~ GUICtrlSetBkColor (-1,0xAAFFAA)
;~ Else
;~ GUICtrlSetBkColor (-1,0xFFFFFF)
;~ EndIf
Next
Next
GUISetState()
GUIRegisterMsg($WM_NOTIFY, "_ListView_Notify")
GUIRegisterMsg($WM_SIZE, "_ListView_Notify")
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
CierraBD($NombreBD)
Exit
EndSwitch
WEnd
Func AbreBD($NombreBD)
; Apertura de BD
Local $hQuery, $aRow, $sMsg
_SQLite_Startup()
ConsoleWrite("_SQLite_LibVersion=" &_SQLite_LibVersion() & @CR)
;_SQLite_Open()
_sqlite_open($NombreBD)
EndFunc
Func CierraBD($NombreBD)
_SQLite_Close($NombreBD)
_SQLite_Shutdown()
EndFunc
Func _ListView_InsertProgressBar($sHwnd, $sItemIndex, $sSubItemIndex = 0)
If Not IsHWnd($sHwnd) Then $sHwnd = GUICtrlGetHandle($sHwnd)
Local $iStyle = _WinAPI_GetWindowLong($sHwnd, $GWL_STYLE)
If BitAND($iStyle, $WS_CLIPCHILDREN) <> $WS_CLIPCHILDREN Then
_WinAPI_SetWindowLong($sHwnd, $GWL_STYLE, BitOR($iStyle, $WS_CLIPCHILDREN))
EndIf
Local $aRect
If $sSubItemIndex = 0 Then
$aRect = _GUICtrlListView_GetItemRect($sHwnd, $sItemIndex, 2)
Else
$aRect = _GUICtrlListView_GetSubItemRect($sHwnd, $sItemIndex, $sSubItemIndex)
EndIf
$aProgress[0][0] += 1
ReDim $aProgress[$aProgress[0][0] + 1][4]
$aProgress[$aProgress[0][0]][0] = _Progress_Create($sHwnd, $aRect[0]+1, $aRect[1]+1, $aRect[2] - $aRect[0]-2, $aRect[3] - $aRect[1]-2)
$aProgress[$aProgress[0][0]][1] = $sItemIndex
$aProgress[$aProgress[0][0]][2] = $sSubItemIndex
$aProgress[$aProgress[0][0]][3] = $sHwnd
Return $aProgress[$aProgress[0][0]][0]
EndFunc ;==>_ListView_InsertProgressBar
Func _Progress_Create($hWnd, $iX, $iY, $iWidth = -1, $iHeight = -1, $iStyle = 0, $iExStyle = 0)
$iStyle = BitOR($iStyle, $WS_CHILD, $WS_VISIBLE)
Return _WinAPI_CreateWindowEx($iExStyle, "edit", "", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd)
EndFunc ;==>_Progress_Create
Func _ListView_Notify($hWnd, $Msg, $wParam, $lParam)
If $Msg = $WM_SIZE Then
_WinAPI_InvalidateRect($hWnd)
Return $GUI_RUNDEFMSG
EndIf
Local $tNMHEADER, $hWndFrom, $iCode, $i
$tNMHEADER = DllStructCreate($tagNMHEADER, $lParam)
$hWndFrom = DllStructGetData($tNMHEADER, "hwndFrom")
$iCode = DllStructGetData($tNMHEADER, "Code")
Switch $iCode
Case $HDN_ITEMCHANGED, $HDN_ITEMCHANGEDW, $LVN_ENDSCROLL
If $iCode <> $LVN_ENDSCROLL Then $hWndFrom = _WinAPI_GetParent($hWndFrom)
For $i = 1 To $aProgress[0][0]
If $aProgress[$i][3] = $hWndFrom Then _
_MoveProgress($hWndFrom, $aProgress[$i][0], $aProgress[$i][1], $aProgress[$i][2])
Next
_WinAPI_InvalidateRect($hWndFrom)
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>_ListView_Notify
Func _MoveProgress($hListView, $hProgress, $sItemIndex, $sSubItemIndex)
Local $aRect
If $sSubItemIndex = 0 Then
$aRect = _GUICtrlListView_GetItemRect($hListView, $sItemIndex, 2)
Else
$aRect = _GUICtrlListView_GetSubItemRect($hListView, $sItemIndex, $sSubItemIndex)
EndIf
If $aRect[1] < 10 Then
_WinAPI_ShowWindow($hProgress, $SW_HIDE)
ElseIf $aRect[1] >= 10 Then
_WinAPI_ShowWindow($hProgress, $SW_SHOW)
EndIf
_WinAPI_MoveWindow($hProgress, $aRect[0]+1, $aRect[1]+1, $aRect[2] - $aRect[0]-2, $aRect[3] - $aRect[1]-2, True)
EndFunc ;==>_MoveProgress
He cambiado en un pixel la posición y redimensión de los controles para que se viesen las líneas de la tabla. Recordad que se necesita en el mismo lugar donde esté este código, la bbdd del que nos proporcionó jamaro. Dejo un archivo zip con el código y la base de datos.
Los dos problemas que me encontré: Primero y más importante, algo de lentitud a la hora de manejar el listview (scroll). Segundo, me fijé que algunas veces, al cambiar el tamaño de las columnas, la información de los edits no se redibujaba bien y aparecía cortada. Solución a esto último, redibujar el listview en los debidos momentos. Lo dejo dicho por si alguien lo quiere hacer
.
Conclusión: Eso de que se relentize un poco el scroll no me hace mucha gracia. Y ya no os quiero ni contar si le metemos muchos más items e inputs
.
En definitiva, es una bonita opción ya que se puede meter cualquier objeto, pero con un número determinado de éstos. Autoit no está preparado para hacer este tipo de cosas. Se necesitaría un lenguaje mucho más potente y rápido.
Siempre te queda la posibilidad de intentar encontrar un control grid gratuíto que tenga esta propiedad y se lleve bien con AutoIt . Si buscas y encuentras alguno dinoslo.
Ahora jamaro te voy a decir lo que yo haría (más bien lo que he hecho varias veces en vb6 cuando manejaba bbdd
).
Fíjate, con todos los grid que tenía en vb6, yo solía hacer esto. Te pongo un gui hecho con koda para que lo entiendas mejor:
Código: Seleccionar todo
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 625, 443, 192, 124)
$Group1 = GUICtrlCreateGroup("Group1", 8, 320, 609, 113)
$Input1 = GUICtrlCreateInput("Input1", 24, 368, 97, 21)
$Input2 = GUICtrlCreateInput("Input2", 144, 368, 97, 21)
$Input3 = GUICtrlCreateInput("Input3", 264, 368, 97, 21)
$Input4 = GUICtrlCreateInput("Input4", 384, 368, 97, 21)
$Input5 = GUICtrlCreateInput("Input5", 504, 368, 97, 21)
$Label1 = GUICtrlCreateLabel("Label1", 24, 344, 36, 17)
$Label2 = GUICtrlCreateLabel("Label2", 144, 344, 36, 17)
$Label3 = GUICtrlCreateLabel("Label3", 264, 344, 36, 17)
$Label4 = GUICtrlCreateLabel("Label4", 384, 344, 36, 17)
$Label5 = GUICtrlCreateLabel("Label5", 504, 344, 36, 17)
$Label6 = GUICtrlCreateLabel("1", 264, 405, 100, 17, $SS_CENTER)
$Button1 = GUICtrlCreateButton("<", 232, 400, 33, 25, $WS_GROUP)
$Button2 = GUICtrlCreateButton(">", 364, 400, 33, 25, $WS_GROUP)
$Button3 = GUICtrlCreateButton("Guardar", 504, 400, 81, 25, $WS_GROUP)
$Button4 = GUICtrlCreateButton("Borrar", 48, 400, 75, 25, $WS_GROUP)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$ListView1 = GUICtrlCreateListView("1 columna|2 columna|3 columna|4 columna|5 columan", 8, 16, 609, 297)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 100)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 100)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 100)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 3, 100)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 4, 100)
$ListView1_0 = GUICtrlCreateListViewItem("1 item", $ListView1)
$ListView1_1 = GUICtrlCreateListViewItem("2 item", $ListView1)
$ListView1_2 = GUICtrlCreateListViewItem("3 item", $ListView1)
$ListView1_3 = GUICtrlCreateListViewItem("4 item", $ListView1)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd
Como puedes observar arriba pongo un listview normal con los registros de la bbdd.
Abajo pongo un marco con tantos inputs como campos editables tenga la bbdd (también, en vez ponerlos en la misma ventana, puedes hacer que se abra otra ventana con todos estos controles). En estos inputs deben aparecer los datos del item (registro) que esté seleccionado en la listview. También te he puesto unos botones. Puedes poner tantos como funciones necesites (guardar/actualizar registro/bbdd, limpiar contenido de los inputs, borrar registro, etc). Yo me voy a centrar en el de editar el registro. Este botón al pulsarse debe cambiar el registro de la bbdd y la listview con los nuevos datos. Te recomiendo que cambies el item de la listview directamente, y no recargando la bbdd con el nuevo registro, ya que sería más lento.
Ahora voy a hablar de los controles opcionales que he puesto abajo del todo. Digo opcionales porque no los veo necesarios para hacer lo anterior. Sería rizar el rizo
. Se trata de un label y 4 botones (sí, 4, se me olvidaron poner dos a cada lado de los que ya hay puestos
).
El label debe reflejar el número de registro (item) actual de la lista, que será el mismo que el registro de la bbdd. También puedes hacer como yo hacía, y era poner número registro actual/total registros (Ejemplo "4/245"). Para hacer esto, cada vez que cambies a un item distinto de la lista, se debe actualizar.
Ahora los 4 botones. Los botones "<" y ">" nos mueven para alante y atrás un registro cada vez que se pulsan. Tienen que estar coordinados con el listview y el label, para poder actualizarlos. Los otros dos botones que se me han olvidado serían "<<" y ">>", que nos trasladarían al registro inicial y final respectivamente.
También tienes que controlar cuando llegan al primer y último registro.
Puede que cueste algo programarlos (más tiempo que dificultad) y no te merezca la pena. Como he dicho antes, esto no es necesario.
Menudo rollo te he metido. Espero que por lo menos te haya dado alguna idea.
Saludos.