¿Cuál es el papel de la clase cview en mfc?
Hay demasiadas funciones de encapsulación específicas. Solo presento algunas importantes. Puede consultar msdn para obtener más detalles.
Objetos de documento asociados Las vistas deben representar datos de documento, por lo que los objetos de documento deben estar asociados con objetos de vista. De esta manera, cuando los datos del documento cambian, puede notificar a la vista a tiempo cuando la vista necesita mostrar diferentes datos del documento, puede extraerlos del objeto del documento;
En un programa marco de documento/vista, el objeto de documento siempre se crea antes de la vista y su asociación con el objeto de documento se establece en el controlador de mensajes WM_CREATE de la vista. El código es el siguiente:
Int CView::OnCreate (LPCREATESTRUCT lpcs)
{
if (CWnd::OnCreate(lpcs) == -1 )
p>return -1;
// El miembro m_pDocument View almacena el puntero al objeto de documento correspondiente, que es nulo en este momento
ASSERT. (m_pDocument == NULL);
p>CCreateContext* pContext = (CCreateContext*)lpcs-gt;lpCreateParams
// pContext-gt; objeto de documento
if ( pContext! Asociar múltiples vistas
pContext-gt; m_pCurrentDoc-gt; AddView(this);
//* El objeto de documento actual El puntero se ha agregado al documento en la función AddView() del documento en el objeto. En la función AddView() del documento, el puntero del objeto del documento actual se asigna al miembro de la vista m_pDocument. Por lo tanto, los dos están relacionados cuando se crea la vista. */
ASSERT(m_pDocument ! = NULL
}
else
{
TRACE( "Advertencia: Creando un panel sin CDocument.\n");
}
}
return 0; // ok
}
Al mismo tiempo, la clase de vista define la función miembro GetDocument(), que devuelve un puntero al objeto del documento.
El código es el siguiente:
CDocument* CView::GetDocument() const
{
ASSERT(this ! = NULL
<); p>return m_pDocument;}
La vista siempre se destruye antes del objeto del documento y se desasocia del objeto del documento en el destructor de la vista. El código es el siguiente:
CView::~CView()
{
if (m_pDocument ! = NULL)
m_pDocument -gt; RemoveView(this);
}
}
}
El dibujo de la ventana de dibujo de la vista en este La sección siempre se dibuja en el mensaje WM_PAINT. Cuando es necesario dibujar la ventana, recibirá el mensaje WM_PAINT enviado por el sistema. Durante el proceso de dibujo, primero se prepara el mango del dispositivo de visualización y finalmente se suelta. Como todos sabemos, no es necesario sobrecargar el controlador de mensajes WM_PAINT, OnPaint(), para dibujar en una ventana de visualización, porque hay un puerto de dibujo nuevo y más amigable: OnDraw(). El parámetro real de esta función es un dispositivo de visualización que ha sido preparado y no es necesario soltarlo al final. De hecho, es el controlador de mensajes WM_PAINT OnPaint() el que nos prepara. El código es el siguiente:
void CView::OnPaint()
{
CPaintDC dc(this);
OnPrepareDC(amp; dc);
OnDraw(amp; dc); ;
p>
}
OnPrepareDC() es una función virtual que siempre se ejecuta antes de OnDraw(). Esta función se puede sobrecargar para configurar el modo de dibujo. Debido a que OnDraw() utiliza un objeto CPaintDC diferente cada vez que se ejecuta, el estado del modo de dibujo no se puede conservar hasta la siguiente ejecución.
OnDraw() se define como una función virtual pura en la clase base de vista CView. Por ejemplo:
virtual void OnDraw(CDC* pDC) = 0;
Por lo tanto, CView es una clase base abstracta y no se pueden crear instancias, y las clases derivadas deben anular OnDraw().
Editar función virtual OnUpdate Cuando los datos del documento cambian, el objeto del documento llamará a CDocument::UpdateAllView() para notificar a todas las vistas y, en respuesta, se llamará al miembro OnUpdate() de la vista. Por lo tanto, un OnUpdate() sobrecargado debería reflejar los cambios en los datos del documento en la vista según sea necesario. CView::OnUpdate() simplemente invalida el área del cliente, provocando que se vuelva a dibujar. Por ejemplo:
void CView::OnUpdate(CView* pSender, LPARAM, CObject*)
{
ASSERT(pSender ! = this ); p >
UNUSED(pSender); // No se utiliza en la versión de lanzamiento
Invalidate(TRUE);
}
Editar esta sección de función virtual. OnInitialUpdate () se llama después de la creación inicial, OnCreate(), o después de que el marco ejecuta un comando Archivo/Nuevo, Archivo/Abrir.
La clase base CView::OnInitialUpdate() simplemente llama a OnUpdate() y se puede sobrecargar para completar la inicialización. Pero tenga en cuenta que es posible que se llame varias veces.
void CView::OnInitialUpdate()
{
OnUpdate(NULL, 0, NULL
}
);Editar función virtual CalcWindowRect Siempre que cambie el tamaño del área del cliente de la ventana del marco principal o cambie la posición de la barra de control y sea necesario reorganizar el área del cliente, llame a esta función para calcular el tamaño del ventana de vista según el tamaño del área del cliente de la vista.
Sabemos que la disposición del área de cliente de la ventana principal se completa con CFrameWnd::RecalcLayout(). Obviamente, también llamará a la función CalcWindowRect() de la vista. El tamaño del área del cliente de la ventana principal se resta de la parte ocupada por todos los controles, y el área restante se divide entre las vistas y se pasa como argumento real a CalcWindowRect(). En la función CalcWindowRect(), es necesario calcular el tamaño de la ventana de visualización.
El código es el siguiente:
void CView::CalcWindowRect(LPRECT lpClientRect, UNIT nAdjustType)
{
//En este momento, lpClientRect es el tamaño de toda el área del cliente de visualización
// Es necesario agregar tamaño a la barra de desplazamiento
if (nAdjustType != 0)
{
// Llame a la API para ajustar el tamaño de acuerdo con el tamaño de la ventana de cálculo del estilo de ventana
: AjustarWindowRectEx(lpClientRect, 0, FALSE, GetExStyle());
DWORD dwStyle = GetStyle( );
if (dwStyle amp; WS_VSCROLL)
{
// Aumenta el tamaño de la barra de desplazamiento vertical
int nAdjust. = afxData.csVScroll;
if (dwStyle & WS_BORDER)
nAdjust -= CX_BORDER
lpClientRect-gt; p>}
if (dwStyle amp; WS_HSCROLL)
{
// Aumenta el tamaño de la barra de desplazamiento horizontal
<. p>int nAdjust = afxData.cyHScroll;if (dwStyle & WS_BORDER)
nAdjust -= CY_BORDER
lpClientRect-gt; /p>
}
return;
}
//No es necesario agregar dimensiones a la barra de desplazamiento, llame a los miembros de la clase base para que lo hagan. completar el cálculo
CWnd::CalcWindowRect(lpClientRect, nAdjustType)
}
Editar la función virtual PostNcDestroy es la última función miembro llamada cuando se abre la ventana de visualización. cerrado Completa la misma función que CFrameWnd::PostNcDestroy, es decir, eliminar el objeto de vista. El código es el siguiente:
void CView::PostNcDestroy()
{
eliminar esto
}
De esta manera, incluso si la vista se construye en el montón, no tiene que preocuparse por la liberación de la vista.
Editar función virtual OnCmdMsg Esta función ya se conoce cuando se habla de CFrameWnd::OnCmdMsg(), solo su código se proporciona a continuación:
BOOL CView::OnCmdMsg(UINT nID, int nCode , void* pExtra, AFX_ CMDHANDLERINFO* pHhandlerInfo)
{
// Primero busque su propia asignación de mensajes de comando
if (CWnd::OnCmdMsg(nID, nCode, pExtra, PHandlerInfo))
return TRUE;
// Si la vista en sí no maneja el comando, deje la oportunidad al objeto de documento asociado con él
if (m_pDocument != NULL)
{
CPushRoutingView push(this);
return m_pDocument-gt;OnCmdMsg(nID, nCode, pExtra , PHandlerInfo) ;
}p>return FALSE;
}
Esta es la primera vez que se utiliza la vista para procesar el comando. p>
Editar Esta parte de la función virtual OnActivateView se llama para notificar a la vista cuando la vista se activa como vista activa o cambia de una vista activa a una vista inactiva. La implementación de la clase base simplemente establece la vista como foco. El código es el siguiente:
void CView::OnActivateView(BOOL bActivate, CView* pActivateView, CView*)
{
UNUSED(pActivateView); / no utilizado en las versiones de lanzamiento
if (bActivate) // ¿Está activo el estado actual?
{
ASSERT(pActivateView == this
);// Establece el foco si la ventana principal también está activa. (En MDI, su marco principal puede estar inactivo).
if (IsTopParentActive())
SetFocus()
}
}