• No se han encontrado resultados

Hoy en día la mayoría de las aplicaciones para Windows tienen menús. Es realmente sencillo trabajar con ellos con C#.

N/A
N/A
Protected

Academic year: 2021

Share "Hoy en día la mayoría de las aplicaciones para Windows tienen menús. Es realmente sencillo trabajar con ellos con C#."

Copied!
15
0
0

Texto completo

(1)

Menús

Hoy en día la mayoría de las aplicaciones para Windows tienen menús. Es realmente sencillo trabajar con ellos con C#.

Hay tres tipos de menús y los tres derivan de una clase común, denominada Menu, que

proporciona la funcionalidad básica y común a las tres. En la figura 17.1 se puede apreciar la jerarquía de estas clases.

Figura 17.1. Jerarquía de las clases para el trabajo con menús.

Las clases MainMenu y MenuItem

MainMenu es el menú principal. Un formulario puede tener definidos varios menús

principales, dependiendo del estado de algunas variables de la aplicación. Estos menús pueden unirse entre sí.

Cada uno de los elementos o items o submenús –ya sean de primer o segundo nivel- de cada menú son objetos de la clase MenuItem. Estos elementos, a su vez, pueden

contener otros objetos o submenús. Todos los elementos u objetos de un menú son almacenados en la colección MenuItemCollection que es una propiedad de las clases MainMenu y ContextMenu.

Los menús contextuales o también llamados menús PopUp se despliegan generalmente

cuando se pulsa sobre un control con el botón derecho. Al igual que los MainMenu

MainMenu ContextMenu MenuItem

Object

MarshalByRefObject

MarshalByRefComponent

(2)

pueden contener varios elementos MenuItem. A continuación se estudiarán las

propiedades más importantes de la clase MenuItem. Posteriormente se estudiarán los

menús PopUp y se realizará un ejemplo básico.

Propiedades

Checked y

RadioChecked Propiedad booleana. Indica si un elemento aparece activado con un

elemento tipo Check o RadioCheck. Para que éste último tenga

funcionalidad debe estar a True la propiedad Checked.

DefaultItem Propiedad booleana. Indica si es el elemento por defecto o

predeterminado. Se escribe en letra negrita.

Enabled Propiedad booleana. Indica si está habilitada o no esa opción de

menú.

MdiList Propiedad booleana. Indica si la lista de ventanas hijas MDI se

añadirá a este item.

MergeOrder Indica el orden donde será ubicado el menú. MergeType Indica el tipo de unión de los menús.

OwnerDraw Propiedad booleana. Indica si será Windows o el programador el

responsable de dibujar el item o elemento de menú.

ShortCut Indica la combinación de teclas o acceso directo asociado con ese

elemento.

ShowShortCut Propiedad booleana. Indica si aparece escrito a la derecha del item la

combinación de teclas asociada al item.

Text Texto del elemento.

Visible Indica si un item es visible o no. Es un propiedad booleana.

Eventos

Click Ocurre cuando se pulsa un item con el ratón. DrawItem Ocurre si un item de menú necesita ser redibujado. MeasureItem Ocurre justo antes de que sea redibujado un item. PopUp Ocurre cuando se presentan en pantalla un submenú. Select Ocurre cuando se selecciona un item del menú.

Hay además dos métodos interesantes de esta clase: CloneMenu que permite crear un

nuevo menú a partir de otros existentes y MergeMenu que permite unir dos menús.

Para trabajar con menús se utiliza la clase MenuItemCollection que almacena los

elementos de cada menú. Para añadir y eliminar elementos de menú a MainMenu o

ContextMenu se utilizan los métodos de esta colección.

La clase ContextMenu

Es el menú que aparece cuando se pulsa con el botón derecho del ratón. Se trabaja de la misma manera que un MainMenu con la única diferencia de que no existe un nivel

(3)

principal de items y por lo tanto no se puede nombrar el principal. Los menú PopUp

contienen también objetos de la clase MenuItem.

Una vez diseñado el menú es necesario asociarlo a un control o a un formulario por medio de la propiedad ContextMenu del control.

Ejemplo: Trabajando con menús.

Como en los demás casos, es posible añadir un menú a un formulario de dos modos: Escribiendo directamente el código o bien mediante el asistente de Visual Studio. En la práctica, casi siempre se trabajará con esta segunda opción.

