Problem with Domodal overide behavior
-
I have written the below code in the InitInstance method of application class I have overwridden the dailog behavior by removing ok and cancel button and also by overiding the deafult behavior of esc and return virtual key down messages. Now the problem is that I want to have control such that the lines after dlg.DoModal();</ are executed as they are the lines that kill the dialog. he basic requirement to to kill the dialog only when a particular exe is executed. I'm waiting for this process to complete but that line is after DoModal after which the control is not going.
if (!CreateProcess(NULL, /* No module name (use command line). */ theApp.m_lpCmdLine, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ FALSE, /* Set handle inheritance to FALSE. */ CREATE_NO_WINDOW, /* Do not display console window */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi)) /* Pointer to PROCESS_INFORMATION structure. */ status = GetLastError(); CProgressActivityDlg dlg; m_pMainWnd = &dlg; //INT_PTR nResponse = **dlg.DoModal();** //if (nResponse == IDOK) //{ // TODO: Place code here to handle when the dialog is // dismissed with OK //} //else if (nResponse == IDCANCEL) //{ // TODO: Place code here to handle when the dialog is // dismissed with Cancel //} MessageBox(NULL, _T("Before loop"), _T("Test"), MB_OK); WaitForSingleObject(pi.hProcess, INFINITE); MessageBox(NULL, _T("Out of loop"), _T("Test"), MB_OK); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); PostMessageW(dlg.GetSafeHwnd(), WM_CLOSE ,0, 0); // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. AfxGetMainWnd()->PostMessage(WM_CLOSE, 0, 0); return FALSE;
-
I have written the below code in the InitInstance method of application class I have overwridden the dailog behavior by removing ok and cancel button and also by overiding the deafult behavior of esc and return virtual key down messages. Now the problem is that I want to have control such that the lines after dlg.DoModal();</ are executed as they are the lines that kill the dialog. he basic requirement to to kill the dialog only when a particular exe is executed. I'm waiting for this process to complete but that line is after DoModal after which the control is not going.
if (!CreateProcess(NULL, /* No module name (use command line). */ theApp.m_lpCmdLine, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ FALSE, /* Set handle inheritance to FALSE. */ CREATE_NO_WINDOW, /* Do not display console window */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi)) /* Pointer to PROCESS_INFORMATION structure. */ status = GetLastError(); CProgressActivityDlg dlg; m_pMainWnd = &dlg; //INT_PTR nResponse = **dlg.DoModal();** //if (nResponse == IDOK) //{ // TODO: Place code here to handle when the dialog is // dismissed with OK //} //else if (nResponse == IDCANCEL) //{ // TODO: Place code here to handle when the dialog is // dismissed with Cancel //} MessageBox(NULL, _T("Before loop"), _T("Test"), MB_OK); WaitForSingleObject(pi.hProcess, INFINITE); MessageBox(NULL, _T("Out of loop"), _T("Test"), MB_OK); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); PostMessageW(dlg.GetSafeHwnd(), WM_CLOSE ,0, 0); // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. AfxGetMainWnd()->PostMessage(WM_CLOSE, 0, 0); return FALSE;
tom groezer wrote:
I'm waiting for this process to complete but that line is after DoModal after which the control is not going.
This really isn't going to work as designed. If you insist on using a modal dialog, you'd have to poll for completion from within the dialog class...not a very good design. As with any other lengthy process, you should be waiting for completion on another thread so you don't block the UI thread. If you need the UI to be in a modal state until completion, there's a variety of ways to design the code. A couple examples: 1) Wrap the waiting worker thread in a modal dialog class. When the thread completes, it can notify the dialog (with a posted message) and the dialog can close itself. 2) Disable the UI so the user can't do anything during the process (if necessary), create a modeless dialog, and fire off the worker thread. When the thread completes, it can notify the UI thread, at which time the UI thread can destroy the modeless dialog and re-enable the UI. However you design it, the main point is - blocking the UI thread for any lengthy process (anything over a few seconds - some would say even less) is bad design, so lengthy processes should be done on threads separate from the UI thread. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I have written the below code in the InitInstance method of application class I have overwridden the dailog behavior by removing ok and cancel button and also by overiding the deafult behavior of esc and return virtual key down messages. Now the problem is that I want to have control such that the lines after dlg.DoModal();</ are executed as they are the lines that kill the dialog. he basic requirement to to kill the dialog only when a particular exe is executed. I'm waiting for this process to complete but that line is after DoModal after which the control is not going.
if (!CreateProcess(NULL, /* No module name (use command line). */ theApp.m_lpCmdLine, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ FALSE, /* Set handle inheritance to FALSE. */ CREATE_NO_WINDOW, /* Do not display console window */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi)) /* Pointer to PROCESS_INFORMATION structure. */ status = GetLastError(); CProgressActivityDlg dlg; m_pMainWnd = &dlg; //INT_PTR nResponse = **dlg.DoModal();** //if (nResponse == IDOK) //{ // TODO: Place code here to handle when the dialog is // dismissed with OK //} //else if (nResponse == IDCANCEL) //{ // TODO: Place code here to handle when the dialog is // dismissed with Cancel //} MessageBox(NULL, _T("Before loop"), _T("Test"), MB_OK); WaitForSingleObject(pi.hProcess, INFINITE); MessageBox(NULL, _T("Out of loop"), _T("Test"), MB_OK); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); PostMessageW(dlg.GetSafeHwnd(), WM_CLOSE ,0, 0); // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. AfxGetMainWnd()->PostMessage(WM_CLOSE, 0, 0); return FALSE;
Here's an example of method 1 in my previous post:
//--------------------------------------
// IDD_PROCESSWAITER dialog resource
//--------------------------------------IDD_PROCESSWAITER DIALOGEX 0, 0, 193, 50
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
CAPTION "Waiting..."
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CTEXT "Waiting for process to complete...",IDC_STATIC,7,17,179,8
END//--------------------------------------
// ProcessWaiter.h
//--------------------------------------#pragma once
// CProcessWaiter dialog
class CProcessWaiter : public CDialog
{
DECLARE_DYNAMIC(CProcessWaiter)CString ProcessPathname; static UINT \_\_cdecl ProcessCreatorAndWaiterThread(LPVOID pParam);
public:
CProcessWaiter(CWnd* pParent = NULL); // standard constructor
virtual ~CProcessWaiter();INT\_PTR ExecuteProcessAndWait(LPCTSTR pathname);
// Dialog Data
enum { IDD = IDD_PROCESSWAITER };protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV supportDECLARE\_MESSAGE\_MAP()
protected:
virtual BOOL OnInitDialog();
virtual void OnOK();
virtual void OnCancel();
afx_msg LRESULT OnThreadComplete(WPARAM wParam, LPARAM lParam);
};//--------------------------------------
// ProcessWaiter.cpp
//--------------------------------------// ProcessWaiter.cpp : implementation file
//#include "stdafx.h"
#include "ProcessWaiter.h"#define WMX_THREADCOMPLETE (WM_APP + 42)
// CProcessWaiter dialog
IMPLEMENT_DYNAMIC(CProcessWaiter, CDialog)
CProcessWaiter::CProcessWaiter(CWnd* pParent /*=NULL*/)
: CDialog(CProcessWaiter::IDD, pParent)
{
}CProcessWaiter::~CProcessWaiter()
{
}INT_PTR CProcessWaiter::ExecuteProcessAndWait(LPCTSTR pathname)
{
ProcessPathname = pathname;return DoModal();
}
UINT __cdecl CProcessWaiter::ProcessCreatorAndWaiterThread(LPVOID pParam)
{
CProcessWaiter *pThis = (CProcessWaiter*) pParam;PROCESS\_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; memset(&StartupInfo, 0, sizeof(STARTUPINFO)); StartupInfo.cb = sizeof(STARTUPINFO); if (0 != ::CreateProcess(pThis->ProcessPathname,// LPCTSTR lpApplicationName, NULL, // LPTSTR lpCommandLine, NULL, // LPSECURITY\_ATTRIBUTES lpProcessAttributes, NULL, // LPSECURITY\_ATTRIBUTES lpThreadAttributes, FALSE, // BOOL bInheritHandles, NORMAL\_PRIORITY\_CLASS, // DWORD dwCreationFlags, NULL
-
Here's an example of method 1 in my previous post:
//--------------------------------------
// IDD_PROCESSWAITER dialog resource
//--------------------------------------IDD_PROCESSWAITER DIALOGEX 0, 0, 193, 50
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
CAPTION "Waiting..."
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CTEXT "Waiting for process to complete...",IDC_STATIC,7,17,179,8
END//--------------------------------------
// ProcessWaiter.h
//--------------------------------------#pragma once
// CProcessWaiter dialog
class CProcessWaiter : public CDialog
{
DECLARE_DYNAMIC(CProcessWaiter)CString ProcessPathname; static UINT \_\_cdecl ProcessCreatorAndWaiterThread(LPVOID pParam);
public:
CProcessWaiter(CWnd* pParent = NULL); // standard constructor
virtual ~CProcessWaiter();INT\_PTR ExecuteProcessAndWait(LPCTSTR pathname);
// Dialog Data
enum { IDD = IDD_PROCESSWAITER };protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV supportDECLARE\_MESSAGE\_MAP()
protected:
virtual BOOL OnInitDialog();
virtual void OnOK();
virtual void OnCancel();
afx_msg LRESULT OnThreadComplete(WPARAM wParam, LPARAM lParam);
};//--------------------------------------
// ProcessWaiter.cpp
//--------------------------------------// ProcessWaiter.cpp : implementation file
//#include "stdafx.h"
#include "ProcessWaiter.h"#define WMX_THREADCOMPLETE (WM_APP + 42)
// CProcessWaiter dialog
IMPLEMENT_DYNAMIC(CProcessWaiter, CDialog)
CProcessWaiter::CProcessWaiter(CWnd* pParent /*=NULL*/)
: CDialog(CProcessWaiter::IDD, pParent)
{
}CProcessWaiter::~CProcessWaiter()
{
}INT_PTR CProcessWaiter::ExecuteProcessAndWait(LPCTSTR pathname)
{
ProcessPathname = pathname;return DoModal();
}
UINT __cdecl CProcessWaiter::ProcessCreatorAndWaiterThread(LPVOID pParam)
{
CProcessWaiter *pThis = (CProcessWaiter*) pParam;PROCESS\_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; memset(&StartupInfo, 0, sizeof(STARTUPINFO)); StartupInfo.cb = sizeof(STARTUPINFO); if (0 != ::CreateProcess(pThis->ProcessPathname,// LPCTSTR lpApplicationName, NULL, // LPTSTR lpCommandLine, NULL, // LPSECURITY\_ATTRIBUTES lpProcessAttributes, NULL, // LPSECURITY\_ATTRIBUTES lpThreadAttributes, FALSE, // BOOL bInheritHandles, NORMAL\_PRIORITY\_CLASS, // DWORD dwCreationFlags, NULL
Nice example :)
Greetings. -------- M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you “The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
-
Nice example :)
Greetings. -------- M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you “The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Is it ok to have something like below to be posted. I just wanted to know whether passing WM_CLOSE is good enough as EndDialog(); PostMessage((((CProgressActivityApp*)lpParam)->m_pMainWnd)->GetSafeHwnd(), WM_CLOSE, 0, 0);
-
Is it ok to have something like below to be posted. I just wanted to know whether passing WM_CLOSE is good enough as EndDialog(); PostMessage((((CProgressActivityApp*)lpParam)->m_pMainWnd)->GetSafeHwnd(), WM_CLOSE, 0, 0);
Yes it's ok. The problem is, your code will never get there to post the message until the dialog closes, which isn't going to happen :) Mark
Mark Salsbery Microsoft MVP - Visual C++ :java: