Aprenderemos qué son los controles comunes y cómo usarlos. Este tutorial sólo será una introducción rápida a ellos.
Bajar el ejemplo de código fuente aquí.
Windows 95 viene
con varias ampliaciones de la interface de usuario sobre Windows 3.1x. Esas
ampliaciones enriquecen la GUI. Algunas de ellas eran apliamente usadas antes de
que Windows 95 llegara a los almacenes, tales como la barra de estado [status
bar], barras de herramientas etc. Los programadores tenían que escribir el
código para estas ampliaciones. Ahora Microsoft las ha incluido con Windows 9x y
NT. Aprenderemos sobre ellas aquí.
Estos son los nuevos controles:
Ya que hay muchos, cargarlos todos en memoria y registrarlos sería un despilfarro de recursos. Todos ellos, con excepción del control "rich edit", están almacenados en comctl32.dll, desde donde las aplicaciones pueden cargarlas cuando se quiera usarlos. El control "rich edit" reside en su propia dll, richedXX.dll, porque es muy complicado y debido a que es más grande que sus hermanos.
Puedes cargar comctl32.dll incluyendo una llamada a InitCommonControls en tu programa.
InitCommonControls es una función en comctl32.dll, así que refiriéndola
en cualquier parte del código de tu programa hará que el cargador de archivos PE
cargue comctl32.dll cuando corra tu programa.No tienes que ejecutarla, sólo
inclúyela en algún lugar de tu código. ¡Esta función no hace NADA! Su
unica instrucción es "ret". Su único propósito es incluir la referencia a
comctl32.dll en la sección de importación de manera que el cargador de archivos
PE la cargue cada vez que el programa sea caragado. El verdadero caballlo de
batalla es el punto de entrada de la función en la DLL que registra todas las
clases de controles comunes cuando es cargada la dll. Los controles comunes son
creados sobre la base de esas clases así como los controles de ventana hija
tales como "edit", "listbox", etc.
El control "rich edit" es
otra cosa. Si quieres usarlo, tienes que llamar a a LoadLibrary para cargarlo
explícitamente y luego llamar a FreeLibrary para
descargarlo.
Ahora aprenderemos cómo crearlos. Puedes usar un editor de recursos para incorporarlos en las cajas de diálogo o puedes crearlos tú mismo. Casi todos los controles comunes se crean llamando a CreateWindowEx o a CreateWindow, pasando le el nombre de la clse del control. Algunos controles comunes tienen funciones de creación específicas, sin embargo, éstas son envolturas en torno a CreateWindowEx que facilitan la creación de esos controles. Las funciones de creación específicas existentes son:
|
|
|
| ToolbarWindow32 | Toolbar |
| tooltips_class32 | Tooltip |
| msctls_statusbar32 | Status bar |
| SysTreeView32 | Tree view |
| SysListView32 | List view |
| SysAnimate32 | Animación |
| SysHeader32 | Header |
| msctls_hotkey32 | Hot-key |
| msctls_progress32 | Progress bar |
| RICHEDIT | Rich edit |
| msctls_updown32 | Up-down |
| SysTabControl32 | Tab |
Los controles property sheets, property pages y image list tienen sus propias funciones de creación específicas. Los controles drag list son cajas de listas [listbox] potenciadas así que no tienen su propia clase. Los nombres de las clases de arriba pueden ser verificados chequeando el guión de recursos generado por el editor de recursos de Visual C++. Difieren de los nombres de clase que aparecen en la lista de la referencia de la api de Windows de Borland y de la lista del libro Programación en Windows 95 de Charles Petzold. La lista de arriba es la precisa.
Esos controles comunes pueden usar estilos de ventana generales tales como WS_CHILD, etc. También tienen sus estilos específicos tales como TVS_XXXXX para el control tree view, LVS_xxxx para el control list view, etc. La referencia de la api de Win32 es tu mejor amigo en este punto.
Ahora que sabemos cómo crear controles comunes, podemos ver el método de comunicación entre los controles comunes y sus padres. A diferencia de los controles de ventanas hija, los controles comunes no se comunican con el padre a través de WM_COMMAND. En vez de eso, ellos envían mensajes WM_NOTIFY a la ventana padre cuando algunos eventos interesantes ocurren con ellos. El padre puede controlar al hijo enviándoles mensajes. También hay muchos mensajes para los nuevos controles. Deberías consultar tu referencia de la api de win32 para más detalles.
Vamos ver los controles de barra de progreso [progress bar] y barra de estado [status bar] en el siguiente ejemplo.
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
.const
IDC_PROGRESS equ
1 ; IDs de los
controles
IDC_STATUS equ 2
IDC_TIMER equ 3
.data
ClassName db
"CommonControlWinClass",0
AppName
db "Common Control Demo",0
ProgressClass db
"msctls_progress32",0 ; el nombre de la
clase de la barra de progreso
Message db
"Finished!",0
TimerID dd 0
.data?
hInstance HINSTANCE ?
hwndProgress
dd ?
hwndStatus dd ?
CurrentStep
dd ?
.code
start:
invoke GetModuleHandle,
NULL
mov
hInstance,eax
invoke WinMain,
hInstance,NULL,NULL, SW_SHOWDEFAULT
invoke
ExitProcess,eax
invoke
InitCommonControls
WinMain proc
hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL
hwnd:HWND
mov wc.cbSize,SIZEOF
WNDCLASSEX
mov wc.style,
CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov
wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_APPWORKSPACE
mov
wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke
LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke
LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke
RegisterClassEx, addr wc
invoke
CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR
AppName,\
WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov
hwnd,eax
.while
TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF
(!eax)
invoke
TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR
msg
.endw
mov eax,msg.wParam
ret
WinMain
endp
WndProc proc
hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if uMsg==WM_CREATE
invoke
CreateWindowEx,NULL,ADDR ProgressClass,NULL,\
WS_CHILD+WS_VISIBLE,100,\
200,300,20,hWnd,IDC_PROGRESS,\
hInstance,NULL
mov
hwndProgress,eax
mov
eax,1000
; the lParam of PBM_SETRANGE message contains the range
mov
CurrentStep,eax
shl
eax,16
; the high range is in the high word
invoke
SendMessage,hwndProgress,PBM_SETRANGE,0,eax
invoke
SendMessage,hwndProgress,PBM_SETSTEP,10,0
invoke
CreateStatusWindow,WS_CHILD+WS_VISIBLE,NULL,hWnd,IDC_STATUS
mov
hwndStatus,eax
invoke
SetTimer,hWnd,IDC_TIMER,100,NULL ;
crear un temporizador
mov
TimerID,eax
.elseif
uMsg==WM_DESTROY
invoke
PostQuitMessage,NULL
.if
TimerID!=0
invoke KillTimer,hWnd,TimerID
.endif
.elseif
uMsg==WM_TIMER
; cuando ocurre un
evento de temporizador
invoke
SendMessage,hwndProgress,PBM_STEPIT,0,0 ; incrementar el
progreso en la barra de progreso
sub
CurrentStep,10
.if
CurrentStep==0
invoke KillTimer,hWnd,TimerID
mov
TimerID,0
invoke SendMessage,hwndStatus,SB_SETTEXT,0,addr Message
invoke MessageBox,hWnd,addr Message,addr
AppName,MB_OK+MB_ICONINFORMATION
invoke SendMessage,hwndStatus,SB_SETTEXT,0,0
invoke SendMessage,hwndProgress,PBM_SETPOS,0,0
.endif
.else
invoke
DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor
eax,eax
ret
WndProc
endp
end start
Si esta llamada tiene éxito, regresará el TimerID. Si falla, regresa 0. Esto se debe a que el valor del ID del temporizador debe ser diferente a cero.
[Iczelion's Win32 Assembly Homepage]
n u M I T_o r's Programming Page
Este tutorial, original de Iczelion, ha sido traducido por: n u M I T_o r