Trouble with VB6 app, bringing a dialog to front and focus on Windows 7 - windows-7

I have a small utility app written in Visual Basic 6 that has been happily running on XP clients for many years until recently a client who is using Windows 7 has notified and shown me that the behaviour is different.
When my VB app displays the dialog, it remains hidden until the user clicks on it in the taskbar.
I changed the code so rather than using a ".show vbModal" command, I changed to displaying the form with non-modally, and then added various API calls like BringWindowToFront and SetWindowPos to make it top most AND calling .focus on the form, despite these extra instructions the best result I can achieve is to make the form flash prompting the user to click on it.
No matter what I've tried I cannot make the window display topmost, and with focus, without user intervention.
Note. this is an ActiveX exe project and is being called by a Win16 app through COM.
Has anyone else encountered this behaviour and know of a solution?
Any suggestions/advice appreciated, thanks.

Applications can't (without lying to Windows) steal focus. The calling app should really call AllowSetForegroundWindow() (if it's available on win16) to allow the COM process to steal the focus, or call SetForegroundWindow() itself.
See the help for SetForegroundWindow() for the conditions on setting focus.

Related

Intercepting a window's attempt to steal global focus on Windows

I'm a developer and a long-time Windows user with an obsession about making my system as convenient to use as possible.
Yesterday I thought about something that has always annoyed me in Windows and that I've taken for granted, and I realized that I have a better idea for how it could work, and I'm now wondering whether it's possible to tweak Windows to work like that.
The thing that annoys me is when windows steal focus. For example, I could be running an installer for some program. While it's working, I'll switch to my browser and browse, maybe entering some text into an email in my browser. Then suddenly the installer finishes and its window steals the focus. Now I'm in the middle of writing an email, so I might press a key that happens to be bound to a button on that installer, and then that button gets invoked, doing some action that I never intended to happen!
This is doubly annoying to me because I'm using a multiple-desktop program called DexPot, and when a window steals focus, it also brings itself to the desktop I'm currently on, which can be really annoying, because then I have to put it back into its original desktop.
How my ideal solution to this problem would work: Every time a window tries to steal focus, we intercept that, and don't let it. We show something like a toaster message saying "Foobar installer wants focus, press Win-Whatever to switch to it". If and when you press the key combo, it switches to the window.
The question is: Is there an easy way to tweak Windows to make this happen? I know very little about Windows programming. I do know AHK and if it's possible with that, that'd be great.
No, there isn't an easy way to add this behavior, but Windows tries to do this automatically.
In theory apps shouldn't be able to steal the foreground while you're actively using another app. Unfortunatly there are some scenarios where Windows can't tell the difference between legitimate user actions that should change the foreground and unwanted foreground-theft. The window manager generally tightens up the holes a bit with each new version of Windows, but also needs to make sure that apps can come to the foreground when the user wants them to, even if that desire is expressed indirectly.
For example, a process launched by the current foreground process can put a window into the foreground. This is necessary so that when a user launches a window from Explorer the newly launched process can open its main window. This permission only lasts until the next user input, so if an application is slow to launch and you start working on an email the app may lose its foreground permissions before it can use them.
See the SetForegroundWindow function documentation for a list of requirements for a process to be able to set a window into the foreground.
There are also apps which specifically make use of these requirements to steal the permission (by joining the foreground queue or synthsising user input to themselves), but I suspect in your installer scenario it is accidental.
I'm not sure what exactly is going on, but I suspect that the problem comes from the installer running as a service and accidentally stealing the foreground permission when it tries to launch the app on your current desktop.
It would be theoretically possible for an external process to hook into the foreground system to override this and show your confirmation toast, but it would be tricky to get right and would require significant low level code (I'd probably start with a CbtHook). It would not be possible in a scripting package like AHK (assuming you mean AutoHotKey) but would need to be native C/C++ code injected into every running process.

Prevent a process from showing any dialogs at all?

On Microsoft Windows (8), I would like to start a process, and prevent it from showing any windows at all. Alternatively, to force-close any windows that are shown. Is there a way to do this?
My application is this: I'm running an automated (nunit) test suite on my continuous integration (teamcity) server. The code under test is also used by an interactive application. Developers occasionally slip in a dialog with a user prompt, without realising what they are doing. This causes the CI process to stop, waiting for user input which never comes. I'd like to be able to dismiss any dialog that appears, or prevent them from being shown.
Even better would be to force an exception at this point, so that the test would also fail.
In my case, this is a C# application, and the dialogs shown are Windows Forms or WPF dialogs.
I did find a couple of similar questions. However each turned out to be solving a slightly different problem.
Stop a process from showing a window from C# (solves a different problem)
Preventing blocking dialogs/message boxes/hanging GUI from non-interactive processes on Windows? (promising solution but C++-specific)
Prevent child process from creating visible windows? (solves a different problem)
Have you considered asking your development team to have a "no dialog" mode of the app for testing purposes? Perhaps if you stopped referring to them as (!!*&%) they would be more inclined to partner with you. ;) Afterall, you do work at the same company on the same product :)
In any case, without a dev-specific solution, consider having a another app (process or thread) that continually sleeps for a few seconds, wakes up and looks for a modal dialog in your application. You can use APIs such as FindWindow to identify when a modal dialog has popped up. (Use Spy++ to get the class name for windows created by MessageBox and CreateDialog APIs).

How to write a program that runs another GUI program inside it

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.

Is it possible to call a function in a different, but currently executing process?

I have a friend who's working at a company that offers pretty poor support for its developers (scoring a 1/12 on the Joel Test).
Their build process is locked down pretty tight, and depending on the size of project it could take 40+(x2) mouse clicks to deploy. So I thought, "Hey, why not automate it the clicks using the win32api?" (Specifically using Python). I've got him a real nice tool that works just fine except for one issue - the tool that they use has a navigation pane that may or may not be open.
You can open and close it with a button press, but I'm not sure how I could make sure it was either open or closed. It's irrelevant to the build process - the only problem is that it alters where the mouse needs to click on the screen depending on its open status. The application is written in .NET and it exposes a function call that applications are able to use to toggle the panel, so I've been looking around for ideas and so far I've got two of them:
Attach to the process via a debugger and execute the function call somehow.
Take a screenshot at the location of the panels titlebar (which I've got through the win32 API and doesn't appear to change regardless if the panel is hidden or not).
Is there an easier way to figure out the state of this panel? The developers are given an admin account on their machine in addition to their regular account, so I can entertain ideas that require admin access, though I don't think that should be necessary?
UPDATE:
It looks like there's a button that can close the pane. In UIAVerify something shows up as "text" "Navigation" "btnClose". It says its AutomationId is btnClose but it's a ControlType.Text
What technology is this panel built from? Is it standard GDI or WPF? If its GDI, it should have a HWND. You should be able to find this HWND through either a class name or window title. Once you have the HWND, you can get its width.
If its built with WPF, er, I have no idea, but Snoop does this kind of thing, so I know its possible.

Ghosts windows when color scheme is NOT Aero on Vista

We have a service that launches an application that will interact with the logged on user. The application we launch is always run as a specific user for which we have the credentials. We do what is necessary (get active session ID, logonUser, adjust token) and launch the application with CreateProcessAsUser in the winsta0\Default desktop.
Everything is working fine if the color scheme of the Vista PC is Aero - but under the basic and classic color schemes, the application is still launched but none of the windows are painted. There is a new task on the taskbar. If you minimize a window which was in the background and in full screen, then you can see the contour of our ghost app - you can move it around, it will respond to keyboard/mouse input just fine. It's just invisible, not painted.
Does anyone has any idea of what could be happening? Why with the Aero color scheme it's fine but not in the others?
Thanks for any help,
Frank
It sounds pretty weird - you may have hit on an actual bug in Vista since it seems unlikely many other people have tried what you are doing.
First of all I'd make sure the problem doesn't exhibit this behaviour when run by the logged in user directly, just to pin it down to whether it's a Aero/Classic issue or a winstation issue.
Secondly I'd attach to the process with a debugger and make sure the message loop is getting various significant messages, particularly WM_PAINT :)
But this is obscure enough that your only option may be to open a paid support issue with Microsoft.
There may also be a problem if you have user-drawn controls on your form (or your form itself is user-drawn). If you only paint the form if Application.RenderWithVisualStyles is true, you may see this behaviour. So make sure you also render stuff without these styles. More information how your form looks/behaves/etc would be appreciated.

Resources