Bájate los ejemplos de cajas de diálogo aquí y aquí. Bajate el ejemplo de una cajas de diálogo común aquí.
Teoría:
Hay muy poco que decir sobre como usar las cajas de diálogo como entrada-salida de nuestro programa. Tu programa crea la página principal normalmente y cuando quieres mostrar la cajas de diálogo, llamas a CreateDialogParam o DialogBoxParam. Con la llamada a DialogBoxParam, no tendrás que hacer nada mas, sólo procesar los mensajes en el procedimiento de la cajas de diálogo. Con CreateDialogParam, tendrás que insertar la llamada a IsDialogMessage en el bucle de mensajes para dejar a la cajas de diálogo el control sobre la navegación del teclado en tu cajas de diálogo. Como los dos casos son diferentes, no pondré el codigo fuente aquí. Puedes bajarte los ejemplos y examinarlos tu mismo, aquí y aquí.
Comencemos con las cajas de diálogo comunes. Windows tiene preperadas unas cajas de diálogo predefinidas que pueden ser usadas por tus aplicaciones. Estas cajas de diálogo existen para proveer un interfaz estandard de usuario. Consisten en cajas de diálogo de archivo, impresión, color, fuente, y busqueda. Deberías usarlas lo máximo posible. Las cajas de diálogo residen en comdlg32.dll. Para usarlas, tendrás que enlazar [link] el archivo comdlg32.lib. Creas estas cajas de diálogo llamando a la función apropiada en la librería de las cajas de diálogo. Para el archivo de diálogo "Abrir" [Open], se emplea la función GetOpenFileName, para la caja de diálgo "Guardar" [Save] GetSaveFileName, para dibujar un diálogo es PrintDlg y ya está. Cada una de estas funciones toma como parámetro un puntero a la estructura. Deberás mirarlo en la referencia de la API de Win32. En este tutorial, demostraré como crear y usar un diálogo "Abrir archivo" [Open file].
Debajo está
la el prototipo de la función GetOpenFileName:
GetOpenFileName proto lpofn:DWORDPuedes ver que sólo recibe un parámetro, un puntero a la estructura OPENFILENAME. El valor devuelto es TRUE que significa que el usuario a seleccionado un archivo para abrir, de otra manera devolverá FALSE. Lo siguiente que veremos será la estructura OPENFILENAME.
OPENFILENAME STRUCTVamos a ver el significado de los miembros mas utilizados de la estructura.lStructSize DWORD ?OPENFILENAME ENDS
hwndOwner HWND ?
hInstance HINSTANCE ?
lpstrFilter LPCSTR ?
lpstrCustomFilter LPSTR ?
nMaxCustFilter DWORD ?
nFilterIndice DWORD ?
lpstrFile LPSTR ?
nMaxFile DWORD ?
lpstrFileTitle LPSTR ?
nMaxFileTitle DWORD ?
lpstrInitialDir LPCSTR ?
lpstrTitle LPCSTR ?
Flags DWORD ?
nFileOffset WORD ?
nFileExtension WORD ?
lpstrDefExt LPCSTR ?
lCustData LPARAM ?
lpfnHook DWORD ?
lpTemplateName LPCSTR ?
lStructSize | El tamaño de la estructura OPENFILENAME, en bytes |
hwndOwner | El manejador (handle) de la caja de diálogo "open file". |
hInstance | Manejador (handle) de la instancia de la aplicación que crea la caja de diálogo "open file". |
lpstrFilter | Las
cadenas de filtro en formato de pares de cadenas terninadas en null (0).
La primera entre las dos es la de descripción. La segunda cadena
es el patrón de filtro. por ejemplo:
FilterString db "All Files (*.*)",0, "*.*",0 db "Text Files (*.txt)",0,"*.txt",0,0 Date cuenta que sólo el patrón en la segunda cadena de este par es usado actualmente por Windows para filtrar los archivos. Tambien date cuenta de que tienes que poner un 0 extra al final de la cadena de filtro para advertir el final de ésta. |
nFilterIndice | Especifica que par de cadenas de filtro que serán usadas inicialmente cuando la caja de diálogo "open file" es mostrada por primera vez. El índice es de base 1, que es el primer par 1, el segundo par es 2 y así el resto. En el ejemplo de arriba, si especificamos nFilterIndice como 2, será usado el segundo patrón, "*.txt". |
lpstrFile | Puntero al buffer que contiene el nombre del archivo usado para inicializar el control de edición de nombre de archivo en la caja de diálogo. El buffer será como mínimo de 260 bytes de largo. Después de que el usuario seleccione el archivo a abrir, el nombre de archivo con toda la dirección (path) es almacenado en este buffer. Puedes extraer la información de aquí mas tarde. |
nMaxFile | El tamaño del buffer lpstrFile. |
lpstrTitle | Puntero al encabezamiento o título de la caja de diálogo "open file" |
Flags | Determina el estilo y características de la caja de diálogo. |
nFileOffset | después de que el usuario haya seleccionado el archivo a abrir, este miembro contiene el índice al primer caracter del nombre de archivo actual. Por ejemplo, si el nombre completo con el directorio (path) es "c:\windows\system\lz32.dll", este miembro contendrá el valor 18. |
nFileExtension | después de que el usuario seleccione el archivo a abrir, este miembro contiene el índice al primer caracter de la extensión del archivo |
.386
.model
flat,stdcall
option
casemap:none
WinMain
proto :DWORD,:DWORD,:DWORD,:DWORD
include
\masm32\include\windows.inc
include
\masm32\include\user32.inc
include
\masm32\include\kernel32.inc
include
\masm32\include\comdlg32.inc
includelib
\masm32\lib\user32.lib
includelib
\masm32\lib\kernel32.lib
includelib
\masm32\lib\comdlg32.lib
.const
IDM_OPEN
equ 1
IDM_EXIT
equ 2
MAXSIZE
equ 260
OUTPUTSIZE
equ 512
.data
ClassName
db "SimpleWinClass",0
AppName
db "Our Main Window",0
MenuName
db "FirstMenu",0
ofn
OPENFILENAME <>
FilterString
db "All Files",0,"*.*",0
db "Text Files",0,"*.txt",0,0
buffer
db MAXSIZE dup(0)
OurTitle
db "-=Our First Open File Dialog Box=-: Choose the file to open",0
FullPathName
db "The Full Filename with Path is: ",0
FullName
db "The Filename is: ",0
ExtensionName
db "The Extension is: ",0
OutputString
db OUTPUTSIZE dup(0)
CrLf
db 0Dh,0Ah,0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
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_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
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_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,300,200,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.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_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.if ax==IDM_OPEN
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hwndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
mov ofn.lpstrTitle, OFFSET OurTitle
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke lstrcat,offset OutputString,OFFSET FullPathName
invoke lstrcat,offset OutputString,ofn.lpstrFile
invoke lstrcat,offset OutputString,offset CrLf
invoke lstrcat,offset OutputString,offset FullName
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileOffset
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
invoke lstrcat,offset OutputString,offset CrLf
invoke lstrcat,offset OutputString,offset ExtensionName
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileExtension
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
invoke MessageBox,hWnd,OFFSET OutputString,ADDR AppName,MB_OK
invoke RtlZeroMemory,offset OutputString,OUTPUTSIZE
.endif
.else
invoke DestroyWindow, hWnd
.endif
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc
endp
end
start
Rellenamos en la rutina los miembros de la estructura ofn.
mov ofn.lpstrFilter, OFFSET FilterString
Este FilterString es el filtro para el nombre de archivo que especificamos como sigue:
FilterString db "All Files",0,"*.*",0Date cuenta que las cuatro cadenas terminan en 0. La primera cadena es la descripción de la siguiente cadena. El actual patrón es la cadena par, en este caso, "*.*" y "*.txt". Actualmente podemos especificar aquí cualquier patrón que queramos. DEBEMOS poner un cero extra después de la última cadena de patrón para denotar el final de la cadena de filtro. No olvides esto sino tu caja de diálogo funcionará de forma extraña.
db "Text Files",0,"*.txt",0,0
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
Especificamos dónde la caja de diálogo pondrá el nombre del archivo que ha seleccionado el usuario. Date cuenta que tendremos que especificar su tamaño en el miembro nMaxFile. Podemos extraer más tarde el nombre del archivo de este buffer.
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
Flags especifica las características de la caja de diálogo.
Las banderas [flags] OFN_FILEMUSTEXIST y OFN_PATHMUSTEXIST demandan que el nombre de archivo y dirección (path) que el usuario pone en el control de edición (edit control) DEBEN existir.
La bandera OFN_LONGNAMES dice a la caja de diálogo que muestre nombres largos de archivo.
La bandera OFN_EXPLORER especifica que la apariencia de la caja de diálogo debe ser parecida a la del explorador.
La bandera OFN_HIDEREADONLY oculta el cuadro de selección de solo-lectura en la caja de diálogo.
Hay muchas banderas más que puedes usar. Consulta tu referencia de la API de Win32.
mov ofn.lpstrTitle, OFFSET OurTitle
Especifica el titulo o encabezado [caption] de la caja de diálogo.
invoke GetOpenFileName, ADDR ofn
Llamada a
la función GetOpenFileName. Pasando el puntero a la estructura ofn como
parámetro.
En este momento,
la caja de diálogo de abrir archivo es mostrada en la pantalla. La función
no volverá hasta que el usuario seleccione un archivo para abrir o presione
el boton de cancelar o cierre la caja de diálogo.
Devolverá
el valor TRUE en eax si el usuario selecciona un archivo para abrir. Sino devolverá
FALSE en cualquier otro caso.
.if eax==TRUE
invoke lstrcat,offset OutputString,OFFSET FullPathName
invoke lstrcat,offset OutputString,ofn.lpstrFile
invoke lstrcat,offset OutputString,offset CrLf
invoke lstrcat,offset OutputString,offset FullName
En el caso que el usuario seleccione un archivo para abrir, preparamos la cadena de salida que se mostrará en la caja de mensajes. Ubicamos un bloque de memoria en la variable OutputString y entonces usamos la función de la API, lstrcat, para entrelazar las cadenas siempre. Para poner las cadenas en varias líneas, debemos separar cada línea con el par de caracteres que alimentan el retorno de carro (13d o 0Dh) y el avance de línea (10d o 0Ah).
mov eax,ofn.lpstrFile
push ebx
xor ebx,ebx
mov bx,ofn.nFileOffset
add eax,ebx
pop ebx
invoke lstrcat,offset OutputString,eax
Las líneas de arriba requieren una explicación. nFileOffset contiene el índice dentro de ofn.lpstrFile. Pero no puedes añadirlo directamente porque nFileOffset es una variable de tamaño WORD y lpstrFile es de tamaño DWORD. Así que tendré que poner el valor de nFileOffset en la palabra baja [low word] de ebx y sumárselo al valor de lpstrFile.
invoke MessageBox,hWnd,OFFSET OutputString,ADDR AppName,MB_OK
Mostramos la cadena en la caja de mensajes.
invoke RtlZerolMemory,offset OutputString,OUTPUTSIZE
Debemos *limpiar*
el OutputString antes de poder meterle cualquier otra cadena. Así que
usamos la función RtlZeroMemory para hacer este trabajo.
[Iczelion's Win32 Assembly Homepage]
n u M I T_o r's Programming Page
Este tutorial, original de Iczelion, ha sido traducido por JoTaKe y revisado por n u M I T_o r