A continuación se implementa una aplicación en la cual se desea escribir un determinado texto en una caja de texto por medio de la pulsación de un botón o a través de un menú. Para ello:

• Cree un proyecto llamado HolaMundoConMenu.

• Añada un botón con sus propiedades Name y Text a btnAceptar y Aceptar

respectivamente. Añada una caja de texto vacía de propiedad Nametexto. Escriba el

código necesario para que al pulsar sobre el botón btnAceptar se escriba en la caja

de texto una determinada frase, por ejemplo, “Zidane es el mejor jugador del planeta”.

private void btnAceptar_Click_1(object sender, System.EventArgs e)

{

texto.Text="Zidane es el mejor jugador del planeta"; }

• Añada el control MainMenu. Este control no es visible en tiempo de diseño. Cuando

se añada al formulario se sitúa en la parte inferior del IDE que Visual Studio utiliza para almacenar este tipo de controles. Con esto, el IDE indica que son controles que no forman parte directa del diseño gráfico de la aplicación. Sin embargo, con estos controles se trabaja de manera parecida al resto de los controles. En realidad se sitúan aquí todos los controles cuyas clases no derivan de la clase Control como Menu, ImageList, Time, ToolTip, etc.

• En la parte superior izquierda del formulario aparece un asistente para crear las opciones de menú. Para ello, debe estar seleccionado el control MainMenu que se ha

(4)

Figura 17.2. Añadiendo un control MainManu al formulario.

Para añadir nuevas opciones de menú –submenús- sólo hay que hacer “doble click” sobre las opciones de menú en las que está escrito “Escriba aquí”. Para añadir el código de manejo de los eventos de menú se ha de hacer igual que con los botones de comando, es decir, a través de la ventana propiedades o haciendo doble click en la opción de menú. A modo de ejemplo se añade una opción de menú de primer nivel llamada “Archivo”, que tendrá otras dos segundo nivel: la primera que ejecute lo mismo que el botón btnAceptar y que lleva el texto “Ejecutar botón Aceptar” y la segunda que cierre la aplicación, “Salir”. Para dibujar una línea que divida en regiones

(5)

Figura 17.3. Diseñando un menú. Línea separadora. Menu 2.bmp

Para asignar el mismo método al menú que al botón, seleccione la opción de menú “Ejecutar botón Aceptar” y en la ventana de propiedades, pulse sobre el icono

“eventos” y seleccione el evento click. Aparecerá un control ComboBox que le permitirá

definir el método manejador de este evento entre los que hasta ahora están escritos. Seleccione btnAceptar_Click (Figura 17.4).

Figura 17.4. El evento Click del menú y del botón son manejados por el mismo

(6)

No se añadirá ningún código, pero se asocia este evento al método. Compruebe que el código de la aplicación aparecen las dos líneas siguientes:

this.btnAceptar.Click += new System.EventHandler(this.btnAceptar_Click);

this.menuItem2.Click += new System.EventHandler(this.btnAceptar_Click);

que indican que los eventos btnAceptar.Click y menuItem2.Click del formulario

serán manejados ambos por el método btnAceptar_Click.

Para salir de la aplicación al pulsar la opción Salir (menuItem4), habrá que

implementar el método menuItem4_Click. Para ello, con esta opción de menú

seleccionada, pulse sobre el icono de Eventos en la ventana de propiedades y seleccione el evento Click. Haga doble click sobre él y escriba el siguiente código: private void menuItem4_Click(object sender, System.EventArgs e) {

Application.Exit(); }

Se utiliza el método estático Exit() de la clase Application, que provoca que se

salga de la aplicación.

Ejecúte la aplicación y compruebe las distintas posibilidades.

Nota: Observe que en la propiedad Menu, de la ventana de propiedades del formulario

aparece mainMenu1 que es el menú asociado al formulario. Si se define otro menú, se puede cambiar esta propiedad en tiempo de ejecución, de modo que se pueden tener varios menús asociados a un determinado formulario.

(7)

La clase ImageList

Este control proporciona una colección para almacenar imágenes que puede ser utilizadas en otros controles como una caja de herramientas o un ListView. Aunque

puede almacenar imágenes de cualquier tamaño, las que se añaden a un mismo control deben tener –en general- el mismo. Sin embargo, en el caso del control ListView –y a

