ventana modal flotante ejemplo automatica mfc dialog modeless

mfc - modal - ventana flotante html5



¿Cómo puedo mostrar un diálogo no modal y mostrar información en él de inmediato? (4)

Quiero mostrar un cuadro de diálogo no modal en la pantalla y mostrar algo de información en él.

Sin embargo, si lo uso de la siguiente manera, tiene algunos problemas:

function() { showdialog(XXX). //heavy work. update the dialog.. //heavy work. update the dialog... }

Parece que se muestra el cuadro de diálogo, pero no dibuja ninguna información en él. Solo dibuja toda la información cuando la función termina.

¿Cómo puedo modificar el diálogo no modal para que muestre la información de inmediato?


Como regla general, los cálculos pesados ​​nunca deben colocarse en el hilo de la GUI. Como se trata de un cuadro de diálogo no modal, el cuadro de diálogo no será propietario del ciclo de mensajes. La solución ProcessMessage () funcionará, pero IMO no es la correcta. Mi sugerencia es: 1) Engendrar un nuevo hilo en OnInitDialog () 2) Tener los mensajes de la publicación de hilo por separado en el cuadro de diálogo cuando sucede algo interesante. Una de estas cosas interesantes es que el trabajo está hecho.

Tenga en cuenta, sin embargo, que esto significará que necesita realizar una sincronización adecuada.


Hay algunas cosas que puedes hacer.

(1) Puede publicar un mensaje en el diálogo desde el método CDialog :: OnInitDialog y luego manejar la función larga en el manejador de mensajes de ese mensaje publicado. De esta forma, primero se mostrará el cuadro de diálogo y luego se ejecutará la función larga.

(2) La segunda opción es asegurarse de que el ciclo de mensajes obtiene algún tiempo de procesamiento. Entonces, si su función larga es algún tipo de bucle, simplemente agregue la llamada ocasional a los mensajes de proceso para asegurarse de que la cola de mensajes se mantenga vacía:

void ProcessMessages() { MSG msg; CWinApp* pApp = AfxGetApp(); while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { pApp->PumpMessage(); } }

Editar: Ciertamente es posible utilizar subprocesos en tal situación, pero hacerlo no siempre implica riesgos y complejidad.

Usar hilos con una GUI significa tener que lidiar con múltiples colas de mensajes, lo que significa usar API como PostThreadMessage y eso introduce un nuevo conjunto de problemas que hay que tener en cuenta.

Para ver un ejemplo de uno de estos temas, consulte este enlace:

http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx

donde dice:

Los mensajes enviados por PostThreadMessage no están asociados con una ventana. Como regla general, los mensajes que no están asociados con una ventana no pueden ser enviados por la función DispatchMessage. Por lo tanto, si el hilo del destinatario está en un bucle modal (como lo usan MessageBox o DialogBox), los mensajes se perderán. Para interceptar mensajes de subprocesos en un bucle modal, use un enlace específico de subproceso.

Utilizo el enfoque de mensaje de proceso en Zeus IDE y funciona muy bien para asegurarme de que la GUI siga siendo receptiva para el usuario. También tiene la ventaja de ser muy fácil de implementar.


En OnInitDialog, inicie un hilo de trabajo para realizar los cálculos. Publique un mensaje de usuario desde el hilo del trabajador para actualizar el diálogo.

Esto es superior a la implementación de ProcessMessages por varias razones:

  • El código para hacer los cálculos se puede separar del código de la UI, donde no pertenece.

  • La IU sigue siendo receptiva mientras se realizan los cálculos reales. ProcessMessages permite múltiples actualizaciones de UI durante la función de cálculo único, pero la UI seguirá bloqueándose durante los cálculos reales.

Código de diálogo:

#define WM_NEW_COUNT (WM_USER + 0x101) BEGIN_MESSAGE_MAP() ON_MESSAGE(WM_NEW_COUNT, OnNewCount) END_MESSAGE_MAP() BOOL CMyDialog::OnInitDialog() { CWinThread* pThread = AfxBeginThread(MyCountFunc, this->GetSafeHwnd()); return TRUE; } LRESULT CMyDialog::OnNewCount(WPARAM wParam, LPARAM) { int newCount = (int)wParam; // m_count is DDX member, e.g. for label m_count = newCount; UpdateData(FALSE); return 0; }

El hilo de trabajo:

UINT MyCountFunc(LPVOID lParam) { HWND hDialogWnd = (HWND)lParam; for (int i=0; i < 100; ++i) { PostMessage(hDialogWnd, WM_NEW_COUNT, i, NULL); } }


No trates de hacer tu trabajo pesado todo de una vez. Haga que el cuadro de diálogo publique un mensaje en el rango WM_APP en OnInitDialog. El manejador WM_APP puede hacer parte del trabajo pesado, luego hacer otro PostMessage y regresar. De esta forma, permite que la bomba de mensajes procese mensajes de ventana entre sus fragmentos de procesamiento.