There are a few things you can do.
(1) You could post the dialog a message from inside the CDialog::OnInitDialog method and then handle the long function in the message handler of that posted message. That way the dialog will first be displayed and then later the long function will get run.
(2) The second option is to make sure the message loop gets some processing time. So if your long function is some sort of loop just add the occasional call to the ProcessMessages to make sure the message queue is kept empty:
void ProcessMessages()
{
MSG msg;
CWinApp* pApp = AfxGetApp();
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
pApp->PumpMessage();
}
}
Edit: It certainly is possible to use threads is such a situation, but doing so is not always without risk and complexity.
Using threads with a GUI means having to deal with multiple message queues which then means using API's like PostThreadMessage and that introduces a new set of issues to be wary of.
For an example of one such issue refer to this link:
http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx
where is says:
Messages sent by PostThreadMessage are
not associated with a window. As a
general rule, messages that are not
associated with a window cannot be
dispatched by the DispatchMessage
function. Therefore, if the recipient
thread is in a modal loop (as used by
MessageBox or DialogBox), the
messages will be lost. To intercept
thread messages while in a modal
loop, use a thread-specific hook.
I use the process message approach in the Zeus IDE and it works very well at making sure the GUI remains responsive to the user. It is also has the advantage of being very easy to implement.