I’ve encountered a problem I can’t solve.
I’m working on a project with MFC in Visual Studio. The problem is, sometimes GUI just stop visibly reacting, but technically it keeps doing the functions it was intended to do. It means, when I press a button, the function OnBnXXXPressed is executing, but the button doesn’t look like it was pressed, as if I’ve pressed on a picture of button, not the button itself. And it’s not just this button — every other element of GUI seems to keep working, but doesn’t show that it is working.
Also, in this state dialog windows don’t show up upon their call. If I call AfxMessageBox, the message box won’t show up, and the thread that called this function, will not be blocked; AfxMessageBox will basically be skipped.
I have absolutely no idea what can possibly cause that behavior. The question is: what should be happening in program for it to behave this way? Especially if it’s built with MFC?
The project consists of 50+ files, and every function responsible for GUI makes changes to the elements it is about. I do not know where the error is, and I ask you, to the very least, where should I look for it.
Thank you for attention!
The answer was originally provided in the comment section. My code indeed has a GDI resource leak that was provoking this behavior.
When a button is clicked, are you doing a bunch of processing, or do you return fast? If you don't return, maybe locking the UI thread. After a user presses on the button, how long is it taking before the OnClick for that finishes running?
If that's it, here's some more info: https://learn.microsoft.com/en-us/windows/desktop/Win7AppQual/preventing-hangs-in-windows-applications
The solution I've generally used for long-running logic on a UI click is to run it a background thread.
Related
A little background
Our application (AppA) is calling a 3rd party application (AppB). We are simulating AppB's window as being modal to our application.
pseudo
while AppB_Running
If AppA_focused
SetForeGroundWindow(AppB_Hwnd)
HandleMessage
SetForegroundWindow(AppA_HWnd)
This has been working for years without incidents, that is, until we started rolling out Windows 10. We started receiving reports that a random app (AppC) was sometime getting the focus when we closed AppB (Actually, given our user's tech expertise, the report were more along the line "Closing AppB kills AppA" but I digress). That behavior can be reproduced occasionnaly(<5%) on dev machine (But not yet while debugging...)
So far, test result suggest AppC is the application that had the focus before AppA.
Is there a way I can ensure AppA gets the focus back when AppB closes?
Extra notes
The problem can be reproduced even if AppA only ever loses focus to AppB. (AppC never being focused after AppA started)
While this does not directly answer my original question, it does give some more insight on the problem and might be useful to someone else.
Part of the issue was an oversight on our end. More specifically, the way we obtained AppB_HWnd. We basically picked the first top level window we encountered. In our current test case, that window happens to be an invisible windows ('MSCTFIME UI'). Calling SetForegroundWindow on an invisible window doesn't seem to cause problems per se, Windows seems to just bring to front one of the process' visible window. It is when said process does not have any visible windows left that things seems to go awry. That usually happen in our case between the moment AppB's main window is closed and the moment the process ends.
So... Don't call SetForegroundWindow on an invisible window
As for why we didn't have any trouble in Win7? Maybe the first window was always a visible one. Or maybe SetForegroundWindow behaved differently back then.
I am not sure how to ask the question so here is a picture of some idea that came to mind
So for example, when you run my "custom launcher" it displays a window with a couple buttons on the side which you can assign values to. When you click on a button, the appropriate program will run in the big panel on the right (in window mode).
This is all from the user's perspective of course. They will just see that the program they want to run appears in that panel. The actual implementation may have nothing to do with "one program running inside another program"
My own use case is limited to windows desktop platforms only, but if it is possible to generalize it that would be nice as well.
Is this actually possible? Can I write such a program that will run another program inside a panel? The program that's launched may be someone else's, such as MS paint or calculator.
Just to expand on my comment above, here is an approach that may work for you: Fake it :)
When you launch the program, intercept all windows messages to the program that control it's position on screen. That way it 'appears' to be fixed in place, but in reality it's still attached to the normal Windows desktop.
Here's some light reading for you:
Windows Event Hooks
A hook is a mechanism by which an application can intercept events,
such as messages, mouse actions, and keystrokes. A function that
intercepts a particular type of event is known as a hook procedure. A
hook procedure can act on each event it receives, and then modify or
discard the event.
I would recommend against it in a commercial application because you are modifying the behavior of software you don't own - that software may make assumptions about what its parent window is, but for experimentation there's the SetParent Win32 function.
I'm a new Mac programmer writing my first mac app, actually porting an existing iOS app to MAC.
The app does a lot of remote communication, so when the user kicks off an operation, I want to display a busy window (or message box, or NSAlert maybe), until the operation is completed, then dismiss it programmatically, or the user can click cancel to stop it.
The busy window prevents the user from doing anything until that operation is completed.
The busy window should have a progress spinner, some text, and a cancel button.
Its such a simple thing yet I'm having problems with it because I dont really know MAC programming, getting myself frustrated.
Can anybody offer suggestions, or already written code for it. I hope some code for this already exists because I cant believe I'm the only person in the world who needs things kind of busy window.
Thanks for any help.
You mean something like this:
http://www.developers-life.com/example-nspanel-with-nsprogressindicator.html
???
Source code is available, too (link at the end of the article).
You can just modify the NSPanel in Xcode and add a "Cancel" button that you connect to your cancel action.
I'm writing an extension that opens a tab when Chrome first runs, technically means placing code in the background page, which sounds simple enough, and works fine in Windows, and probably Linux as well, though I haven't tested it.
The problem is with Mac, which doesn't actually fully close Chrome when the user clicks the close button at the top left. To fully close Chrome you have to force quit it, which is something people generally do not do.
So this means I'll need to rely on some other event to trigger code when the user first "opens" chrome. Does anyone have idea for which even that could be? I suppose I could add a listener to every tab's create event and check the number of tabs, or something similar, but I'm looking for a light weight solution. Any ideas?
UPDATE: One idea us to use the chrome.windows.onCreated event and just check that there are no other windows open. Is that the best method, or can anyone think of something more efficient?
Use two events and a counter. Because window open/close are relatively rare, this should not be a problem:
onCreated, increase the counter, and validate the value.
onRemoved, decrease the counter.
I'm writing a Win32 plug-in DLL for a third-party MFC app. The DLL needs to display a modal dialog. When I do this using DialogBox() or other plain Win32 API (e.g. I tried to write my own modal loop), the main application's window doesn't redraw all elements: it redraws standard elements, but not the client area. Modeless dialogs display just fine.
I suspect this happens because MFC doesn't really have modal dialogs in Win32 sense. It can only have one message loop and a separate loop in DialogBox() disrupts its delicate machinery. Here's a CodeProject article that explains this. But this CodeProject article is 9 years old, so maybe things have changed since then. Could somebody shed some light on this? The app uses MFC 8 (i.e. mfc80.dll).
Update. Here's a link to the original question; it may contain some additional information.
Update 2. Thanks everyone; I really appreciate all the advice, it certainly helps me to get the big picture of how things fit together. The first path I'm going to explore is to use native MFC 'modal' dialogs. (Since I do all this from Python, I'll use Python bindings for MFC, pywin32). This will take some time; when it's ready, I'll update the post with results.
Every thread can have a message loop. Put your modal dialog into a separate thread and emulate the standard behavior of Windows by disabling the parent window.
Edit: after some discussion (see below) it appears that the parent code behaves incorrectly.
Still, I think there are possible workarounds. One could be a parent window (to the modal dialog, but child to the one that currently behaves incorrectly) that overlays the erroneous window content, but redraws it from a DC in memory to mimic correct behavior. Of course the parent window still would have to be disabled. Another solution may be to subclass the parent window, to correct the behavior. Since the plugin would run within the same process, the implementation should be straightforward.