veces las cajas de herramientas- es preciso almacenar dos tipos de tamaños de imágenes. Este control no es visible en tiempo de diseño ni en tiempo de ejecución, aunque se le pueden añadir imágenes en tiempo de diseño y en tiempo de ejecución.

La clase ToolBar

Los controles ToolBar se usan para construir una barra de herramientas. Un buen

ejemplo lo constituye la barra de herramientas del Word 2000 (figura 17.5)

Figura 17.5. Barra de herramientas del Word 2000

Una barra de herramientas contiene, por lo general, varios controles de la clase

ToolBarButton que pueden aparecer como botones estándar –como por ejemplo los botones Abrir, Guardar, ...-, controles ComboBox –como el tipo de letra- botones

desplegables –como los iconos color de la letra, resaltar o ayuda- , botones

ToogleButton o de dos posiciones o de ON/OFF –como el tipo de alineación del

párrafo, y botones con texto, imagen o ambos. Además, normalmente suelen disponer de una pequeña etiqueta o ToolTip, con una breve descripción de la función del botón.

En general, las barras de herramientas sirven para acceder de manera más rápida y gráfica a algunos de los elementos más importantes o más utilizados de un menú.

Se puede asociar imágenes a cada uno de los botones a través de un objeto ImageList,

asignando el índice de cada imagen a la propiedad ImageIndex del botón. También se

puede asignar un texto a la derecha o en la parte inferior del botón a través de la propiedad Text del ToolBarButton.

La apariencia de la barra de herramientas viene definida por la propiedad Appearance.

Por ejemplo, puede ser la apariencia normal o Flat que es el aspecto exterior que tiene la barra de herramientas de Visual Studio .NET o el Word 2000 de Microsoft, donde los botones no tienen relieve, pero que al pasar con el ratón sobre ellos, adquieren un aspecto tridimensional. Los botones de la caja de herramientas se pueden agrupar en

(8)

unidades lógicas utilizando los separadores. Un separador es un botón de la barra de herramientas con la propiedad Style en Separator.

Para crear una colección de botones de la barra de herramientas se ha de utilizar la propiedad Buttons de dicho control. Es posible añadir o eliminar controles en tiempo

de diseño o utilizando los métodos Add o Insert de la propiedad Buttons.

Esta clase deriva de Control y por lo tanto hereda todas sus propiedades, métodos y eventos. Además tiene otras propiedades muy útiles:

Propiedades

Buttons Es una colección que contiene los botones de la barra de herramientas –

de la clase ToolBarButton-.

ImageList Es una colección que contiene las imágenes de los botones de la barra

de herramientas.

ShowToolTips Propiedad booleana. Permite que aparezcan las pequeñas etiquetas

(ToolTips) con alguna explicación de la acción de cada botón.

Wrappable Propiedad booleana. Permite que si la barra de herramientas es muy

grande, se amplíe a otra línea de botones.

ButtonSize Determina el tamaño de los botones en la barra de herramientas.

Eventos

Además de los eventos que hereda de la clase Control, hay dos que tienen especial

importancia y son específicos de este control:

ButtonClick Ocurre siempre que se pulsa un botón de la barra de herramientas.

En el método auditor de este evento se pasan dos parámetros. El primero, sender es el objeto que ha generado el evento y el otro es

un objeto de la clase ToolBarButtonClickEventArgs que

encapsula información sobre el evento. Para determinar qué botón – de la clase ToolBarButton- de la barra de herramientas se ha

pulsado se puede utilizar la propiedad Button de esta clase que

devuelve el botón pulsado. Es el evento por defecto.

ButtonDropDrown Ocurre cuando se pulsa un botón de la barra de herramientas con la

propiedad Style a DropDownButton. Para determinar el botón

que se ha pulsado se procede como en el caso anterior.

Los botones de la barra de herramientas son una colección de objetos de la clase

ToolBarButton que se asocian a la barra por medio de la propiedad Buttons. Este es

un procedimiento muy sencillo en tiempo de diseño porque Visual Studio proporciona un editor para añadir botones a la colección. A continuación se estudian este tipo de botones.

(9)

La clase ToolbarButton

Los objetos de esta clase son los controles que se ubican en la barra de herramientas. Esta clase no deriva de la clase Control, sino directamente de la clase Component.

Propiedades

Esta clase permite configurar para cada botón de la caja de herramientas la imagen, estilo, texto y ToolTip. A través de ellos se puede configurar un botón “desplegable”

como, por ejemplo los dos botones situados en la parte superior derecha de la barra de herramientas del Visual Studio .NET.

Las propiedades más importantes son:

DropDownMenu Asigna un menú de tipo PopUp a un botón “desplegable”. Para ello,

debe tener la propiedad Style a DropDownButton-. ImageIndex Contiene el índice de la imagen del botón.

Style Es el estilo del botón.

Text La etiqueta o texto –opcional- del botón en la barra de herramientas. ToolTipText Es el texto de la etiqueta explicativa del botón. Para ello, la barra de

herramientas debe tener la propiedad ShowToolTips a True.

ParcialPush Sólo tiene sentido con la propiedad Style a ToogleButton. Si es True, los botones están en gris, indicando que están inhabilitados. Pushed Propiedad booleana. Indica si el botón está pulsado o no (ON/OFF).

Para controlar los eventos sobre la barra de herramientas, se procede como en los demás controles.

Cuando se desea determinar qué botón ha sido pulsado, se utiliza la propiedad Button -

que devuelve el botón que se ha pulsado- de la clase ToolBarButtonClickEventArgs

que se ha pasado al auditor del evento.

Ejemplo: Construyendo una barra de herramientas.

A continuación se desea implementar un apalicación con una barra de herramientas. El aspecto final de esta aplicación es el de la figura 17.7.

Para ello. se deben seguir los siguientes pasos:

• Cree un nuevo proyecto para una Aplicación Windows y llámele

ProyectoBarraDeHerramientas.

• Cambie el nombre de la clase que define a la aplicación de Form1 a FormularioPrincipal. Para ello, seleccione Form1 en la ventana Vista de clases y

en la ventana de propiedades cambie la propiedad Name de la clase a FormularioPrincipal.

(10)

• Aunque no es necesario hacerlo así, cambie también el nombre del fichero de la clase, para que coincida con el de la clase. Para ello, o bien en la ventana

Explorador de Soluciones seleccione el fichero Form1.cs, pulse el botón derecho

del ratón y seleccione la opción del menú contextual “Cambiar nombre” o bien con

Form1.cs seleccionado en el Exploracdor de Soluciones, en la Ventana de

propiedades modifique la propiedad “Nombre de archivo” a

FormularioPrincipal.cs.

• Al menos, en la versión beta es necesario cambiar en el código del formulario la línea:

Application.Run(new Form1());

por la línea

Application.Run(new FormularioPrincipal());

• Este es un buen momento para salvar la aplicación.

• Añada un control ImageList al formulario. Se ubicará en una zona destinada a los

controles no visuales. Modifique la propiedad Name a imagenes.

• Añada cuatro imágenes a la colección de imágenes que está definida en la propiedad

Images del control. Pulse en el pequeño botón situado a la derecha del nombre de la

palabra Collection de la propiedad Images y se abrirá un editor para añadir o

eliminar imágenes a la colección de imágenes del control. Para añadir una imagen, pulse el botón Agregar del editor y escoja desde, por ejemplo, C:\Archivos de programa\Microsoft Visual Studio.NET\Common7\Graphics\icons\Misc los

iconos MISC06.ICO, MISC05.ICO, MISC04.ICO y TIMER01.ICO. Pulse el botón Aceptar para cerrar el editor. En caso de equivocación, puede eliminar una imagen

seleccionándola y pulsando Quitar o puede cambiarse la ubicación relativa de las

imágenes en la colección por medio de las flechas.

• Añada tres ContextMenu que posteriormente serán los menús que se desplieguen al

pulsar en uno de los botones, en la barra de herramientas y en el formulario respectivamente y cambie sus propiedades Name a menuPopUpBoton, menuPopUpBarra y menuPopUpFormulario y añada respectivamente las siguientes

opciones a cada menú:

Hora de Londres, Hora de Los Angeles, Hora de Moscú. Arriba, Abajo, Izquierda, Derecha.

Ver barra de herramientas, Ocultar barra de herramientas.

Añada un control ToolBar al formulario. Por defecto se sitúa en la parte superior de

éste, aunque puede ubicarse en cualquier otro lugar modificando la propiedad Dock. Modifique o defina las siguientes propiedades de la barra de herramientas:

