0
votes

I am trying to create a simple dialog box on a win32 console window project with only ok and cancel button using mfc. I have created dialog template using resource editor and necessary classes. The following code illustrates the project

/*dialog.h - dialog class inherited from Cdialog*/
#pragma once
#include "resource.h"
#include "afxwin.h"

class dialog : public CDialog
{
DECLARE_DYNAMIC(dialog)
    public:
 dialog(CWnd* pParent = NULL);   // standard constructor
 virtual ~dialog();

    // Dialog Data
enum { IDD = IDD_DIALOG1 };
    protected:
 virtual void DoDataExchange(CDataExchange* pDX);  // DDX/DDV support
     DECLARE_MESSAGE_MAP();

    public:
 BOOL OnInitDialog();
     void OnOK();
     void OnCancel();
    void PostNcDestroy();
 };

/* dialog.cpp : implementation file */

#include "stdafx.h"
#include "dialog.h"
#include "afxdialogex.h"

IMPLEMENT_DYNAMIC(dialog, CDialog)

dialog::dialog(CWnd* pParent /*=NULL*/)
: CDialog(dialog::IDD, pParent)
{}

dialog::~dialog()
{
DestroyWindow();
}
void dialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(dialog, CDialog)
END_MESSAGE_MAP()


// dialog message handlers

BOOL dialog::OnInitDialog()
{
CDialog::OnInitDialog();
return(TRUE);
}

void dialog::OnOK()
{
if (UpdateData(true))
    DestroyWindow();
}

void dialog::OnCancel()
{
DestroyWindow();
}

void dialog::PostNcDestroy()
{
CDialog::PostNcDestroy();
delete this;
}

/*dialogbox.cpp : Defines the entry point for the console application.*/
#include "stdafx.h"
#include <iostream>
#include <afxwin.h>
#include <assert.h>
#include "dialog.h"
#include <thread>
DWORD WINAPI ModelessThreadFunc(LPVOID);
int _tmain(int argc, _TCHAR* argv[])
{
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), SW_SHOW))
    {
        std::cout<<"Fatal Error: MFC initialization failed\n";
    }
else
{   
    CreateThread(NULL, 0, ModelessThreadFunc, NULL, 0, NULL);
    HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"CloseModelessDialog");
    while(WaitForSingleObject(hEvent, 0))
    {
    }
    CloseHandle(hEvent);
}
return 0;
}

DWORD WINAPI ModelessThreadFunc(LPVOID)
{
    dialog *dial = new dialog;
    assert(dial->Create(dialog::IDD));
    dial->ShowWindow(SW_SHOWNORMAL);
    HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"CloseModelessDialog");
    MSG msg;
    while(WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
    {
      while(::GetMessage(&msg, NULL, 0,0) != 0)
     {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
     }
    }
    CloseHandle(hEvent);
    return 0;
}

The dialog box runs fine. But after pressing ok or close, the dialog box closes and my main program is not ending. I think the event is not closing. Could anyone clarify?

1
The program doesn't exit from internal GetMessage loop. You need PostQuitMessage to exit this loop. Or just check event in the same loop, instead of useing nested loops.Alex F
This: while(WaitForSingleObject(hEvent, 0)) is a terrible idea. your main() is effectively spinning waiting for an event to transpire rather than what you should be doing; waiting on the thread handle. And nowhere in this code do you seem to ever SetEvent regardless, not post a quite message to the thread message queue.WhozCraig
Anyway, this strange exercise can be replaced by simple modal DialogBox call from main function. Modal dialog has its own message loop.Alex F
Finally, of course the event is not closing; You didn't close the handle in main(); you closed the handle in your dialog thread. They're different handles to the same event. And closing the handle in one is not going to signal the other regardless. You would need to use SetEvent for this, but honestly you just DialogBox in the thread proc and WaitForSingleObject on the thread handle that you're incidentally leaking back in main().WhozCraig
sorry for no response from my side to your comments and answers. I am in middle of another task. Soon will execute all your feedbacks and update the results asap. Thank you.Kumar

1 Answers

0
votes

If you have your own UI thread, you can set the m_pMainWnd pointer with the address of your Dialog. You don't Need the own message Loop.

  1. Just create your own class derived from CWinThread.
  2. Create your Dialog in InitInistance as you do it now. Set the pointer to the Dialog in m_pMainWnd.
  3. Exit InitInstance with TRUE. So tis causes CWinThread::Run to execute.
  4. Create your thread with AfxBeginThread.
  5. When the Dialog Closes. ExitInstance will be called and the thread wil exit.

PS: Using CreateThread with MFC and the CRT can cause Memory leaks. Always use the CRT thread routines or AfxBeginThread.