TN061: ON_NOTIFY y mensajes WM_NOTIFY

Esta nota técnica proporciona información sobre el nuevo mensaje WM_NOTIFY y describe la manera recomendada (y más común) de tratamiento de mensajes WM_NOTIFY en una aplicación MFC.

Mensajes de notificación en Windows 3.x

En Windows 3.x, controles de notificar a sus padres de eventos tales como clics del mouse, cambios en el contenido y la selección y la pintura de fondo de control enviando un mensaje al padre. Simples notificaciones se envían como mensajes WM_COMMAND especiales, con el código de notificación (como BN_CLICKED) y controlan ID empaquetado en wParam y el identificador del control en lParam. Tenga en cuenta que ya wParam y lParam están llenos, no hay manera para pasar cualquier dato adicional, estos mensajes pueden ser sólo simple notificación. Por ejemplo, en la notificación de BN_CLICKED , no hay ninguna forma de enviar información acerca de la ubicación del cursor del ratón cuando se hace clic en el botón.

Cuando los controles de Windows 3.x necesitan enviar un mensaje de notificación que incluye datos adicionales, utilizar una variedad de mensajes especiales, incluyendo WM_CTLCOLOR, WM_VSCROLL, mensajes WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEMy así sucesivamente. Estos mensajes pueden reflejarse hacia el control que los enviaron. Para obtener más información, consulte TN062: mensaje de reflexión para controles de Windows.

Mensajes de notificación en Win32

Para los controles que existían en Windows 3.1, la API de Win32 utiliza la mayoría de los mensajes de notificación que se utilizaban en Windows 3.x. Sin embargo, Win32 agrega también una serie de controles sofisticados y complejos para los admitidos en Windows 3.x. con frecuencia, estos controles deben enviar datos adicionales con sus mensajes de notificación. En lugar de agregar un nuevo mensaje WM_ * para cada nueva notificación que necesita datos adicionales, los diseñadores de la API de Win32 decidieron agregar sólo un mensaje WM_NOTIFY, que puede pasar cualquier cantidad de datos adicionales de una manera estandarizada.

Mensajes WM_NOTIFY contienen el ID del control enviando el mensaje en wParam y un puntero a una estructura en lParam. Esta estructura es una estructura NMHDR o alguna estructura más grande que tiene una estructura NMHDR como su primer miembro. Tenga en cuenta que desde el miembro NMHDR es el primero, un puntero a esta estructura puede utilizarse como o un puntero a un NMHDR o un puntero a la estructura más grande dependiendo de cómo convertirlo.

En la mayoría de los casos, el puntero apuntará a una estructura mayor y necesitará convertirlo al usarlo. En sólo unas pocas notificaciones, como las notificaciones comunes (cuyos nombres empiezan con NM_) y el control de punta de herramienta TTN_SHOW y notificaciones de TTN_POP , es una estructura NMHDR realmente utilizada.

La estructura NMHDR o miembro inicial contiene el identificador y el ID del control enviando el mensaje y el código de notificación (como TTN_SHOW). A continuación se muestra el formato de la estructura NMHDR:

typedef struct tag&NMHDR {}
 nbsp;  HWND hwndFrom;
    UINT idFrom;
    Código UINT;
} NMHDR

Para un mensaje TTN_SHOW , el miembro code se establecería en TTN_SHOW.

La mayoría de las notificaciones pasen un puntero a una estructura más grande que contiene una estructura NMHDR como su primer miembro. Por ejemplo, considere la estructura utilizada por el mensaje de notificación de LVN_KEYDOWN del control de vista de lista, que se envía cuando se presiona una tecla en un control de vista de lista. El puntero apunta a una estructura LV_KEYDOWN , que se define como se muestra a continuación:

typedef struct tagLV_KEYDOW&N {}
 nbsp;  NMHDR hdr;   
    WORD wVKey;  
    UINT banderas;  
} LV_KEYDOWN

Tenga en cuenta que, desde el miembro NMHDR es el primero en esta estructura, el puntero que esté aprobado en el mensaje de notificación se puede convertir en un puntero a un NMHDR o un puntero a un LV_KEYDOWN.

Notificaciones común a todos los nuevos controles de Windows

Algunas notificaciones son comunes a todos los nuevos controles de Windows. Estas notificaciones pasan un puntero a una estructura NMHDR.

Código de notificación Enviado porque
NM_CLICK Usuario hace clic en el botón izquierdo del ratón en el control
NM_DBLCLK Botón izquierdo usuario hace doble clic en el control
NM_RCLICK Usuario hace clic en el botón derecho del ratón en el control
NM_RDBLCLK Botón derecho usuario hace doble clic en el control
NM_RETURN Usuario presiona la tecla ENTRAR mientras el control tiene el foco de entrada
NM_SETFOCUS Control se ha dado el foco de entrada
NM_KILLFOCUS Control ha perdido el foco de entrada
NM_OUTOFMEMORY Control no ha podido completar una operación porque no había suficiente memoria disponible

ON_NOTIFY: Manejo de mensajes WM_NOTIFY en aplicaciones MFC

La función CWnd::OnNotify gestiona los mensajes de notificación. Su implementación predeterminada comprueba el mapa de mensajes para los controladores de notificación llamar. En general, no reemplazar OnNotify. En su lugar, proporciona una función de controlador y agregar una entrada de mapa de mensajes para ese controlador para el mapa de mensajes de clase de la ventana de su propietario.

