Question

I have two code files, one contains my WinMain() function, and all functions related to my main dialog window. The other contains a thread callback and variable functions related to my program. I have defined HWND hWnd = NULL as a global variable in MainDlg.cpp and defined extern HWND hWnd in Other.cpp (which contains the thread callback). The thread is created when the WM_INITDIALOG message is sent to the window. Inside the thread callback, the hWnd variable is null until long operation is performed, then after that it becomes available.

MainDlg.cpp

HWND hWnd = NULL;
HANDLE hListenThread = NULL;

DWORD WINAPI ListenThread( LPVOID lpvParam );

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    /* ... */
    if( NULL == (hWnd=CreateDialog( hInstance, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)WndProc)) )
    {
        MessageBox( NULL, "Error creating the main dialog!", NULL, MB_OK | MB_ICONERROR );
        return -1;
    }

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

    return 0;
}

BOOL CALLBACK WndProc(HWND hWndDlg, UINT Message, WPARAM wParam, LPARAM lParam)
{

    switch(Message)
    {
        case WM_INITDIALOG:
        {
            DWORD dwListenThreadId = NULL;
            /* referencing hWnd here works fine... */
            /* ... */
            hListenThread = CreateThread(
                NULL,
                0,
                ListenThread,
                hWndDlg,
                0,
                &dwListenThreadId);
            /* ... */
        } break;
    }

    return false;
}

Other.cpp

extern HWND hWnd;
DWORD WINAPI ListenThread( LPVOID lpvParam )
{

    if( hWnd == NULL )
        MessageBox( NULL, "hWnd == NULL", NULL, MB_OK | MB_SYSTEMMODAL );

    if( hWnd != NULL )
        MessageBox( NULL, "hWnd != NULL", NULL, MB_OK | MB_SYSTEMMODAL );

    return 0;
}

Both Message Boxes in the ListenThread callback are displayed when the application is launched. Can someone please tell me why this is happening? Is there something I can do to fix this besides doing while( hWnd == NULL ); at the beginning of my ListenThread ?

Was it helpful?

Solution

The WM_INITDIALOG message occurs before CreateDialog returns and hWnd isn't set until CreateDialog returns. So the thread starts running before CreateDialog returns and sets the global hWnd variable.

So you could fix this by moving your thread creation from the WM_INITDIALOG message to just after the return of CreateDialog.

But you don't need to do that because you code doesn't required the global hWnd variable. You are already passing your dialogs window handle as the parameter to the thread start procedure. So just cast the lpvParam to an HWND and use that. That will let you get rid of your global variable, which is bad practice to use.

Other.cpp

DWORD WINAPI ListenThread( LPVOID lpvParam )
{
    HWND hWnd= (HWND)lpvParam;

    if( hWnd == NULL )
        MessageBox( NULL, "hWnd == NULL", NULL, MB_OK | MB_SYSTEMMODAL );

    if( hWnd != NULL )
        MessageBox( NULL, "hWnd != NULL", NULL, MB_OK | MB_SYSTEMMODAL );

    return 0;
}

OTHER TIPS

The WM_INITDIALOG message is issued to WndProc() from inside of CreateDialog() itself, not by DispatchMessage(). This is stated as much in the CreateDialog() documentation. Your hWnd variable is not assigned until after CreateDialog() exits. If your thread starts running before CreateDialog() exits (depending on task scheduling, that is not a guarantee), your first MessageBox() gets called. While the MessageBox() is running, CreateDialog() has time to exit and assign the variable, which is why the second MessageBox() gets called after you dismiss the first MessageBox().

You don't need to use the hWnd variable in your thread at all. You are passing the dialog HWND to the lpParameter parameter of CreateThread(), so it will appear in the lpvParam parameter of ListenThread(), eg:

DWORD WINAPI ListenThread( LPVOID lpvParam )  
{  
    HWND hWnd = (HWND) lpvParam;  
    ...
    return 0;  
}  
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top