I have a game app that has the ability to go fullscreen and back to windowed when Alt-Enter is pressed. However, when it goes fullscreen, I get the following warning from DirectX:
DXGI Warning: IDXGISwapChain::Present: Fullscreen presentation inefficiencies incurred due to application not using IDXGISwapChain::ResizeBuffers appropriately, specifying a DXGI_MODE_DESC not available in IDXGIOutput::GetDisplayModeList, or not using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH.
I've already ruled out the second two possibilities through testing, so I know the only reasons left for the warning to pop up are either IDXGISwapChain::ResizeBuffers isn't being used right, or Windows is just bugged. Since I can't debug the 2nd possibility, I'm sticking with the ResizeBuffers problem. To debug this, I want to look at what happens when Alt-Enter is pressed going from windowed to fullscreen. However, the app does not seem to be calling my ResizeDXGIBuffers method; in fact, it seems that Alt-Enter is embedded into windows or DirectX somewhere, and I don't know how to find the chain of function calls that go off when it is pressed. EDIT: When my method is put in the WM_ACTIVATEAPP handler, it is called, but this is not what i meant. If i take it out of that message handler, the window STILL goes to fullscreen, even though I am not calling any functions to make the window fullscreen myself. So Alt+Enter must be automatically calling some internal function to do this.
So that is my question: Does anyone know what function is called by windows and/or DirectX 11 when Alt-Enter is pressed?
EDIT: As the tags for this question say, I am using DirectX 11 on a Windows machine. Specifically, Windows 7 64-bit.
EDIT 2: I now completely eat the Alt+Enter keystroke and manually store the state of Alt+Enter being pressed so that I know for certain only my code is being called. The warning I spoke of above persists, however. I am following the MSDN best practices as well, so I don't know where to go from here.
Try handling the WM_ACTIVATEAPP message.
I do not know which framework you use to create your windows, so I can't tell how to concretely handle this message.
After looking at the MSDN best practices page and re-working my code to reflect all of the practices described, the warning has disappeared. I hope this helps anyone else that has the same problem.
Also, thanks to Hans Passant for the link. I already fixed it by the time you posted it, but thanks anyways.
Related
I'm trying to use SendMessage to post mouse clicks to a background window (Chrome), which works fine, but brings the window to front after every click. Is there any way to avoid that?
Before anyone says this is a duplicate question, please make sure that the other topic actually mentions not activating the target window, because I couldn't find any.
Update: aha, hiding the window does the trick, almost. It receives simulated mouse/keyboard events as intended, and doesn't show up on screen. However, I can just barely use my own mouse to navigate around the computer, and keyboard input is completely disrupted.
So my question is, how does sending messages to a window affect other applications? Since I'm not actually simulating mouse/keyboard events, shouldn't the other windows be completely oblivious to this?
Is it possibly related to the window calling SetCapture when it receives WM_LBUTTONDOWN? And how would I avoid that, other than hooking the API call (which would be very, very ugly for such a small task)?
The default handling provided by the system (via DefWindowProc) causes windows to come to the front (when clicked on) as a response to the WM_MOUSEACTIVATE message, not WM_LBUTTONDOWN.
The fact that Chrome comes to the front in response to WM_LBUTTONDOWN suggests that it's something Chrome is specifically doing, rather than default system behaviour that you might be able to prevent in some way.
The source code to Chrome is available; I suggest you have a look at it and see if it is indeed something Chrome is doing itself. If so, the only practical way you would be able to prevent it (short of compiling your own version of Chrome) is to inject code into Chrome's process and sub-class its main window procedure.
The MSDN page on DXGI gives instructions on how to handle fullscreen resolutions different from the desktop resolution. It says to call IDXGISwapChain::ResizeTargets() before calling IDXGISwapChain::SetFullscreenState() to prevent flickering, among other things.
It does not say how to handle Alt-Enter, which calls IDXGISwapChain::SetFullscreenState() before the program is given a chance to make its own call to IDXGISwapChain::ResizeTargets(). If the latter method is called upon a WM_SIZE message, another WM_SIZE message will be sent, possibly causing an infinite loop. How can I ensure that the latter will be called before the former when alt-enter or alt-tab are pressed, and that mode switching occurs painlessly in general?
This is going to be really tricky ... the right way how this is supposed to be handled is IDXGIFactory::MakeWindowAssociation, which, as far as I know, nobody has managed to use successfully. You may want to try it anyway.
The "right" answer is to manually handle Alt+Enter. So, disable Alt+Enter using MakeWindowAssociation and get your hands dirty. First, there is no need to capture WM_SIZE. Instead, listen on WM_ENTERSIZEMOVE, WM_CAPTURECHANGED, WM_WINDOWPOSCHANGED and WM_EXITSIZEMOVE. This will prevent you from having to deal with WM_SIZE and still get all relevant window resizing events. (When doing this, read this question as well: WM_ENTERSIZEMOVE / WM_EXITSIZEMOVE - when using menu, not always paired)
Ok, so assuming everything went fine, for Alt+Enter, you have to do the following: You set your swap chain to full screen using IDXGISwapChain::SetFullscreenState and then resize your swap chain (IDXGISwapChain::ResizeBuffers). By default, you'll get a swap chain which is as close as possible to the current resolution of your window before resizing. The way you do this properly is to enumerate the full screen resolutions first, and upon going fullscreen, forcing the resolution you want to have. This sounds ugly, but it seems to be the most robust way to solve the problem.
In general, real, exclusive fullscreen mode is not worth the trouble, as you will always get flickering when someone goes Alt+Tab (you can't avoid it if a mode switch happens, as the screen itself will have to readjust.) A much better solution is to use a fullscreen borderless window. You simply create a window class without any decoration, make it full-screen, place it such that it covers the whole screen and be done with it. Then you don't have to worry about Alt+Enter and Alt+Tab at all. It also allows people to continue working on a second screen without flickering. Performance wise, this is pretty ok'ish (most new games support this as "borderless fullscreen".)
There might be a silver bullet which solves all of this correctly, but I haven't seen it yet. If there is a cleaner/nicer solution, I'd be really curious to hear it. "Borderless fullscreen" seems to be the current standard though, IIRC, Unity 5 will only allow "borderless fullscreen" for Direct3D 11.
I just want to add an update on this issue - I've written a small windowing library that I believe handles DXGI pretty well - no debug messages, no error messages, and everything behaves as intended, at least on my Windows environment. The full solution to this problem is much too complex to explain in a single answer, since it requires a lot of precisely placed method calls (DXGI is really, really rigid as it turns out), but I have my code up on github if anyone wants to take a look at it. Specifically, this file and this file are the ones you want to look at - the latter being an aggregate object of the former.
Note that I have disabled ALT+ENTER in favor of F11, but the functionality is exactly the same.
If you want to use that library, by the way, I am releasing it as free software and will provide documentation soon.
I wanna ask if someone can provide me a c++ code in which I can hide/show the pointer of the mouse when pressing a specific key..
I found several codes written for only TURBO C++, none of which can be compiled and run using dev c++ or even visual c++..
I tried running the codes I found in Dev C++ but I only get lots of errors and incompatibilities..
I also found several articles that says I can use the function ShowCursor but it just wouldn't work..
In fact hiding the cursor can turn out to be quite a task, depending on what you want to achive. If you're programming a GUI-application using the WinAPI it is pretty easy.
Just calling ShowCursor(false); once might turn out not to work in some cases though, since the ShowCursor function only "sets an internal display counter". The cursor is displayed until this counter is smaller than 0 (see msdn on it). You could try something like this:
while(ShowCursor(false)>=0);
to ensure the counter gets below 0.
This will however only hide the cursor inside your applications window, if you're using newer Windows versions like Windows 7. Hiding the cursor all over the system could turn out to be a lot more difficult.
If you are programming a console application ShowCursor won't show any effect as far as I've tested it. Using the following code:
while(ShowCursor(false)>=0);
std::cout<<ShowCursor(false)<<std::endl;
std::cout<<ShowCursor(true)<<std::endl;
we can see, that the counter definitely is below 0, but still the cursor is displayed. I haven't come up with a solution to this so far.
If you look at the documentation for the SetCursor function, setting the cursor to a NULL handle (e.g SetCursor(NULL)) will remove the cursor from the screen.
I know this type of thing is looked negatively upon but I write software for people with disabilities and sometimes good gui practices don't make sense. In this case, the user interacts with a assistive interface and under certain conditions, my control app needs to prompt the user with a question. My background process creates a dialog (I'm using wxwidgets wxDialog class) and calls Show(). The dialog box appears but it does not have focus (the application that the user was previously using keeps it). Since my users can't use mice, they can't simply click on the window. I've tried calling show and then followed by SetFocus(HWND) but that doesn't do it. What's the problem? Is this even possible? Window7. I'm thinking that it might have something to do with it being a dialog and not a full window (wxFrame). Any help is greatly appreciated.
Try using SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE)
Unfortunately, not only is it 'looked negatively upon', but it is not possible. There's no getting around this; ask yourself what would happen if every application could do this? Obviously, if you can put your dialog on top of the other application, it can do exactly the same back to you.
http://blogs.msdn.com/b/oldnewthing/archive/2010/11/25/10096329.aspx
The only think I can think of would be for you to put a notification icon in the system tray, and then have it display a notification balloon.
I had to do something like this before. Simply calling functions like SetForegroundWindow or SetWindowPos didn't do the trick.
I ended up using this ForceForegroundWindow function (1st one) and it works pretty well.
I know this is Delphi code, but the API is the same and Delphi is a pretty simple language.
I am trying to create a simple dialog in MFC using Visual C++. My problem is that when I get the dialog on the screen and try to type in an Edit Box field, if I type the letter 'a' once, it appears in the edit box as 'aaaaaaaaaaa' (that's 12 a's). Furthermore, if I try to navigate around in the box using the arrow keys, the carat moves 12 characters at a time.
It's not just a display error, as the output from the editbox is still "aaaaaaaaaaaa".
I'd post code, but there's really none to post. I added the edit box using the Toolbox in Visual Studio and assigned a variable to it in my class so this isn't any sort of special edit box.
If anyone has any thoughts as to what might be happening it would be greatly appreciated. Unfortunately, I don't know where to begin.
Thank as always.
To debug this, add PreTranslateMessage function to your dialog, and see exactly how many times the keydown is being processed.
BOOL DialogName::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_KEYDOWN)
{
// TODO: see what is going on here
return TRUE; //do not dispatch this message, so keydown will have no effect
}
return CDialog::PreTranslateMessage(pMsg);
}
Are you capturing any events such as WM_KEYUP in your PreTranslateMessage() function or anywhere else in your app ?
If you have overridden the default handling for keyboard events, it might cause the symptoms you are seeing.
For some reason this brings back vague memories of early struggles with MFC. Have you looked for mutual recursion at all? I was forever doing something in one bit of the app that sent a message (unbeknown to me) that was picked up by another method that called the first method...
My guess is it's one of those smack the forehead ones; it gives me this nagging sense of deja vu that I can't make concrete.
If it's mutual recursion you should be able to see it in the call stack, if you can find the right place for a break point.
Is this happening for a fresh project, or can you recreate this problem in a fresh project?
It'll help discern whether it's something you've done in your code, or your install.
I installed service pack 2 in my WinXp 64 OS and the problem get solved for me :)