ClassWizard, a través de la hoja de propiedades de ClassWizard o WizardBar, puede crear la entrada de mapa de mensajes ON_NOTIFY y proporcionarle una función de controlador de esqueleto. Para obtener más información sobre cómo utilizar ClassWizard para facilitar esto, consulte Mensajes de asignación de funciones en el Manual del programador de Visual C++.

La macro de mapa de mensajes ON_NOTIFY tiene la siguiente sintaxis:

ON_NOTIFY ( wNotifyCode, id de, memberFxn )

donde los parámetros en cursiva son reemplazados con:

wNotifyCode

El código para el mensaje de notificación a tratarse, como LVN_KEYDOWN.

id.

El niño identificador del control que se envía la notificación.

memberFxn

La función de miembro que se llamará cuando se envía esta notificación.

Su función miembro debe declararse con el siguiente prototipo:

afx_msgvoidmemberFxn()NMHDR*pNotifyStruct,LRESULT*resultado);

donde están los parámetros en cursiva:

pNotifyStruct

Un puntero a la estructura de la notificación, como se describe en la sección anterior.

resultado

Un puntero para el código de resultado se configuran antes de volver.

Ejemplo

Para especificar que desea que la función miembro OnKeydownList1 para controlar los mensajes LVN_KEYDOWN de la CListCtrl cuyo ID es IDC_LIST1 , utilizaría ClassWizard añadir lo siguiente a su mapa de mensajes:

ON_NOTIFY (LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)

En el ejemplo anterior, es la función proporcionada por ClassWizard:

void CMessageReflectionDlg::OnKeydownList1 (&NMHDR * pNMHDR, LRESULT * pResult)
{
   LV_KEYDOWN * pLVKeyDow = (LV_KEYDOWN **) pNMHDR;
   / / TODO: agrega el controlador de notificación de control
   / / nbsp;  código aquí
   
   * pResult = 0;
}

Tenga en cuenta que ClassWizard proporciona automáticamente un puntero del tipo adecuado. Puede acceder a la estructura de notificación mediante ya sea pNMHDR opLVKeyDow.

ON_NOTIFY_RANGE

Si necesita procesar el mismo mensaje WM_NOTIFY para un conjunto de controles, puede utilizar ON_NOTIFY_RANGE en lugar de ON_NOTIFY. Por ejemplo, puede tener un conjunto de botones que desea realizar la misma acción para un determinado mensaje de notificación.

Cuando se utiliza ON_NOTIFY_RANGE, especifique un intervalo contiguo de identificadores de niño para que controlen el mensaje de notificación especificando el comienzo y final de identificadores de niño de la gama.

ClassWizard no manejar ON_NOTIFY_RANGE; para usarlo, necesita editar el mapa de mensajes usted mismo.

La entrada de mapa de mensajes y el prototipo de función para ON_NOTIFY_RANGE son los siguientes:

ON_NOTIFY_RANGE ( wNotifyCode, id de, idLast, memberFxn )

donde los parámetros en cursiva son reemplazados con:

wNotifyCode

El código para el mensaje de notificación a tratarse, como LVN_KEYDOWN.

id.

El primer identificador en el rango contiguo de identificadores.

idLast

El último identificador en el rango contiguo de identificadores.

memberFxn

La función de miembro que se llamará cuando se envía esta notificación.

Su función miembro debe declararse con el siguiente prototipo:

afx_msgvoidmemberFxn()UINT idNMHDR*pNotifyStruct,LRESULT*resultado);

donde están los parámetros en cursiva:

id.

El identificador de niño del control que envió la notificación.

pNotifyStruct

Un puntero a la estructura de la notificación, como se describió anteriormente.

resultado

Un puntero para el código de resultado se configuran antes de volver.

ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE

Si desea más de un objeto en la notificación de enrutamiento para manejar un mensaje, puede utilizar ON_NOTIFY_EX (o ON_NOTIFY_EX_RANGE) en lugar de ON_NOTIFY (o ON_NOTIFY_RANGE). La única diferencia entre la versión EX y la versión normal es que la función miembro llamada para la versión EX devuelve un BOOL que indica si o no debe continuar el procesamiento de mensajes. Devolver FALSE desde esta función le permite procesar el mismo mensaje en más de un objeto.

ClassWizard no manejar ON_NOTIFY_EX o ON_NOTIFY_EX_RANGE; Si desea utilizar cualquiera de ellos, tiene que editar el mapa de mensajes usted mismo.

La entrada de mapa de mensajes y el prototipo de función para ON_NOTIFY_EX y ON_NOTIFY_EX_RANGE son los siguientes. El significado de los parámetros es los mismos que para los no-EX versiones.

ON_NOTIFY_EX ( nCode, id de, memberFxn )

ON_NOTIFY_EX_RANGE ( wNotifyCode, id de, idLast,memberFxn )

El prototipo para ambos de lo anterior es el mismo:

afx_msgBOOLmemberFxn()UINT idNMHDR*pNotifyStruct,LRESULT*resultado);

En ambos casos, id contiene el identificador de niño del control que envió la notificación.

Su función debe devolver TRUE si el mensaje de notificación ha sido completamente manejado o falso si otros objetos en el enrutamiento de comandos deben tener una oportunidad para manejar el mensaje.

&Notas técnicas por número |nbsp; Notas técnicas por categoría

Index