I wrote a small autohotkey script that removes the border, titlebar, and resize handles of a window, and centers it on the first monitor. This works for most applications and games, but some (bioshock 2, APB, etc) replace their window style instantly after removing it. Is there a way to block window style changes?
I would prefer to keep this in AHK, but the title has c# in it because I would like to convert my application to that down the road, and if it's only possible in c#/c++ then now would be a good time to start conversion.
I could be missing something, but I doubt this is going to be easy. The behavior you describe is one of an application which is either monitoring for changes in its window style, or just constantly redrawing them nonstop to prevent these changes. Of course you could just Loop through and fight against it where you remove, it replaces, you remove, it replaces, but that won't solve anything.
One way you could try is to create a .dll and inject it into the app's process, and then hook some API calls and simply return before anything gets redrawn. Google for 'detours hooking' for some examples. That might work, but would be out of the scope of AHK. And your simple 15 minute AHK script would turn into a much bigger project. =(
Related
I am writing an Alt+Tab replacement in C#, and have trouble with fullscreen applications.
Is there a way to detect if a SetForegroundWindow(hWnd) call is going to change the screen resolution? Or equivalently, if hWnd is a fullscreen application? I would like to wait until the resolution change is done, or if there is no change, proceed immediately.
The screen resolution change is done asynchronously, the function call returns well before it happens, so my code runs prematurely, and draws my application onto the surface of the fullscreen application, with wrong dimensions, then after the resolution change, it looks especially ugly.
Source of my application is at https://bitbucket.org/FrigoCoder/frigotab/src if anyone is interested.
To clarify, I would be more interested in knowing beforehand if a resolution change occurs than detecting it later. I already know a half-solution where I call SetForegroundWindow() on GetDesktopWindow() or some other window and watch SystemEvents.DisplaySettingsChanging and DisplaySettingsChanged. This however only gives me a late asynchronous notification if a resolution change occurs, and does not tell me if it does not.
I managed to solve the issue. Instead of trying to detect fullscreen applications, I simply send an inactivation message to the foreground application, which triggers an early resolution change:
SendMessage(GetForegroundWindow(), WM_ACTIVATEAPP, false, GetCurrentThreadId());
This exact same message is also sent during application switches, so I essentially emulate one before it actually happens. I have not encountered any side effects yet.
Mind you however, that this does not solve DWM issues. Windows 7 automatically disables DWM composition for compatibility launches, or when it detects direct access to the primary display surface. It does not allow you to re-enable, and I do not see an easy solution to this problem. Thankfully this issue will eventually go away since DWM composition is always enabled in Windows 8 and newer.
Perhaps the Winforms Event SizeChanged can help you.
You could use this event as a continuation of sorts for the rest of your code. In the case that the event doesn't fire due to no resizing, you could have a secondary continuation that will run after a specified timeout. It's not perfect, but may meet your needs.
I have a complex WPF application that is using a lot of resources from the shared Resource Dictionary.
The first Window initialized takes 8 seconds to initialize. The performance issue is less on SSD disk drives but still it requires 2 seconds.
I tried to use the Visual Studio Profiler and it shows big expense of time on InitializeComponent();
of the windows that needs to be displayed.
I believe it is related to the Resource dictionary used but I can't replace it because I really need it and because all windows and WPF elements are using the StaticResource references.
I tried to optimize the launch as much as it is possible.
I created many background threads but this didn't helped too much. Whenever a window needs to be displayed it must be attached on UI thread under the same Dispatcher. This makes a big performance issue and all UI and any Progress bar left on the screen is blocked.
So to summarize. From the point when the ShowDialog is called until the window is displayed it
takes 8 seconds. This is visible only on the first window. Any other window opened after that is displayed quickly.
Now I am asking firstly what happens in the background and why this delay is so big and second what can be done to increase the startup speed.
I didn't mentioned but there are no Exceptions or DataErrors present during the launch so it is
not related to Exceptions.
I believe it is something with the initialization of Buttons and other components because almost all of them have the ControlTemplate restyled.
Lots of assemblies need to be loaded and lots of code must be JIT compiled before your first window can be shown. One useful technique to reduce startup time is to structure your code in such a way that types are not loaded before they are needed. It may be preferable to get a blank window up on screen with a wait indicator before delving into code outside of the core WPF assemblies. Optimize for that scenario.
Avoid loading images/media and other resources too early if you are trying to get something up on the screen as soon as possible.
Avoid loading any data synchronously, and do as little in your view and view model constructors as possible. Defer the loading of data until your view has been shown (throw up a wait indicator if necessary).
If you think your Xaml resources are a problem, split them up, and have each view pull in only the resources it needs. Don't merge them into App.xaml. You might also look into how to share the resources more efficiently across multiple views.
Throwing up a splash screen can improve the perceived startup time. Getting anything up on the screen to let the user know your app is actually doing something goes a long way.
Lastly, don't fret too much; poor startup time is the hallmark of WPF applications, and in the end, there's only so much you can do.
You can also use the ProfileOptimization class to improve startup time over subsequent sessions of the program. May not help you, the developer, but may have an impact on your users for the better.
Often when debugging an piece of asynchronous code, it will give me this blue screen on my second monitor with a clock on it. This happens often after I pressed 'Continue' from a breakpoint but sometimes it also turns into a black screen.
Using the Windows button or dragging a window over it removes it but it is still rather annoying. Can I turn this off somewhere?
I don't think you can turn this off. I would assume a unit test project actually starts an app to be able to run the tests. Similar thing was the case with Silverlight unit tests - an app needs to be hosted somewhere to be able to run the code.
Perhaps you could use something like Stardock's ModernMix to make it possible to switch that app to run inside of a window to make it a bit less annoying to you.
Whenever my windows forms application runs for the first time, the tray icon stays visible for about less than a minute, and then it autohides, what can i do to make it stick and not auto hide ?
I tried searching and can't find any useful information.
It appears that this is the default behavior for windows 7 and above, I wonder if there is a way to override that behavior from inside my application ?
There is no supported programmatic way to override the system's default show/hide notification icon behavior. MSDN:
When an icon is added to the notification area on Windows 7, it is added to the overflow section of the notification area by default. This area contains notification area icons that are active, but not visible in the notification area. Only the user can promote an icon from the overflow to the notification area, although in certain circumstances the system can temporarily promote an icon into the notification area as a short preview (under one minute).
Emphasis mine.
As you've no doubt read the discussion in the comments, there is indeed no supported way of doing this. That said, if you're determined and you have the time to do a little digging, I'd recommend using a few tools to bypass the documentation and looking at what's actually happening under the hood with the notification setting. There may be appropriate documentation on this but I've not found it.
The brute force approach would be to use SysInternal's RegMon tool to view all registry access . If you tie it to the "Explorer.exe" process, you will see all relevant information on what the desktop and start bar are doing, including any file access. Make no mistake - this is a brute force approach and will require a lot of effort and digging. Once tied to the explorer.exe process you can make changes to the notificaiton settings. Viewing and investigating the changes made by the process will give you an idea of where the relevant settings are stored and how. The downside is that there's going to be a lot of data to trawl through and investigate to find out what's going on but it can be done. This is not an ideal solution but if no other is forthcoming you're left with the rough and ready approach I'm afraid. It comes down to how much effort you want to put into a solution to this.
I have a windows form application which needs to be the TopMost. I've set my form to be the TopMost and my application works as I'd like it to except for in one case.
There is a 3rd party application (referred to as player.exe) that displays SWF movie files on a portion of the screen that popup on top of my application.
Using Process Monitor I determined that player.exe application calls
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
in my case:
flash.exe 901 96 379 261 somemovie.swf
Since flash.exe is being spawned in a new process after my form has been set to the TopMost it is appearing on top of my application.
First thing I did was make my application minimize the player.exe main application window hoping that this would prevent the Flash from appearing also. But, unfortunately it doesn't... even with the window minimized whenever the flash movie starts it shows up at the pixel location (901,96). I then tried creating a timer to keep setting the form.TopMost property to true every 10ms. This sort of works but you still see a very quick blip of the swf file.
Is there some type of Windows API call which can be used to temporarily prevent player.exe from spawning child processes which are visible? I admit it sounds a little far fetched. But, curious if anyone else has had a similar problem.
Addendum:
This addendum is to provide a reply to some of the suggestions layed out in Mathew's post below.
For the emergency situation described in the comments, I would look at possible solutions along these lines:
1) How does the third party application normally get started and
stopped? Am I permitted to close it
the same way? If it is a service, the
Service Control Manager can stop it.
If it is a regular application,
sending an escape keystroke (with
SendInput() perhaps) or WM_CLOSE
message to its main window may work.
Easiest way to close the app is to CTRL-ALT-DEL, then kill process. -OR-
The proper way is to Hold ESC while clicking the left mouse button... then input your username and password, navigate some menu's to stop the player.
There is no PAUSE command... believe it or not.
I don't think using WM_CLOSE will help since minimizing the application doesn't. Would that kill the process also? If not, how do you reopen it.
2) If I can't close it nicely, am I permitted to kill it? If so,
TerminateProcess() should work.
I can't kill the process for two reasons. 1) Upon relaunch you need to supply username/password credentials... There may be a way to get around this since it doesn't prompt when the machine is rebooted but... 2) Whenever I kill the process in task manager it doesn't die gracefully and asks if you want to send an error report.
3) If I absolutely have to leave the other process running, I would try
to see if I can programmatically
invoke fast user switching to take me
to a different session (in which there
will be no competing topmost windows).
I don't know where in the API to start
with this one. (Peter Ruderman
suggests SwitchDesktop() for this
purpose in his answer.)
I got really excited by this idea... I found this article on CodeProject which provides a lot of the API Wrapper methods. I stopped implementing it because I think that in order for desktop's to work you must have explorer.exe running (which I do not).
EDIT2: On second thought... maybe explorer.exe isn't needed. I'll give it a try and report back.
Edit3: Was unable to get the code in that article working. Will have to put this on hold for a moment.
Answer Summary
As one might have expected, there is no simple answer to this problem. The best solution would be to problematically switch to a different desktop when you need to guarantee nothing will appear over it. I was unable to find a simple C# implementation of desktop switching that worked and I had a looming doubt that I would just be opening a whole new set of worms once it was implemented. Therefore, I decided not to implement the desktop switching. I did find a C++ Implementation that works well. Please post working C# virtual desktop implementations for others.
Setting the TopMost property (or adding the WS_EX_TOPMOST style to a window) does not make it unique in the system. Any number of topmost windows may be created by any number of applications; the only guarantee is that all topmost windows will be drawn 'above' all non-topmost windows. If there are two or more topmost windows, the Z-order still applies. From your description, I suspect that flash.exe is also creating a topmost window.
Aside from periodically forcing your window to the top of the Z-order, I think there is little you can do. Be warned, however, that this approach is dangerous: if two or more windows are simultaneously trying to force themselves to the top of the Z-order, the result will be a flickering mess that the user will likely have to use the task manager to escape.
I recommend that your program not attempt to meddle with other processes on the computer (unless that is its explicit purpose, e.g. a task manager clone). The computer belongs to the user, and he may not value your program more highly than all others.
Addendum:
For the emergency situation described in the comments, I would look at possible solutions along these lines:
How does the third party application normally get started and stopped? Am I permitted to close it the same way? If it is a service, the Service Control Manager can stop it. If it is a regular application, sending an escape keystroke (with SendInput() perhaps) or WM_CLOSE message to its main window may work.
If I can't close it nicely, am I permitted to kill it? If so, TerminateProcess() should work.
If I absolutely have to leave the other process running, I would try to see if I can programmatically invoke fast user switching to take me to a different session (in which there will be no competing topmost windows). I don't know where in the API to start with this one. (Peter Ruderman suggests SwitchDesktop() for this purpose in his answer.)
You can use the Process class to start flash.exe directly - and use an appropriate ProcessStartInfo settings to show the window in a hidden state - or with a WindowStyle of hidden or minimized.
You could also consider using the SetWindowsHookEx API to intercept the process start API calls, and when the process is flash.exe run some code to restore you window to top-most status.
Matthew's answer is excellent, but I suspect you may be asking the wrong question. Why does your application need to be topmost? If you're trying to create a kiosk or some such, then topmost is not the way to go.
Edit: After reading your response to Matthew's comment, I'd suggest creating a new desktop and switching to it before displaying your alert. (See CreateDesktop and SwitchDesktop in MSDN.)