How to find window associated with CFileDialog Open File from AfxGetMainWindow() in MFC Application

Aakash 60 Reputation points
2023-11-20T18:14:16.44+00:00

Hello everyone,

I am trying to close an MFC application from code. I have added code to save any open documents before the close function is called. I would like to close all open dialog boxes from the application before the main frame exits by sending a close message as shown below:

AfxGetMainWnd()->SendMessage(WM_CLOSE);
PostQuitMessage(0);

I am able to successfully capture dialog box instances within the application (derived from CDialog) and send an IDCancel to their dialog boxes to close them. However, I am encountering issues with capturing the dialog window for any CFileDialog window (either Open File or Save As). I'm only interested in modal dialogs and below is the code I use to capture the window instances corresponding to open dialogs.

vector<CWnd*> GetAllActiveModalDialogWindow(const CWnd* pWnd)
	{
		vector<CWnd*> allDialogWindows;
		CWnd* pChildWnd = pWnd ? pWnd->GetNextWindow(GW_HWNDPREV) : NULL;
		while (pChildWnd)
		{
			if (pWnd == pChildWnd->GetTopLevelParent() &&
				(pChildWnd->IsKindOf(RUNTIME_CLASS(CDialog))|| pChildWnd->IsKindOf(RUNTIME_CLASS(CFileDialog)) ||
					pChildWnd->IsKindOf(RUNTIME_CLASS(CPropertySheet))))
			{
				allDialogWindows.push_back(pChildWnd);
			}

			pChildWnd = pChildWnd->GetNextWindow(GW_HWNDPREV);
			
		}
		return allDialogWindows;
	}

The above only seems to return windows that correspond to dialogs part of my application and none of CFileDialog. Upon using Spy++, I notice that the classname for any dialog (incl. for File Open) is "#32770".
I tried the below code to try and capture all dialogs but once again I only seem to be returned dialogs from my application.

vector<CWnd*> GetAllActiveModalDialogWindow(const CWnd* pWnd)
	{
		vector<CWnd*> allDialogWindows;
		TCHAR szClassName[MAX_PATH];
		CWnd* pWndChild = pWnd->GetWindow(GW_CHILD);
		while (pWndChild)
		{
			::GetClassName(pWndChild->GetSafeHwnd(), szClassName, MAX_PATH);

			if (_tcscmp(szClassName, "#32770") == 0)
				allDialogWindows.push_back(pWndChild);

			pWndChild = pWndChild->GetWindow(GW_HWNDNEXT);
		}

		return allDialogWindows;
	}

The pWnd parameter in above function is pointer to main window in the application i.e AfxGetMainWnd()

I've been stuck on this problem for weeks now and I would really appreciate some insights and opinions.

Supporting Information: VS2019, include afxdlgs.h

Thank you all and I hope you have a wonderful day!

Best,

Aakash

Windows development | Windows API - Win32
Developer technologies | C++
{count} votes

Accepted answer
  1. David Lowndes 2,640 Reputation points MVP
    2023-11-20T23:01:05.8733333+00:00

    If you use Spy++ and find the open/save dialogs in the hierarchy, I think you'll find that they're parented by the desktop, not your own application window. However, they appear to be owned by the appropriate window of your application, so maybe searching for them that way will work.

    2 people found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Aakash 60 Reputation points
    2023-11-28T18:52:49.15+00:00

    Thanks to @David Lowndes comment on Spy++ and window hierarchy, I was able to find a solution. For those interested, I basically call the GetDesktopWindow() and loop over the child windows and during the process I check if the owner of this child window is any of the dialog window (or the parent window) from my application. This way I avoid capturing open dialogs that are unrelated to my application. It might not be the most efficient solution but it seems to get the job done.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.