TN029: Ventanas divisoras
En esta nota, se describe la clase CSplitterWnd de MFC, que proporciona divisiones de ventana y administra el cambio de tamaño de otras ventanas de panel.
Estilos divisores
Un elemento CSplitterWnd
admite dos estilos diferentes de ventanas de división.
Con "divisores estáticos", la ventana divisora crea los paneles cuando se crea. El orden y el número de los paneles nunca cambia. Las barras divisoras se usan para cambiar el tamaño de los distintos paneles. Puede usar este estilo para mostrar una clase de vista diferente en cada panel. El editor de gráficos de Visual C++ y el Administrador de archivos de Windows son ejemplos de programas que usan este estilo divisor. Este estilo de ventana divisora no usa cuadros divisores.
Con "divisores dinámicos", se crean y se destruyen paneles adicionales a medida que el usuario divide y reúne nuevas vistas. Este divisor comienza con una sola vista y proporciona cuadros divisores para que el usuario inicie la división. La ventana divisora crea dinámicamente un nuevo objeto de vista cuando la vista se divide en una dirección. Este nuevo objeto de vista representa el nuevo panel. Si la vista se divide en dos direcciones mediante la interfaz de teclado, la ventana divisora crea tres nuevos objetos de vista para los tres paneles nuevos. Mientras la división está activa, Windows muestra el cuadro divisor como una barra divisora entre los paneles. Windows destruye los objetos de vista adicionales cuando el usuario quita una división, pero la vista original permanece hasta que se destruye la propia ventana divisora. Microsoft Excel y Microsoft Word son ejemplos de aplicaciones que usan el estilo de divisor dinámico.
Al crear cualquier tipo de ventana divisora, debe especificar el número máximo de filas y columnas que administrará el divisor. Un divisor estático creará paneles para rellenar todas las filas y columnas. Un divisor dinámico creará solo el primer panel cuando se cree el elemento CSplitterWnd
.
El número máximo de paneles que puede especificar para los divisores estáticos es de 16 filas por 16 columnas. Las configuraciones recomendadas son:
1 fila x 2 columnas: normalmente con paneles no similares
2 filas x 1 columna: normalmente con paneles no similares
2 filas x 2 columnas: normalmente con paneles similares
El número máximo de paneles que puede especificar para los divisores dinámicos es de 2 filas por 2 columnas. Las configuraciones recomendadas son:
1 fila x 2 columnas: para datos en columnas
2 filas x 1 columna: para texto u otros datos
2 filas x 2 columnas: para datos orientados a cuadrícula o tabla
Ejemplos de divisores
Muchos de los programas de ejemplo de MFC usan ventanas divisoras directas o indirectamente. En el ejemplo general VIEWEX de MFC, se muestran varios usos de divisores estáticos, incluido cómo colocar un divisor en un divisor.
También puede usar ClassWizard para crear una nueva clase de ventana de marco secundario de interfaz de múltiples documentos (MDI) que contiene una ventana divisora. Para obtener más información sobre las ventanas divisoras, consulte Varios tipos de documentos, vistas y ventanas de marco.
Terminología usada por la implementación
Esta es una lista de términos específicos de las ventanas divisoras:
CSplitterWnd
: una ventana que proporciona controles de división de panel y barras de desplazamiento que se comparten entre todos los paneles de una fila o columna. Especifique las filas y columnas con números de base cero (el primer panel es fila = 0 y columna = 0).
Panel: ventana específica de la aplicación administrada por un elemento CSplitterWnd
. Un panel suele ser un objeto derivado de la clase CView, pero puede ser cualquier objeto CWnd que tenga el identificador de ventana secundaria adecuado.
Para usar un objeto derivado de CWnd
, pase el elemento RUNTIME_CLASS del objeto a la función CreateView
como lo haría si estuviera usando una clase derivada de CView
. La clase debe usar DECLARE_DYNCREATE e IMPLEMENT_DYNCREATE porque el marco de trabajo usa la creación dinámica en tiempo de ejecución. Aunque hay un montón de código en CSplitterWnd
que es específico de la clase CView
, siempre se usa CObject::IsKindOf antes de realizar esas acciones.
Barra divisora: control que se coloca entre las filas y columnas de los paneles. Se puede usar para ajustar los tamaños de las filas o las columnas de los paneles.
Cuadro divisor: control de un elemento CSplitterWnd
dinámico que puede usar para crear nuevas filas o columnas de paneles. Se encuentra en la parte superior de las barras de desplazamiento verticales o a la izquierda de las barras de desplazamiento horizontales.
Intersección de divisores: intersección de una barra divisora vertical y una barra divisora horizontal. Puede arrastrarla para ajustar el tamaño de una fila y una columna de paneles simultáneamente.
Barras de desplazamiento compartidas
La clase CSplitterWnd
también admite barras de desplazamiento compartidas. Estos controles de barra de desplazamiento son elementos secundarios de CSplitterWnd
y se comparten con los distintos paneles del divisor.
Por ejemplo, en una ventana de 1 fila x 2 columnas, puede especificar WS_VSCROLL al crear CSplitterWnd
. Windows crea un control de barra de desplazamiento especial que se comparte entre los dos paneles.
[ ][ ][^]
[pane00][pane01][|]
[ ][ ][v]
Cuando el usuario mueva la barra de desplazamiento, se enviarán mensajes WM_VSCROLL a ambas vistas. Cuando cualquiera de las vistas establece la posición de la barra de desplazamiento, se establecerá la barra de desplazamiento compartida.
Tenga en cuenta que las barras de desplazamiento compartidas son más útiles con objetos de vista similares. Si combina vistas de diferentes tipos en un divisor, es posible que tenga que escribir código especial para coordinar sus posiciones de desplazamiento. Cualquier clase derivada de CView
que use las API de barra de desplazamiento de CWnd
se delegará en la barra de desplazamiento compartida, si existe. La implementación de CScrollView
es un ejemplo de una clase CView
que admite barras de desplazamiento compartidas. Las clases que no se derivan de CView
, las clases que se basan en barras de desplazamiento que no son de control y las clases que usan implementaciones estándar de Windows (por ejemplo, CEditView
) no funcionarán con la característica de barra de desplazamiento compartida de CSplitterWnd
.
Tamaños mínimos
Para cada fila hay un alto de fila mínimo y para cada columna hay un ancho de columna mínimo. Este mínimo garantiza que un panel no sea demasiado pequeño para mostrarse con los detalles completos.
En el caso de una ventana divisora estática, el alto de fila y el ancho de columna mínimos iniciales es 0. En el caso de una ventana divisora dinámica, el alto de fila y el ancho de columna mínimos iniciales se establecen mediante el parámetro sizeMin de la función CSplitterWnd::Create
.
Puede cambiar estos tamaños mínimos mediante las funciones CSplitterWnd::SetRowInfo y CSplitterWnd::SetColumnInfo.
Tamaños reales frente a ideales
El diseño de los paneles de la ventana divisora depende del tamaño del marco que los contiene. Cuando un usuario cambia el tamaño del marco contenedor, CSplitterWnd
cambia de posición y tamaño los paneles para que se ajusten tan bien como sea posible.
El usuario puede establecer manualmente los tamaños de alto de fila y ancho de columna, o bien el programa puede establecer el tamaño ideal mediante la clase CSplitterWnd
. El tamaño real puede ser menor o mayor que el ideal. Windows ajustará el tamaño real si no hay suficiente espacio para mostrar el tamaño ideal o si hay demasiado espacio vacío en la parte derecha o inferior de la ventana divisora.
Controles personalizados
Puede invalidar muchas funciones para proporcionar un comportamiento personalizado y una interfaz personalizada. Puede invalidar este primer conjunto para proporcionar imágenes alternativas para los distintos componentes gráficos de una ventana divisora.
virtual void OnDrawSpltter(CDC* pDC, ESplitType nType, const CRect& rect);
virtual void OnInvertTracker(const CRect& rect);
Llame a esta función para crear un control de barra de desplazamiento compartida. Puede invalidarlo para crear controles adicionales junto a la barra de desplazamiento.
virtual BOOL CreateScrollBarCtrl(DWORD dwStyle, UINT nID);
Estas funciones implementan la lógica de la ventana divisora dinámica. Puede invalidarlas para proporcionar una lógica de división más avanzada.
virtual void DeleteView(int row, int col);
virtual BOOL SplitRow(int cyBefore);
virtual BOOL SplitColumn(int cxBefore);
virtual void DeleteRow(int rowDelete);
virtual void DeleteColumn(int colDelete);
Funcionalidad de CView
La clase CView
usa los siguientes comandos de alto nivel para delegar en la implementación de CSplitterWnd
. Dado que estos comandos son virtuales, la implementación estándar de CView
no requerirá que esté vinculada toda la implementación de CSplitterWnd
. En el caso de las aplicaciones que usan CView
pero no CSplitterWnd
, la implementación de CSplitterWnd
no se vinculará con la aplicación.
virtual BOOL CanActivateNext(BOOL bPrev = FALSE);
Comprueba si ID_NEXT_PANE o ID_PREV_PANE son posibles actualmente.
virtual void ActivateNext(BOOL bPrev = FALSE);
Ejecuta el comando "Panel siguiente" o "Panel anterior".
virtual BOOL DoKeyboardSplit();
Ejecuta el comando de división del teclado, normalmente "Dividir ventana".