API menús
(para VB3 o
VB4-16bits)
Fecha: 28/Jun/97
Por: Jordi Garcia Busquets [email protected]
Date sent: Mon, 9 Jun 1997
15:54:26 -0100 (GMT+1)
From: Jordi Garcia Busquets [email protected]
Hola, Guillermo!
Te adjunto un zip con la demo sobre las funciones de las API
relacionadas con el manejo de menus. En el zip te incluyo un
fichero de
texto, con una pequenya introduccion y algunos ejemplos que se
incluyen en
la demo. Coge de ahi lo que quieras, para mostrarlo en tu pagina
web.
Agradeceria pusieras mi nombre y mi e-mail (hombre, a mi tambien
me gusta que se me haga propaganda, que caramba :-))
Bueno. Ya nos veremos.
P.D.: No tuve tiempo de pasar el proyecto a VB4. Aun asi, he
incluido un
parrafo en el fichero de texto con las principales cosas que
deberian
hacerse para pasarlo a VB4. Tu mismo, organizalo como quieras.
Pulsa en este link para bajar los listados del ejemplo y el msgblast.vbx (jordigb.zip 27.5 KB)
Este es el TIP.TXT con un poco de explicación de qué va todo esto:
Usando funciones de menu de las API en Visual Basic 3.0
Los siguientes ejemplos muestran como crear menús mediante
código.
1. Añadir un menú nuevo a una ventana que no tiene menús.
hmenu = createmenu()
hmenupopup = CreatePopupMenu()
result = Appendmenu(hmenupopup, MF_STRING, 300,
"&New")
result = Appendmenu(hmenupopup, MF_STRING, 301,
"&Save")
result = Appendmenu(hmenupopup, MF_STRING, 302, "Save
&As...")
result = Appendmenu(hmenu, MF_POPUP, hmenupopup,
"&File")
result = SetMenu(Me.hWnd, hmenu)
Este ejemplo creará un menú y lo asignará a la ventana. Fijaos
en el proceso: primero
se crea el menú; luego un menú popup; luego se añaden
elementos al menú popup; luego se asigna
el menú popup al menú que hemos creado anteriormente, y
finalmente asignamos el menú a la barra
de menús del formulario. Todas las variables usadas son enteros.
2. Añadir otro menu a la misma ventana
windowmenuhandle = getmenu(Me.hWnd)
hmenupopup = CreatePopupMenu()
result = Appendmenu(hmenupopup, MF_STRING, 303,
"&Copy")
result = Appendmenu(hmenupopup, MF_STRING, 304,
"&Cut")
result = Appendmenu(windowmenuhandle, MF_POPUP, hmenupopup,
"&Edit")
Drawmenubar (Me.hWnd)
Ahora que ya tenemos un menú en la ventana, el método para
agregar un nuevo menú a la
ventana varía un poco. Concretamente, ahora no se debe usar
Setmenu, ya que perderíamos el menú
que hemos agregado anteriomente. Ahora lo que hay que hacer es
agregar el menú a la ventana
conservando el anterior. Para hacer esto se usa la función
AppendMenu. Aquí se usa la función
GetMenu para capturar el handle de la barra de menús de la
ventana. Finalmente, si queremos
ver los cambios realizados, necesitamos hacer un refresh de la
barra de menús (DrawMenuBar).
3. Modificar un ítem de un menú.
windowmenuhandle = getmenu(Me.hWnd)
hmenu = Getsubmenu(windowmenuhandle, 0)
hmenupopup = CreatePopupMenu()
result = Appendmenu(hmenupopup, MF_STRING, 308,
"Doc&1.doc")
result = Appendmenu(hmenupopup, MF_STRING Or MF_CHECKED, 309,
"Doc&2.doc")
result = modifymenu(hmenu, 2, MF_STRING Or MF_POPUP Or
MF_BYPOSITION, hmenupopup, "Save &As...
(Changed!)")
Este ejemplo modifica el ítem "Save &As..." que
creamos en el primer ejemplo, y lo
reemplaza por un menú popup de dos elementos. Fijaos en el uso
de las constantes MF_STRING,
MF_CHECKED, MF_POPUP... todas estan disponibles en el fichero de
ayuda de las API que viene
con el Visual Basic 3.0 (en VB 4.0 se pueden conseguir mediante
el Visor de las API).
Este ejemplo también serviría para poder insertar un nuevo
submenú, en vez de
modificarlo. En vez de usar ModifyMenu, debería usarse
InsertMenu.
4. Marcar y desmarcar elementos
windowmenuhandle = getmenu(Me.hWnd)
hmenu = Getsubmenu(windowmenuhandle, 1)
result = CheckMenuItem(hmenu, 0, MF_CHECKED Or MF_BYPOSITION)
Este ejemplo coloca una marca al lado del primer elemento en el
segundo menú de la ventana.
Para desmarcarlo, simplemente cabe cambiar MF_CHECKED por
MF_UNCHECKED.
5. Desabilitar un menú
windowmenuhandle = getmenu(Me.hWnd)
result = EnableMenuItem(windowmenuhandle, 0, MF_GRAYED Or
MF_BYPOSITION)
Drawmenubar (Me.hWnd)
Este ejemplo desabilita todo el primer menú de la ventana.
Haciendo esto, seremos
incapaces de ver los elementos que contiene.
6. Desplegar un menú flotante cuando se cliquea sobre la
ventana.
Sub Form_MouseDown (button As Integer, Shift As Integer, X As
Single, Y As Single)
Dim Coord As POINTAPI
Dim windowmenuhandle, hmenuFile, hmenuEdit, result As Integer
windowmenuhandle = getmenu(Me.hWnd)
hmenu = Getsubmenu(windowmenuhandle, 0)
Coord.X = X
Coord.Y = Y
Clienttoscreen Me.hWnd, Coord
result = TrackPopupMenu(hmenu, TPM_LEFTALIGN Or TPM_RIGHTBUTTON,
Coord.X, Coord.Y, 0, Me.hWnd, Null)
End Sub
Este ejemplo despliega el primer menú de la ventana cuando el
usuario hace click en la
misma. Fijaos que se usa la función ClienToScreen. Esto es así
porque los parámetros x e y del
evento mousedown son coordenadas referentes a la area cliente de
la ventana (eso es, la
posición (0,0) será la esquina superior-izquierda de la
ventana) , mientras que la función
TrackPopupMenu trabaja con coordenadas referentes a toda la
pantalla (la posición (0,0) ahora
se referirá al primer píxel superior-izquierdo de nuestro
monitor). O sea, que necesitamos
convertir estas coordenadas referentes a la area de la ventana, a
toda la pantalla entera.
Es importante recalcar que, para que el ejemplo funcione
correctamente, la propiedad
ScaleMode del formulario tiene que ponerse a 'Pixel'.
7. Borrar un menú
windowmenuhandle = getmenu(Me.hWnd)
result = DeleteMenu(windowmenuhandle, 0, MF_BYPOSITION)
Drawmenubar (Me.hwnd)
Este ejemplo elimina el primer menú del formulario.
Os dejo un fichero zip que contiene una demo con todos estos
ejemplos
y unos cuantos más, para así tener una referencia casi completa
de todas las funciones de las
API relacionadas con los menús. Esta demo usa un VBX llamado
MSGBLAST, que se usa para poder
capturar cualquier mensaje que el programa pueda recibir, y
ejecutar código en respuesta a
este mensaje. En nuestro caso lo usaremos, entre otros fines,
para poder capturar el mensaje
que se envía a la aplicación cuando se selecciona un elemento
de un menú, el mensaje WM_COMMAND.
Quizás os parezca raro que tengamos que usar un VBX para poder
ejecutar código en respuesta a
un menú. Cuando nos creamos los menús en tiempo de diseño, el
VB ya se encarga de detectar el
mensaje cuando uno de estos elementos se selecciona. Pero cuando
nos creamos los menús de cero,
no hay forma de capturar el mensaje, a menos que no sea con el
VBX. En otros lenguajes, como
Delphi o Visual C++, se puede capturar cualquier mensaje
utilizando técnicas de subclassing
(que es de hecho la tecnica que usa el VBX), sin necesidad de
usar controles adicionales.
En VB las cosas son diferentes, como todos ya sabemos.
Para pasar el proyecto a 32 bits, deberian hacerse algunas
modificaciones. Primero,
por supuesto, modificar las declaraciones de las funciones API
con sus equivalentes en 32 bits.
Normalmente habra que cambiar el nombre de la libreria y el tipo
de los parametros (los enteros
pasaran a ser longs, etc). Luego, substituir el MSGBLAST por un
OCX equivalente. Existe un OCX
que tiene la misma función. Se llama MSGHOOK. Tambien existe
MSGBLAST.OCX, pero este es de pago,
al contrario de su antecesor.
Que os cunda.