Click to See Complete Forum and Search --> : CreateDialog - how to send messages?


fzgny5
December 16th, 2004, 09:04 AM
I am new to VC++ and have a problem. I have an application that does several things and I wish to have a single dialog with a listbox that I periodically write to to give a status of the initialization to the user. Here is what I have so far but I cannot figure out how to write additional messages to the dialog. Every time I try it appears to get into an infinite loop. Any help is appreciated...

BTW... this is a Win32 Application not using MFC
------------------------------------------------------------------------------------------------------
#include<windows.h>
#include"Resource.h"

BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow )
{
MSG msg;
HWND hDlg;

hDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_UserInterface), NULL, DialogProc);
if (hDlg == NULL)
return 0;

ShowWindow(hDlg, SW_SHOWNORMAL);

// *** I do numerous function calls here that need to write to the listbox

//UpdateWindow(hDlg);

while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch(uMsg) {
case WM_INITDIALOG:
SetFocus(hwndDlg);
SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)"hello");
return TRUE;
break;
//case WM_PAINT: // Seems to get me into an infinite loop!
// SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)"paint");
// return TRUE;
// break;
case WM_COMMAND:
if(wParam == IDCANCEL) {
DestroyWindow(hwndDlg);
return TRUE;
}
break;
default:
return FALSE;
}

return FALSE;
}

kkez
December 16th, 2004, 09:14 AM
wm_paint isn't the right place to put SendDlgItemMessage. If you want to update the status of the user periodically you can use SetTimer and WM_TIMER message to update your listbox.

ex:


#define IDC_TIMER1 1

BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{

//....
switch(uMsg)
{
case WM_INITDIALOG:
//your inizializations
SetTimer(hwndDlg, //handle of the window to which WM_TIMER message is sent
IDC_TIMER1, //id of the timer
1000 //gap between every WM_TIMER message, in this case 1 sec
NULL); //you don't need this parameter
break;
case WM_TIMER:
SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)"paint");
break;
case WM_CLOSE:
KillTimer(hwndDlg,IDC_TIMER1);
break;
}

NoHero
December 16th, 2004, 10:14 AM
And as mentioned in several other threads you should rewrite your main loop to:


BOOL bResult = 0;

while ( (bResult = GetMessage(&msg, hDlg, 0, 0)) != 0 )
{
if ( bResult == -1 )
{ // handle this error some way
break;
}
else
{ // Check for none dialog message
if ( !IsDialogMessage(hDlg, &msg) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

fzgny5
December 16th, 2004, 10:15 AM
That will work (I think). Can I use "SendDlgItemMessage" anywhere in my code and the timer will display the message or will I have to create some type of global variables to indicate what messages I want to display (based on where I am in the initialization of the app)?

In a nutshell, I want to display the dialog and update it based on which function I am executing. Where in the code do I put the function calls (just before GetMessage?) and how do I update the dialog from within the function?

Thanks!

fzgny5
December 16th, 2004, 10:46 AM
I put the code in my app and here's what I experienced:

1. I put SendDlgItemMessage statements in my functions.
2. The status window did not update as I went along (just hourglassed) as the function calls are before the GetMessage loop.
3. Once my functions were complete, the dialog updated.

I need to figure out how to update the dialog as I process a function. Is it possible? Does it have something to do with the placement of the GetMessage loop?

Thanks again!

kkez
December 16th, 2004, 11:49 AM
Now i understood. You execute these functions before the loop, so you can't do anything with your window until these functions returns, because the window can't start handling messages. I suggest you to move these functions inside WM_INITDIALOG, and after each function you can call SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, ecc...).

kkez
December 16th, 2004, 11:58 AM
Or, if you want more, you can create a thread, put these function inside the thread's function, create a timer and display a counter or whatever you want to make sure the program is running and everithing is working fine. It's harder to do but if you want to try...:p

fzgny5
December 16th, 2004, 12:55 PM
I guess I can't really put it in WM_INITDIALOG as it does everything in it just prior to displaying the dialog. Can you give more info on creating another thread (possibly an example)? Would CreateWindow be any different? I guess if all else fails I could launch a separate app (to display/update the dialog) which reads from a logfile created by the initial app, eh?

Is there an easier way to do this if I use MFC? I know nothing about MFC though...

Are there no instances of someone constantly writing an updated status to a window during processing that is meaningful (i.e. described what is going on)?

kkez
December 17th, 2004, 07:53 AM
You're right. Take a look at CreateThread and ThreadProc from msdn (search google). I will post an example later on.

kkez
December 17th, 2004, 12:53 PM
int WINAPI WinMain(......)
{
...
HANDLE hThread = NULL;
DWORD dwThreadId;
hThread = CreateThread(NULL, 0, ThreadProc, 0, 0, dwThreadId);

if (hThread == NULL) return 0;
....
}

DWORD WINAPI ThreadProc(LPVOID)
{
//your functions go here

return 0;
}