Making a CDialog visible - visual-studio

I'm trying to get a DialogBox with a check box to appear. I added it to the resource file, created the dialog template, and added the class and event handler for the dialog. As I understand it, now I just need to create an instance of the class and call DoModal().
So, I've gone back and done some investigating and played with the code some and this is what I have now
UsingMSPSK PSKDialog;
if( PSKDialog.DoModal() == IDOK)
{
}
else {
AfxMessageBox("Not IDOK");
}
CTempoDialog TempoDialog;
if(TempoDialog.DoModal() == IDOK)
{
}
When I run this, I get no dialog from the PSLDialog.DoModal() call, but I get the AfxMessageBox, then The TempoDialog appears. I stepped through the DoModal() call in the debugger and it seemed to run and return properly, so I can't figure out where my Dialog Box is going.
I just looked at the return value of the DoModal() call again, and it seems that it is exiting immediately, how can I fix that?

It should work to make the dialog visible - assuming the dialog template has the WS_VISIBLE style and so on. Maybe the dialog initialisation is failing? Does the "DoModal" dialog call exit immediately? This would indicate a failure to create the window.
What version of Visual Studio are you using? Version 6 used to not let you set breakpoints on code that was not yet loaded. Alternatively, make sure that the symbols are loaded. In the Modules window, right click the dll containing your code and choose "Load symbols". Are you making a debug build with symbolic information, or a release build? Make sure it is a debug build for the easiest debugging experience.

I'm not sure why this happened, but the check box I added was an ActiveX control, and it broke my dialog box. When I discovered the toolbox pane, and dragged a check box from there, it worked fine.

Related

Unexpected CDialog DoModal() behavior