Name barra Appearance Flat BorderStyle FixedSimple ContextMenu menuPopUpBarra ImageList imagenes ShowToolTips true

(11)

Observe que se asocia a este control uno de los tres menús PopUp o contextuales, a

través de la propiedad ContextMenu. Además, cuando se define la propiedad ImageList se asocia las imágenes de dicho control a la barra. La propiedad ShowToolTips asocia pequeñas etiquetas autoexplicativas a cada botón.

A continuación, se procede a añadir los botones a la barra de herramientas. Para ello, los botones se añaden a la propiedad Buttons de la Barra de herramientas que

es una colección de objetos de tipo ToolBarButton. Se puede también hacer esta

operación en tiempo de ejecución. Sin embargo, si es posible, es mejor hacerlo en tiempo de diseño. Desde la propiedad Buttons, pulse el botón situado a la derecha

de la palabra Collection. Se presenta en pantalla un editor para añadir, eliminar y

editar las propiedades de los distintos botones (figura 17.6).

Añada cuatro botones con las siguientes propiedades que se asignarán en el propio editor, como se indica en la figura:

Name boton0 ImageIndex 0

DropDownMenu None

ToolTextTip Botón cero Text

Style PushButton

Name boton1 ImageIndex 1

DropDownMenu None

ToolTextTip Botón uno Text

Style PushButton

Name boton2 ImageIndex 2

DropDownMenu None

ToolTextTip Botón dos Text

Style PushButton

Name boton3 ImageIndex 3

DropDownMenu MenuPopUpBoton

ToolTextTip Ubicación de la barra de herramientas

Text

Style DropDownButton

Añada un botón más, que actuará como separador. Sitúelo entre los botones 2 y 3, como se indica en la figura 17.6:

Name separador ImageIndex DropDownMenu None ToolTextTip Text Style Separator

(12)

Figura 17.6. Editor de la colección que contiene los botones del control ToolBar

• Asigne a la propiedad ContextMenu del formulario el menú menuPopUpFormulario. En la barra de herramientas, asigne a esta propiedad el

menú menuPopUpBarra.

Ahora es un buen momento para guardar la aplicación. Ejecútela y vea que aunque los botones de la barra de herramientas no tienen código, al situar el ratón sobre cada uno de ellos se realizar un pequeño efecto 3D y además aparecen las etiquetas

ToolTip definidas para cada botón. Observe el separador (figura 17.7). Vea que en

la parte derecha del cuarto botón –boton3- aparece una flecha que si se pulsa

despliega un menú. Además se puede observar que el hecho de pulsar en el propio botón es distinto que pulsar en la flecha. Por otro lado, si se sitúa en la parte derecha de la barra de herramientas y pulsa con el botón derecho del ratón puede ver que se despliega un menú contextual distinto que si se realiza esta misma acción sobre el formulario, ya que aparecen otras opciones correspondientes al

menuPopUpFormulario.

• A continuación se va a proceder a cumplimentar el código de los botones. Para ello, se implementará el evento ButtonClick, que es el que ocurre cuando se pulsa

cualquiera de los botones de la barra de herramientas. Haga doble click sobre la barra de herramientas, o en la ventana de propiedades, pulse el icono correspondiente a eventos y haga doble click sobre el evento ButtonClick. De

manera automática Visual Studio registra el evento ButtonClick para que sea

auditado o manejado por el método denominado barra_ButtonClick de la clase

añadiendo la línea:

barra.ButtonClick+=new

(13)

Implemente el método barra_ButtonClick con el siguiente código:

private void barra_ButtonClick(object sender,ToolBarButtonClickEventArgs e) { int indiceDelBotonSeleccionado = barra.Buttons.IndexOf(e.Button); switch (indiceDelBotonSeleccionado) { case 0:

MessageBox.Show("Ha pulsado el primer botón"); break;

case 1:

MessageBox.Show("Ha pulsado el segundo botón"); break;

case 2:

MessageBox.Show("Ha pulsado el tercer botón"); break;

}

if(e.Button == boton3)

MessageBox.Show("Botón con dos eventos distintos"); }

e.Button es el botón pulsado.

barra.Buttons es la colección de botones de la barra. Pasándole el botón

pulsado al método IndexOf éste devuelve el índice del botón que se ha pulsado.

Aunque lo lógico hubiera sido incluirlo en el bloque switch se trata la pulsación

del último de los botones a través de una sentencia if, de una manera algo

