2008-12-22 21 views
5

Quiero mostrar un cuadro de diálogo no modal en la pantalla y mostrar algo de información en él.¿Cómo puedo mostrar un cuadro de diálogo no modal y mostrar información en él de inmediato?

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 aparece el cuadro de diálogo, pero no establece ninguna información contenida 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?

Respuesta

5

Hay algunas cosas que puede hacer.

(1) Se podría posterior el diálogo de un mensaje desde el interior del método CDialog :: OnInitDialog y luego manejar la función de tiempo en el controlador 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. Así que si su función a largo es una especie de bucle sólo tiene que añadir la llamada ocasional a los ProcessMessages para asegurarse de que la cola de mensajes se mantiene vacío:

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

Editar: Sin duda, es posible utilizar hilos es tal una situación, pero hacerlo no siempre es sin riesgo y complejidad.

El uso de hilos con una interfaz gráfica de usuario significa tener que hacer frente a múltiples colas de mensajes que a su vez significa el uso de la API como PostThreadMessage y que introduce un nuevo conjunto de problemas que tener cuidado de.

Para un ejemplo de una de esas cuestiones se refieren a este enlace:

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

donde se dice:

Los mensajes enviados por PostThreadMessage son no asociado a 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 subproceso del destinatario está en un bucle modal (como se usa en MessageBox o DialogBox), se perderán los mensajes . Para interceptar mensajes de subproceso en un ciclo modal , utilice un enlace específico de subproceso.

uso el enfoque de mensaje de proceso en el Zeus IDE y funciona muy bien en asegurarse de que la interfaz gráfica de usuario se mantenga sensible para el usuario. También tiene la ventaja de ser muy fácil de implementar.

+2

IMO la función ProcessMessage() es la forma de agregar capacidad de respuesta a una aplicación MFC. – Hapkido

+2

Yo también usaría la opción ProcessMessage;) – jussij

+0

Estoy totalmente en desacuerdo. 1) Un método de interfaz de usuario no debe realizar una gran cantidad de "otro" trabajo, las preocupaciones deben separarse. 2) Se puede usar un hilo de trabajo simple en la mayoría de estas situaciones, sin necesidad de múltiples bombas. ¿Por qué estás tratando de asustar al OP lejos de los hilos? –

2

Como regla general, los cálculos pesados ​​nunca se deben colocar en el hilo de la GUI. Como se trata de un diálogo no modal, el 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 subprocesos 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 debe realizar una sincronización adecuada.

4

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.

Ésta es superior a la implementación ProcessMessages por varias razones:

  • El código para hacer los cálculos se pueden separar del código de interfaz de usuario, en la que no pertenece.

  • La IU sigue siendo sensible 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.

el 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 subproceso de trabajo:

UINT MyCountFunc(LPVOID lParam) 
{ 
    HWND hDialogWnd = (HWND)lParam; 

    for (int i=0; i < 100; ++i) 
    { 
     PostMessage(hDialogWnd, WM_NEW_COUNT, i, NULL); 
    } 
} 
1

No trate de hacer su trabajo pesado a la 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.

Cuestiones relacionadas