I am debugging a strange issue with a 3rd party library that displays a formatted message box. The library uses a class based on CDialog and runs the message box dialog with the DoModal() method. Sometimes a message is displayed from a common subroutine that uses the handle of the main window as the parent (type 1), other times from another modal dialog (type 2).
Sometimes a Type 1 call is triggered by an action in a modal dialog and when this happens, the original dialog is no longer modal after the message dialog is dismissed. Changing nothing except the formatted message box with the system default message box and the original dialog stays modal, as expected.
When a Type 2 call is made, the original dialog always remains modal, so I am working to ensure that is how I call the library function, but this looks like it might be a bug in the CDialog itself, so I thought I would ask if anyone knows about this.
I have never worked with these class libraries before (I'm an old school C guy), but it looks like the library is always using EndDialog() to terminate the modal message box and there's no "fancy, low-level" windows stuff that I can find (other than the message formatting). It is probably obvious that I don't really know what I'm asking, so if there is a better place to discuss this, please send me there.
On the other hand, if anything derived from CDialog and DoModal() does this, it would appear to be a bug in the class library, since built-in modal dialogs (like MessageBox) do not have this unwanted effect. I would share the library code, but I am not the original author and I don't have permission, but I am willing to look for things as long as you are willing to have some patience for someone not familiar with C++ code structuring.
I don't know whether my answer will help you a bit.
but there is property for a Dialog box - "System Modal", which makes it System Modal Dialog.
If you set it to True, your Dialog becomes a System Modal Dialog Box.

Crash when calling getOpenFileName from QItemDelegate's custom editor

Prerequisites:
I have a custom QItemDelegate which creates custom editor for treeview items.
The editor consists of a QLineEdit and QToolButton. The button is used to open the file dialog for selecting the file and placing it's path into line edit.
I use a call to QFileDialog::getOpenFileName to open the file dialog. The dialog is native Windows file dialog (this is important).
When the editor is created the first time, everything works ok no matter how often I press that button. But after the editor is closed and reopened again the first press on the button results in a crash. The reason of the crash is that my custom editor eventually gets deleted.
Here is some code:
void CCustomEditor::on_RunSetupBtn_clicked()
{
auto qFilename = QFileDialog::getOpenFileName(this,
"Select application to run",
QString(),
"Executable files (*.exe)");
if (qFilename.isEmpty())
return;
SetCommandLine(QDir::toNativeSeparators(qFilename), m_qParameters);
}
I have made some digging and found out that calling WinAPI function GetOpenFileName results in the very same way: my editor gets deleted (although crash doesn't happen). It seems that Qt calls it also internally.
I have tracked down the reason of why my editor gets deleted and found out that when getOpenFileName is called, active window changes and focus changes with it.
In the first case the focus is moved from TreeView item, but in the second case it is moved from the editor itself!
This results in the deletion of editor because of 'focus out' event.
It is important to say that this situation doesn't happen if 'DontUseNativeDialog' flag is set when file dialog is created. Therefore this should be a bug in Qt's window management between native windows and Qt widgets.
As a workaround of this bug I suggest the following solution: before making a call to getOpenFileName set the focus to the button itself.
m_pUI->RunSetupBtn->setFocus();
auto qFilename = QFileDialog::getOpenFileName(this,
"Select application to run",
QString(),
"Executable files (*.exe)");
The other workaround is to use 'DontUseNativeDialog' flag, but the resulting file dialog doesn't look native, in fact it is quite ugly.
If someone has a better solution, feel free to share.
I have a similar problem with getOpenFileName and getSaveFileName. My solution is, after getOpenFileName, getSaveFileName or at the end of the function set the windows as active with activateWindow().

CMFCToolbar ReplaceButton() causes button to disappear

Using Visual Studio 2010 and working with an MFC SDI Application.
I have a CMFCToolbar object owned by the Main Frame.
When the document in this application is created, the MainFrame calls a function to replace one of the buttons in the CMFCToolbar object with a CMFCToolbarMenuButton. The contents of the menu button are populated with information from the document. The menu creation always works. The call to ReplaceButton always succeeds. But there's a visual symptom of the call that I haven't yet figured out.
Any time ReplaceButton is called, the button disappears. Not only is it not drawn, it's not clickable. It's temporarily gone. I assume this is because there's a dangling reference to the old button, which I have just destroyed with the call to ReplaceButton.
I've tried calling Invalidate(), RecalcLayout() to trigger a re-draw, but neither has worked yet. The only reliable method I have for getting the button to show up is re-sizing the application window manually or by un-docking/re-docking the toolbar. I assume there's some kind of lower-level refresh that occurs in these situations, but I don't know how to trigger it manually.
Is there a way to make sure my button is drawn immediately?
Edit: code sample
Count = m_Doc->...->GetCount();
for (Index = 0; Index < Count; ++Index)
{
Caption.Format(L"%s", m_Doc->...->GetName());
m_pLayerMenu->AppendMenu(MF_ENABLED | MF_STRING, LAYER_DROP_SEED+Index, Caption.GetData());
}
m_wndBrushBar.ReplaceButton(ID_BRUSH_TERRAIN,
CMFCToolBarMenuButton(ID_BRUSH_TERRAIN, *m_pLayerMenu, GetCmdMgr()->GetCmdImage(ID_BRUSH_TERRAIN)));
Update:
Calling m_wndBrushBar.AdjustLayout() seems to stabilize the visual behavior of these CMFCToolbar buttons. So that's a partial solution.
Partial because of the following:
It's hard to tell what the real visual behavior is. It turns out that all visual settings/states are stored in the Registry with these MFC objects, and it can hold onto states of dynamically created objects that really alter the startup behavior of the app.
I've gone in to delete the registry values under
Current User -> "Local App-Wizard Generated Applications" -> [My App Name].
Done this a number of times, just to find out what the real behavior of my app is. Feel like I'm missing some fundamental knowledge with the current version of MFC. Lots of bugs arising from the registry deal.
Is there a way to prevent registry settings for certain objects, or to shut off this behavior altogether? Otherwise, I guess my shutdown process will have to be a LOT more thorough with resetting all the visual elements. Registry values seem to ignore, override, or bypass my startup code. I can code how I want an object to look at startup, but if there are values in the registry, it does no good.
You've discovered a sometimes annoying aspect for the CMFC code. That is, the concept of a Workspace. The Workspace manages the concept of the application state. I, too, have had problems like the one you describe. But, you have the flexibility to manage how those objects are recreated by overriding the LoadState () and SaveState () methods.

Clicking on PictureBox with AutoIt ControlClick fails

I am trying to automatically click a PictureBox control from an old VB6 application using AutoIt. Window Info finds a control with class ThunderRT6PictureBoxDC and ID 15, and AutoIt successfully hides it if I run...
ControlHide($class, "", "[ID:15]")
However, when I try to click it using:
ControlClick($class, "", "[ID:15]")
...nothing happens - and #error is unset.
Clicking using MouseClick with the control coordinates works, but then I have to make sure that the window isn't covered by anything.
Does anyone know why nothing happens, and what I can do to workaround without resorting to MouseClick?
I don't know AutoIt, but possibly this is because the control is a PictureBox rather than a button, so Windows doesn't support the concept of a "click" on this control. Can't think of any alternative workaround.

How do you display a dialog from a hidden window application?

I have developed a COM component (dll) that implements an Edit() method displaying a WTL modal dialog.
The complete interface to this COM component corresponds to a software standard used in the chemical process industry (CAPE-OPEN) and as a result this COM component is supposed to be usable by a range of 3rd party executables that are out of my control.
My component works as expected in many of these EXEs, but for one in particular the Edit() method just hangs without the dialog appearing.
However, if I make a call to ::MessageBox() immediately before DoModal() the dialog displays and behaves correctly after first showing the MessageBox.
I have a suspicion that the problem may be something to do with this particular EXE running as a 'hidden window application'.
I have tried using both NULL and the return value from ::GetConsoleWindow() as the dialog's parent, neither have worked.
The dialog itself is an ATL/WTL CPropertySheetImpl.
The parent application (EXE) in question is out of my control as it is developed by a (mildly hostile) 3rd party.
I do know that I can successfully call ::MessageBox() or display the standard Windows File Dialog from my COM component, and that after doing so I am then able to display my custom dialog. I'm just unable to display my custom dialog without first displaying a 'standard' dialog.
Can anyone suggest how I might get it to display the dialog without first showing an unnecessary MessageBox? I know it is possible because I've seen this EXE display the dialogs from other COM components corresponding to the same interface.
Are you using a parent for the Dialog? e.g.
MyDialog dialog(pParent);
dialog.DoModal();
If you are, try removing the parent. Especially if the parent is the desktop window.
Depending on how the "hidden window" application works, it might not be able to display a window. For example, services don't have a "main message loop", and thus are not able to process messages sent to windows in the process. i.e, the application displaying the window should have something like this:
while(GetMessage(&msg, NULL, 0, 0))
{
if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
in WinMain.
This isn't supposed to be reliable - but try ::GetDesktopWindow() as the parent (it returns a HWND).
Be warned - if your app crashes, it will bring down the desktop with it. But i'd be interested to see if it works.
It turns out I was mistaken:
If I create my dialog with a NULL parent then it is not displayed, and hangs the parent application
However if I create my dialog with ::GetConsoleWindow() as the parent then the dialog is displayed; it just fooled me because it was displayed behind the window of the application that launched the parent application
So now I just have to find out how to bring my dialog to the front.
Thanks for the answers ;-)
Whatever you do, do not use the desktop window as the parent for your modal dialog box.
See here for explanation: http://blogs.msdn.com/b/oldnewthing/archive/2004/02/24/79212.aspx
To quote the rationale:
Put this together: If the owner of a
modal dialog is the desktop, then the
desktop becomes disabled, which
disables all of its descendants. In
other words, it disables every window
in the system. Even the one you're
trying to display!

Resources