Receiving results from dialogs - c++

I am trying to get some data from a dialog in an MFC C++ dialog-based application. I ahev made this image to help you understand better my situation:
When the user clicks the findWndBtn in the left-side window, the right-side dialog appears by dlg.DoModal() function. After the user completes the fields in the right-side the dialog, the following code is executed:
HWND WindowHandle = FindWindow( WindowClass, WindowName );
CDialogEx::OnOk();
After the dialog exits, I want the m_myWndHwnd field to pe filled with the handle found by that dialog.
How can I do that?
Tell me please, If didn't said enough, for me to complete with the detail that you need.

Two options:
Have the second dialog post a message back to the first dialog, passing the result you want to store as an argument.
Have the second dialog store the result in a class member variable, and have the caller retrieve it (via a member function or directly if you're OK with that) when the dialog returns.

Related

Using a dialog box as a main window. Not receiving WM_INITDIALOG messages

I have created a modeless dialog as a main window, but the window procedure isn't being sent WM_INITDIALOG messages.
Here's what I've done.
Created a dialog template using Visual Studio's resource editor, and
set its class name to a custom class.
Used WNDCLASSEX to register the class, window procedure, as well as
some icons and brush etc.
Used CreateDialog() with the last two parameters set to NULL, (Parent
window, and window procedure).
Created the message loop using IsDialogMessage(), TranslateMessage()
and DispatchMessage();
Returned DefDlgProc() in the window procedure as the default if no
messages were processed.
I can't think of anything else significant. Everything works well except for not receiving WM_INITDIALOG messages.
I've done it this way so the app minimises to the task bar, and I can have a menu if needed.
So my first question is, Have I done anything stupid?
Secondly, should I expect to receive WM_INITDIALOG messages using this system?
And if not, what is a good way to initialise say a combobox with strings.
(I've looked at things like WM_ACTIVATE, WM_ACTIVATEAPP etc, but nothing seems appropriate.
And the combobox isn't created yet at WM_CREATE.)
Thanks in advance.
I realised the answer shortly after posting.
As mentioned in the comments above, it's a window procedure, not a dialog procedure, so I shouldn't have been trying to initialize child windows within the procedure.
So I initialized them outside the procedure, after creating the dialog box and before the message loop.
All the dialog features are working as expected, but it's a main window that can have a menu and minimizes to the taskbar.

Capturing the window handle of a newly created modal dialog

I'm using and improving on an open source MFC work-alike library called FFC. Sometimes the library associates the wrong window handle to a dialog object, which means the C++ object can't be found later when the correct handle is looked up. In particular, this is happening when the application opens its root window, which is a dialog that it opens with a call to DoModal.
In its DoModal function, the FFC library uses a... "surprising" way to attach the handle to the dialog object. It stashes the "this" pointer in a global variable and hooks a function to be called on all window messages before calling the DialogBox function. This hook function it registered in term assumes the handle from the first message it receives is the handle for the window in the global variable, and attaches that handle to it.
Sometimes, this works. Often - and I don't know if it's because of intrusive things done by the McAfee scanner on my work computer, or because my program starts from a console window, or something else - many unrelated messages will be captured before a message actually meant for the modal dialog comes through.
At first I thought it was because FFC wasn't making sure the message it looks for is "WM_CREATE". I added this check, but it didn't fix the problem. Turns out one or more of the spurious messages are also WM_CREATE messages! Before it gets the one for the real dialog, the first WM_CREATE it receives is a handle for a window with blank window text and rectangle 0,0-0,0.
So is this really the correct or canonical way to get the handle for a modal dialog? It seems unreliable. (Note that because the dialog is modal, you can't use the return value from CreateWindowEx because the DialogBox function doesn't return until the modal dialog is closed.) Is this really how MFC does it? Is there a better way? Could I associate some data with the dialog or look for data that should be associated with it to make sure I have the right window handle? (For instance checking the template parameter passed to the dialog box call, if I can get that back from the handle somehow.)
I am sure this is published in books, but MFC sets a windows hook (WH_CBT) and then looks for the HCBT_CREATEWND code in the hook to marry the C++ object to the HWND.

MFC one parent dialog, multiple child dialogs

I want to build a MFC application, with one main dialog, and all the other dialogs are child of this main dialog (and embedded in it).
Now, i was able to embed the first child in the main dialog, but i want to pass to the next dialog (note that the order of opened dialogs is random), so i need to hide the first dialog and show another. To know which dialog is shown at the moment and hide it, i've tried using a CDialog variable to store the current opened dialog, but i get a CObject::operator =' : cannot access private member declared in class 'CObject' error.
Is there another way to do this "hide and show dialogs" game?
EDIT: Could i store some ID of the dialogs and use it to acomplish this task?
So i managed to accomplish this task using classes IDDs.
First, i store the last opened dialog's IDD
m_dlgStartPage.Create(CStartPageDlg::IDD, this);
m_openedWin.nDialogIDD = m_dlgStartPage.IDD;
m_dlgStartPage.ShowWindow(SW_SHOW);
Then, when a new dialog needs to be shown, i send a message to my main dialog (nIDD is the IDD of pending dialog to show):
AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND_CHANGE_WINDOW, nIDD, 0);
And last, in my main dialog, i parse all the child dialogs and check if m_openedWin.nDialogIDD matches with each dialog's IDD, so i can hide it. After this, i parse once again all the chid dialogs and use the nIDD from the sent message to show the correct one.
I don't really like this approach, because of all the parsing and sent messages to the main dialog's class, so if anyone has a better idea or method, please post it.

Passing values between dialog boxes in mfc

When using MFC, if i have a main dialog box, then I another dialog box is called from the main, what message is sent to the main dialogue box to let it know it has focus, is it WM_SETFOCUS()? If so, what paramaters are needed? The problem I have is, a value is selected in the child dialog and I want it copied to an edit control in the main dialog box once it (the child dialog) closes. Right now, I have it so the second dialog box copies its value to a global variable, but once the second dialog box closes, I wanted to the main dialog box to grab the global variable and display in the edit control.
You can also use a member variable in the child dialog box, like
CChildDialogBox dlg;
if (dlg.DoModal() == IDOK) // child dialog saves the value in a CString member variable m_str
{ GetDlgItem(IDC_EDIT1)->SetWindowText(dlg.m_str);
}
This MSDN article describes how you can set up member variables connected to controls in a dialog box.
I realized my problem, really a beginner's mistake, I though after a DoModal call a function would immediately exit. I didn't know I could perform additional code(assigning the edit control variable a new value and then SetWindowText) after the call, before the function ended.

win32 DialogBox app: how to show text from callback on the DialogBox?

I'm working on a win32 DialogBox based app. This uses DialogBox() to create the dialog box, and has a dialog box procedure which does all the usual things.
The dialog box has some static text controls on it, and generally I'm showing text in these via SendDlgItemMessage() from within the dialog box procedure.
However at one point the DialogBox initiates a lengthy operation. This operation has a callback with a series of status messages. I'm having some trouble showing these messages on the dialog box, for two reasons:
The callback function doesn't know what the dialog box HWND is, because it gets called from the code which carries out the lengthy operation. I suppose I can define a file scope HWND variable and copy the dialog box HWND into it from the dialog box procedure just before the lengthy operation is started. That way, the callback function could have access to the dialog box HWND. But that seems awfully kludgy: is there a more elegant way?
The dialog box procedure is blocked while the lengthy operation happens. This doesn't matter because it's an embedded system. But will Windows even show the text in the dialog box if I issue a SendDlgItemMessage() while the dialog box procedure is blocked?
edit I've done some investigations using SendDlgItemMessage() to send a WM_SETTEXT to a static text control on a dialog. The text is displayed immediately even if the dialog box procedure is blocked.
Well, your dialog HWND is a singleton so it isn't the end of the world. But yes, the standard way this is done is by passing an opaque pointer to the code that gets the job done. Compare with the lParam argument of EnumWindows() for example, the callback gets that pointer back.
Whether a control repaints itself immediately is an implementation detail. I only know of progress bar doing this. You could call UpdateWindow on the dialog window handle to get any pending paint updates flushed to the screen.
The all-around better mouse trap is to perform long running tasks on a worker thread. Avoids Windows displaying the "Not Responding" ghost window, avoids timeouts on broadcast messages and numerous potential deadlock problems. But tends to be tricky to get right, you cannot update the window directly from the worker thread.