Qt 4.7.1
I have a qttest setup which has until recently been performing well. I have encountered, and dealt with, the need to interact with modal dialogs by using singleshot timers.
However, I am now seeing the opposite behaviour; calls such as QFileDialog::getSaveFileName are returning straight away with no display of the dialog. This is since I performed a merge so I assume there is some code or build change behind it, but it isn't the function call itself.
As far as example code goes, I can't post my whole framework or AUT but the consider the following inside a test function:
QMessageBox::StandardButton button = QMessageBox::question(NULL,"Thing",
"Do you want to do a thing?",
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No);
The call returns straight away and button is set to NoButton. I should add that there is a bit of a framework around my tests and I manually start each test with QTest::qExec. (The framework has not changed, of that I'm sure)
Any ideas on what might be causing this?
Edit:
The eventloop started by the messagebox in the above example has quitNow set to true, which is causing exec to return straight away. I'm now looking for why this is set, in the meantime feel free to enlighten me!
This was due to calling qApp->exit() in my cleanup() function. There is no need to do this!
Related
I've searched this extensively, and the answer I came up with about 20 times is to use CWnd::EnableWindow(FALSE). Currently, I have:
GetDlgItem(myComboBox)->EnableWindow(FALSE);
Instead of disabling the ComboBox, now the entire Dialog doesn't show up, and since it's a modal dialog (or at least I'm guessing that's the reason), the entire program gets locked up because I can't close the dialog if it's not there.
Is there a way to disable editing to this box without making it disappear entirely; similar to what SetReadOnly() does for a CEdit?
Edit:
Suddenly, the syntax above started working the next morning. I'm still not entirely sure why it didn't work in the first place.
EnableWindow(FALSE) is the correct function to call but your syntax looks like it may be incorrect (but it's hard to say with such a minimal example).
Is myComboBox an instance of CComboBox? If so, I'd expect to see:
myComboBox.EnableWindow(FALSE);
or, using the associated resource ID:
((CComboBox*)GetDlgItem(IDC_MY_COMBO_BOX))->EnableWindow(FALSE);
Threading issues or duplicate resource ID's can also cause weird issues.
It seems you are trying to call EnableWindow() from a different thread than the dialog's
You could try this, and see if it works for you:
GetDlgItem(myComboBox)->PostMessage(WM_ENABLE, (WPARAM)FALSE);
I am using wxWidgets 3.0.2 with Gtk on Linux.
I am trying to make a wxDataViewCtrl a drop target for a drag and drop operation. I derived a class from wxTextDropTarget and then made a call to wxDataViewCtrl::SetDropTarget() to make an instance of this class to be the drop target for the wxDataViewCtrl.
However, nothing happens. Every time I try to drop something on the wxDataViewCtrl, the wxDropSource::DoDragDrop() method returns wxDragCancel. For my custom wxTextDropTarget class, I overrode the OnEnter() method and had it write to stdout "OnEnter()" whenever I entered the wxDataViewCtrl with something to drop, but nothing gets written to stdout.
To test that I am even doing the custom wxTextDropTarget class right and setting up the drop source correctly, I added a wxTextCtrl to my GUI and made that the drop target and everything worked as expected: wxDropSource::DoDragDrop() returned wxDragCopy and "OnEnter()" would get written to stdout when I entered the wxTextCtrl with something to drop.
Does wxDataViewCtrl not support DnD? Or is there something else I am overlooking?
Just thought I'd follow up on my own post in case somebody else runs into the same problem.
After writing a small test program just to test DnD between a control and a wxDataViewCtrl and discovering that it works fine, I went back to my original application and stared at it for a bit longer to try and figure out what was I was doing differently. It turns out that I needed to call SetDropTarget() on the PARENT window of the target wxDataViewCtrl and not the wxDataViewCtrl itself, i.e. my_data_view_ctrl->GetParent()->SetDropTarget(blah blah blah);.
However, I didn't have to do this in my test program, so I thought it was a bit weird. The only difference between my test program and my actual program was that in my actual program, I have the wxDataViewCtrl inside a wxStaticBoxSizer and I think that was problem. I suspect that the wxStaticBox (that the wxStaticBoxSizer uses) was getting the drop notification instead of the wxDataViewCtrl, hence why I needed to set it's SetDropTarget() rather than the wxDataViewCtrl.
The subject says it all. After i closed my app, it stays in the list of processes with some memory. I tried google perf tools and hours of debugging to find the leak.
Are there other tools to test it and find the problem?
Thank you.
My guess is that you have closed the top level window, and thus all its child windows, but you have not closed the app itself.
This does not happen if your program is arranged in a 'normal' way, but if you have, deliberately or by accident, used an unusual arrangement this can happen.
Fixing it, of course, depends on how exactly you have arranged your code. However, here is a suggestion to begin.
The usual way to close the app is to call wxApp::OnExit() which normally occurs when the top level window closes.
Do you have your own class, derived from wxApp? Do you have an override of OnExit()? If not, then make it so and use the debugger to check whether or not it is being called. If it is not being called, work out how to ensure that it is called.
Another idea: use the following to check that your top level window will close the app
bool wxApp::GetExitOnFrameDelete() const
Returns true if the application will exit when the top-level window is
deleted, false otherwise.
If this return false, use the corresponding set to make it so.
A 3rd idea: The application will not exit while there are any top level windows open. So perhaps you have another top level window that is minimized or invisible but has not been closed? Any wxDialog or WxFrame or window derived from these is a top level window and will prevent the application from closing.
A 4th idea: Do you have any globals or attributes of the application object, whose destructors could enter an endless loop? These destructors are called after the windows are destroyed and if one of them does not return you would see the behaviour you describe.
You may try to look at wxWidget's sample folder. You'll find lots of small but complete applications that contain the full init/exit application cycle.
Inspect some samples and compare with your app's workflow.
Yes...problem solved. A TopLevelWindow that was not destroyed. A Memory Leak....stupid mistake.
I have a third party encryption library, which may create a MessageBox if key creation fails. The failure can be caused by bad random number generation or other rarities, and in most cases, trying again will result in success. My code will attempt key creation up to three times before deciding it failed.
Now, the issue is that the program may be used with automation. If a MessageBox is created during automation, it will block the process forever, because there's nobody to click the 'OK' button.
Does anyone know of a way to catch when this message box is created and automatically close it?
Anything is fair game, as long as it's not something that will make security suites angry. This means no hooking or code tunneling.
In summary, I need to catch when a MessageBox is created and close it. The MessageBox's creation is outside of my control. Modifying the code at runtime is not acceptable.
Also, I've noticed there are some other similar questions, but they don't have the same requirements.
EDIT: Additional note, I can find the message box via searching through all windows until I find one with a matching title and then send it a WM_CLOSE message, but I don't think this is a great solution. I also have no guarantee that the message box has been/will be displayed, or how long after my call it will be displayed. It could display instantly, it could display 1200 ms later, or it could not display at all.
Just before you begin the encryption process, install a WH_CBT hook, and in its callback watch for an nCode of HCBT_CREATEWND. If you get a matching class name ('#32770 (Dialog)' ?) and a matching title either return a nonzero value from the callback, or if that doesn't work post a WM_CLOSE (or a BM_CLICK to a relevant button if selecting an option is necessary). Uninstall the hook after the process for not messing with every possible dialog your application pops up.
That sounds like bad design on the part of that library. Generally any sort of utility library (like encryption) has no business invoking any kind of GUI (unless you explicitly ask it to).
Is there possibly some configuration or setting in this library that could disable its use of message boxes?
If not, I'd suggest that you might want to investigate using a different library. After all, if the designers of this library have already made this kind of poor design decision once, then there may be other unfortunate surprises lurking in there.
You can hope that it will be found by GetForegroundWindow, but this may catch other applications. The more brute force way is to iterate over all windows with EnumWindows looking for something that has a caption or text equal to this shown by the library.
I have once "remote controlled" an application by sending mouse click events to some controls. I guess you would have to do this in a separate thread that is watching for Events if a window is opened. Pretty ugly but working...
Create a new thread. If your function fails and a Message Box is opened, obtain a handle to the message box by looping through the windows (GetTopWindow, GetNextWindow) and comparing the window's process id to the one returned from GetCurrentProcessId().
Or, you can avoid all the hard work and just hook the MessageBox API with detours. It's not very hard, and if you don't want to pay for detours, you can do it manually.
Call VirtualProtect and set the memory protection at MessageBox at PAGE_EXECUTE_READWRITE
Create a naked function, and use it as a trampoline.
Create a function identical in parameters to MessageBox (this will be your hook)
Create a jump from MessageBox to your hook function.
We have a legacy build infrastructure for nightly builds (implemented in Perl) to compile, link and unit tests our applications/plugins. On Windows, if the unit testing process crashes, this pops up a Modal Dialog which "locks" our build farm.
Is there a way (win32 API call, system config, env var, something...) to disable this behavior to have the child process terminate immediately on crashes, with no Modal Dialog and a non-zero exit status instead?
Thanks, --DD
PS: We compile with SEC (Structured Exception Handling) on Windows, to be able to "catch" crashes using catch (...), therefore avoiding this issue most of the time, but sometime that's not enough, since of course some crashes are not recoverable (if they corrupted the stack for example).
Depending on who's throwing the dialog, you may have to combine multiple approaches.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
...will shut up one set of dialogs.
You need to add an 'unhandled exception handler' that catches all exceptions: put a call to SetUnhandledExceptionFilter(handler) in your initialisation code and it'll call the handler routine. Really simple.
I use sample code from an old article, include a file called minidumper, call the exposed function, and you're done.
Here's some more example code, this pops a different dialog, but you can change that to simply write a message to a log file or similar.
If you're writing a pure .NET app, then you'll be more interested in this article.
Do not use the "catch(...)" statement because then you can miss the point of having unit tests.
What you need is a non-modal dialog, since the modal dialogs are for blocking the user from any further actions and the program execution (in your case the unit test runs) hangs up until the user makes his/her choice. Now the crash dialogs can't be avoided, but you need to see how your unit test framework handles these situations. I would say you missed something around the unit testing framework because if I have a crash in my applications I got just a log message about that from the Boost.Test stubs.
If you run your unit tests as a child process it shouldn't block your build bot, BUT: if a unit test case fails, you shouldn't continue the building process in my opinion.
You can use WSH to "script" your windows.
With it you can "simulate" that somebody clicked on the "Accept" button of the modal window, or send the ESC key to close that.
Regards.