http://www.emesn.com/autoitforum/viewto ... 059#p13053
Ximorro ha contestado lo siguiente:
No sé cómo usas DllStructCreate en una función de gestión de mensaje, supongo que es para desempaquetar las dos palabras de wparam.
En principio, como su nombre indica, DllStructCreate es para crear una estructura de tipo de datos Struct de C para pasar a una DLL. Una estructura es un conjunto ordenado de varias variables (campos) que pueden ser de diferente tipo (puedes tener un número entero sin signo, un real y un carácter, por ejemplo). Los tipos son los de C, que son mucho más cercanos a la máquina que en AutoIt, por eso son más específicos.
Aunque está pensado para pasar parámetros a DLL que usan estructuras, se pueden hacer algunos trucos con ellos. Por ejemplo en una función de mensaje como la que pones wparam suele ser dos palabras de 16 bits empaquetadas en el mismo entero de 32 bits. Por ejemplo en el mensaje WM_COMMAND la primera palabra (posición alta) suele ser el código del submensaje, y la segunda (la baja) el identificador del control.
Para extraerlos sí hay otra manera, de hecho yo lo hago de otra manera: con operaciones booleanas. Por ejemplo para extraer la parte baja ponemos a cero los 16bits altos y así nos quedamos con los bajos:
$iIDFrom = BitAND($wParam, 0x0000FFFF)
(yo pongo 0xFFFF pero con los ceros se ve más claro dónde hace ceros el AND binario)
Para tomar la parte alta se hace por ejemplo un desplazamiento de 16 bits (en los desplazamientos se pierden los bits, a diferencia de las rotaciones, con lo que nos deshacemos de la palabra baja y ponemos la alta en su lugar:
$iCode = BitShift($wParam, 16)
Otra forma de hacer eso es usando una DLLStruct, yo creo que es más sencillo lo anterior, pero supongo que lo que tienes es una estructura de dos enteros de 16 bits (¿de qué tipo son? ¿short?), al rellenar esa estructura con el entero de 32 bits (wparam) puedes tomar cada una de sus partes con un DllStructGetData. Realmente ese número de 32 bits no es un número directamente, sino que es la unión de dos números de 16 bits, con la estructura se especifica esa, eeeh, estructura, valga la redundancia , y luego se extraen los campos individuales con el GetData
Espero no haber liado más la cosa...
En su momento leí esta explicación, de la que me guardé incluso el enlace:
Código: Seleccionar todo
Explicación obtenida de http://www.mirrorkarpoffespanishtutor.comxa.com/manuales/asm_win32/tut19_es.html
WM_NOTIFY
wParam == ID del control, nada garantiza que este valor sea el único, así que nosotros no lo usamos.
Es mejor usar hwndFrom o el miembro IDFrom de la estructura NMHDR a la que apunta lParam.
lParam == Puntero a la estructura NMHDR. Algunos controles pueden pasar un puntero más largo pero
debe tener una estructura NMHDR como primer miembro.
Es decir, cuando tenemos lParam, podemos estar seguros que apunta a una estructura NMHDR.
Ahora examinaremos la estructura NMHDR.
NMHDR struct DWORD
hwndFrom DWORD ?
idFrom DWORD ?
code DWORD ?
NMHDR ends
hwndFrom es el manejador de la ventana que envía este mensaje WM_NOTIFY.
idFrom es el ID del control que envía este mensaje.
code es el mensaje actual que el control quiere enviar a su ventana padre.
Desde que empecé con Autoit, he utilizado (copiado - pegado - adaptado) en varios de mis programitas funciones "personalizadas" de My_WM_COMMAND, My_WM_NOTIFY y My_WM_GETMINMAXINFO, ; bien para conocer la "reacción" de ciertos controles, bien para asegurar el tamaño mínimo de una ventana arrastrando los bordes, ... pero sin conocer exactamente su funcionamiento y el por qué de su uso.
Aunque con la explicación de Ximorro entiendo un poco mejor cómo obtener los datos, sigo sin saber quizás lo más importante: la palabra estructura ¿es esta la única manera en la que los mensajes de windows (GUIRegisterMsg) se presentan?
De hecho, al leer el mensaje de respuesta de Ximorro, he visto que en algún programa he utilizado algo como lo que propone (ver más abajo el ejemplo de My_WM_COMMAND) y sí parece más sencillo que DllStructCreate.
Por cierto ¿dónde se puede consultar un "listado" de todos los posibles "eventos" WM_NOTIFY, WM_COMMAND, WM_GETMIMAXINFO,...?
Seguiré preguntando....
----------------------------------
Pongo algunos de los ejemplos que he utilizado (copiado - pegado - adaptado) hasta la fecha:
EJEMPLO PARA "REACCIONAR" TRAS UN CLICK, DOBLE CLIC EN UN LISTVIEW (u otro control)
Código: Seleccionar todo
Func My_WM_Notify_Events($hWnd, $MsgID, $wParam, $lParam)
Local $tagNMHDR, $event, $hwndFrom, $code,$idFrom
$tagNMHDR = DllStructCreate("int;int;int", $lParam) ; Crea la estructura (hwndFrom, idFrom, code) con los datos de $lParam
If @error Then Return
$hwndFrom = DllStructGetData($tagNMHDR, 1) ; Asigna el primer valor de la estructura. Id del control HWnd($hwndFrom)
$idFrom = DllStructGetData($tagNMHDR, 2) ; Asigna el segundo valor de la estructura. Id del control GUICtrlGetHandle($idFrom)
$code = DllStructGetData($tagNMHDR, 3) ; Asigna el tercer valor de la estructura. Code
Select
Case $idFrom = $lw_direcciones_origen
Select
Case $code = $NM_DBLCLK
cw("Evento: "& $code & " en Ventana: " & $hWnd & " Control:" & $idFrom)
;msgbox(0,"",GuiCtrlRead(GuiCtrlRead($lw_direcciones_origen),1))
GUI_ConfiguraEstaciones_Origen_a_Destino()
EndSelect
Case $idFrom = $lw_direcciones_destino
Select
Case $code = $NM_DBLCLK
cw("Evento: "& $code & " en Ventana: " & $hWnd & " Control:" & $idFrom)
;msgbox(0,"",GuiCtrlRead(GuiCtrlRead($lw_direcciones_destino),1))
GUI_ConfiguraEstaciones_Destino_a_Origen()
EndSelect
EndSelect
$tagNMHDR=0
$hwndFrom=0
$idFrom=0
$code=0
EndFunc
Código: Seleccionar todo
Func My_WM_COMMAND($hWnd, $imsg, $iwParam, $ilParam)
Local $setHK = False
Local $nID = BitAND($iwParam, 0x0000FFFF) ; LoWord - this gives the control which sent the message
Local $nNotifyCode = BitShift($iwParam, 16) ; HiWord - this gives the message that was sent
Local $hCtrl = $ilParam
If $nNotifyCode = $EN_CHANGE Then
If $hCtrl = GUICtrlGetHandle($I_Filtro) Then ; Al cambiar el control $I_Filtro
sleep(800) ; Retraso para evitar que al escribir muy rápido en el cuadro de texto no de tiempo a actualizar bien la lista_origen
if $Viene_de_GUI_ConfiguraEstaciones_MostrarServicio=0 Then ; Se ejecuta sólo si el cambio de la casilla no viene de GUI_ConfiguraEstaciones_MostrarServicio()
if $Relleno_lw_direcciones_origen=1 then GUI_ConfiguraEstaciones_Filtrar() ; Sólo si $lw_direcciones_origen ya se ha rellenado
EndIf
EndIf
EndIf
Return $GUI_RUNDEFMSG
EndFunc ;==>My_WM_COMMAND
Código: Seleccionar todo
Func My_WM_GETMINMAXINFO($hWnd, $Msg, $wParam, $lParam) ; Propuesto por Ximorro (foro Autoit.es) http://www.emesn.com/autoitforum/viewtopic.php?f=4&t=2567&p=10504#p10503
; Función para asegurar un tamaño mínimo de la ventana cuando se cambia el tamaño mediante arrastre de bordes de ventana
if $hWnd = $GUI_Principal Then ; Si el mensaje viene de la ventana $GUI_Principal
#cs ; Sintaxis de la estrctura de tagMINMAXINFO
typedef struct tagMINMAXINFO {
POINT ptReserved;
POINT ptMaxSize;
POINT ptMaxPosition;
POINT ptMinTrackSize;
POINT ptMaxTrackSize;
} MINMAXINFO, *PMINMAXINFO, *LPMINMAXINFO;
#ce
Local $tMINMAXINFO = DllStructCreate("int[2];" & _ ; La primera está reservada
"int MaxSize[2];int MaxPosition[2];int MinTrackSize[2];int MaxTrackSize[2]", $lParam) ; Crea la estructura con los datos de $lParam. Como los datos que tiene MINMAXINFO son tipo POIN, en este caso los manejamos con matriz de dos elementos.
DllStructSetData($tMINMAXINFO, "MinTrackSize", 425, 1) ; Asigna el mínimo ancho (en el primer miembro de MinTrackSize), empezando por 1.
DllStructSetData($tMINMAXINFO, "MinTrackSize", 365, 2) ; Asigna el mínimo alto (en el segundo miembro de MinTrackSize), empezando por 1.
Return 0 ;No mandamos el mensaje a Windows, ya lo hemos procesado nosotros
; Return $GUI_RUNDEFMSG (variable definida en GUIConstantsEx.au3) ; Return $GUI_RUNDEFMSG en lugar de Return 0, si quisiéramos que el mensaje siguiera su curso
EndIf
EndFunc
Código: Seleccionar todo
Func MY_WM_SIZE($hWnd, $iMsg, $iwParam, $ilParam)
_GUICtrlStatusBar_Resize($BarraEstado_GUI_Principal) ; Ajusta el tamaño de la barra de estado
;_GUICtrlListView_SetColumnWidth($lw_principal, 4, $LVSCW_AUTOSIZE ) ; Ajusta el ancho de la columnaN (empezando por 0)
Return $GUI_RUNDEFMSG
EndFunc ;==>MY_WM_SIZE