diferente. Debe quedar claro que éste último es el evento click de ese botón, no el evento correspondiente a pulsar sobre la flecha asociada al botón. Para tratar este evento, en la ventana de propiedades, pulse en el icono correspondiente a eventos y haga doble click sobre el evento ButtonDropDown. Por defecto el

IDE sugiere el nombre barra_ButtonDropDown. Acéptelo. escriba el siguiente

código en el método:

private void barra_ButtonDropDown(object sender,

ToolBarButtonClickEventArgs e) {

//Indica el momento en que ocurre este evento MessageBox.Show("Ha pulsado la flecha"); }

(14)

Figura 17.7. Aspecto final de la aplicación

• Para tratar cada uno de los eventos del menú, se trabaja igual que en un menú PopUp

–de hecho lo es-. Para ello, pulse en el control menuPopUpBoton en la ventana de

diseño, seleccione la primera opción –Hora de Londres- y haga doble click en la

ventana de propiedades en el evento Click. Cambie el nombre que le ofrece el IDE

por defecto que será menuItem1_Click por menuItemBoton_Click para poder

tratar los tres eventos con un mismo método y escriba el código siguiente:

private void menuItemBoton_Click(object sender, System.EventArgs e) {

if((MenuItem)sender==menuItem1)

MessageBox.Show("Es la hora de Londres"); else if ((MenuItem)sender==menuItem2)

MessageBox.Show("Es la hora de Los Angeles"); else if ((MenuItem)sender==menuItem3)

MessageBox.Show("Es la hora de Moscú"); }

Realmente es un estorbo el hecho de que aparezca una ventana de diálogo cada vez que se pulsa la flecha. Sólo se trata este evento aquí para comprender el momento en que ocurre.

• A continuación asocie a los eventos click de los otros dos items de este menú –Hora de Los Angeles y Hora de Moscu- el mismo evento menuItemBoton_Click

desde la ventana de propiedades.

Proceda del mismo modo con los otros dos menús PopUp y escriba los códigos que a

continuación se indican, teniendo cuidado de asociar el mismo nombre para todos los eventos del mismo menú. El primero de ellos ubicará la barra de herramientas en los cuatro bordes del formulario y el correspondiente al formulario ocultará y hará visible la barra de herramientas.

private void menuItemBarra_Click(object sender,System.EventArgs e) {

if((MenuItem)sender==menuItem4) barra.Dock=DockStyle.Top;

(15)

else if ((MenuItem)sender==menuItem5) barra.Dock=DockStyle.Bottom; else if ((MenuItem)sender==menuItem6) barra.Dock=DockStyle.Left; else if ((MenuItem)sender==menuItem7) barra.Dock=DockStyle.Right; }

private void menuItemFormulario_Click(object sender,System.EventArgs e) { if((MenuItem)sender==menuItem8) barra.Visible=true; else if ((MenuItem)sender==menuItem9) barra.Visible=false; }

Referencias

Documento similar

De hecho, este sometimiento periódico al voto, esta decisión periódica de los electores sobre la gestión ha sido uno de los componentes teóricos más interesantes de la

Ciaurriz quien, durante su primer arlo de estancia en Loyola 40 , catalogó sus fondos siguiendo la división previa a la que nos hemos referido; y si esta labor fue de

Respecto a las enfermedades profesionales, en virtud del RD 1299/2006, de 10 de noviembre, por el que se aprueba el cuadro de enfermedades profesionales en el sistema de

Cedulario se inicia a mediados del siglo XVIL, por sus propias cédulas puede advertirse que no estaba totalmente conquistada la Nueva Gali- cia, ya que a fines del siglo xvn y en

 Tejidos de origen humano o sus derivados que sean inviables o hayan sido transformados en inviables con una función accesoria..  Células de origen humano o sus derivados que

En cuarto lugar, se establecen unos medios para la actuación de re- fuerzo de la Cohesión (conducción y coordinación de las políticas eco- nómicas nacionales, políticas y acciones

El Tratado de Maastricht introduce como elemento fundamental de la Unión Europea la cooperación en los ámbitos de la justicia y en los asuntos de interior (JAI) y establece la doble

Volviendo a la jurisprudencia del Tribunal de Justicia, conviene recor- dar que, con el tiempo, este órgano se vio en la necesidad de determinar si los actos de los Estados