API menús
(para VB3 o VB4-16bits)

Fecha: 28/Jun/97
Por: Jordi Garcia Busquets
jordi@hades.udg.es


Date sent: Mon, 9 Jun 1997 15:54:26 -0100 (GMT+1)
From: Jordi Garcia Busquets
jordi@hades.udg.es

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.


ir al índice