I open an open file dialog using GetOpenFileName function. I'm making a handler function that will center the dialog window inside the owner window. I center the dialog on CDN_INITDONE notification.
Currently, it seems that Windows remembers last dialog position for desktop apps and overrides my dialog coordinates. How to reset that last remembered position so that I can check centering will work for my users?
I thought about running a test using a different user or virtual machine but this isn't very convenient. Unfortunately, searching in the registry for myexecutable.exe returns nothing.
I'm running Windows 8.
I'm about a year late, but I just had to deal with this issue. What worked for me was supplying an OFNHookProc to GetOpenFileName(), then subclassing the parent of the HWND passed to the OFNHookProc.
After subclassing, I handle WM_WINDOWPOSCHANGED, and if the coordinates aren't where I think they should be, I do a SetWindowPos(), undo the subclass and return 0.
Edit: I should say that other methods, such as WM_INITDIALOG in the hook proc or CDN_INITDONE did not work for me whatsoever.
Related
Imagine I save my window's position in my preferences file. Now, the user moves the window to a second monitor, then quits my app. Then he disconnects the second monitor and launches my app again.
Now my app wants to restore the window's saved location. But if it blindly restores the old window coordinates, the window will be off-screen.
I used to use ConstrainWindowToScreen for my Carbon app, but now that I'm porting it to Cocoa, I can not find an equivalent for this.
The docs suggest that, somehow, Cocoa would automatically prevent this from happening. While that might be the case when the monitors change while the window is open, in my case where I've stored the window location myself and restore them when I re-open the window at launch, this isn't going to work. I need to invoke Cocoa's magic functionality on demand, but how?
(Note: I am aware that I could iterate over all available screens, but that's quite a pain to write myself if I want to get this foolproof. Still, if you can present a complete C or ObjC function that solve it this way, that'd be appreciated, too.)
See the "Managing Window Frames in User Defaults" section in the NSWindow Class Reference. Those methods ensure that a window will be placed entirely on screen.
If you want to save and restore the window location yourself (as a string), use -stringWithSavedFrame and -setFrameFromString:.
Use -saveFrameUsingName: and -setFrameUsingName to have NSWindow save and restore its frame in the user defaults, given a window name.
I agree with Darren's suggestion to use the built-in mechanism for restoring window positions. Really, it's as easy as setting a window's frame autosave name in IB (or with -setFrameAutosaveName:).
That said, if a window has a title bar, then all of the methods which order it onto the screen (e.g. -orderFront: or -makeKeyAndOrderFront:) will automatically reposition it to make sure at least the title bar and a significant chunk of the window is on the screen. It's honestly difficult to get a titled window to be theoretically visible but actually off-screen.
So, I have a dialog based application using pure WinAPI. There is a main dialog, and then multiple other dialogs that are toolwindows. These toolwindows are meant to free-float around, the user can drag them, hide them, and show them, but they have no taskbar entry. This is what I intended, but the problem is, when I switch from the main window to a different application, then click on the taskbar entry for the main window, the main window will show up, but the toolwindows will not. They stay hidden behind the main window and sometimes windows of other applications, and you cannot use them until you move all of the top-most windows and hunt down the toolwindow.
So, what I'm trying to do to work around this is, when the user restores the window from being minimized, I want to enumerate through all of the tool windows and bring them to the front, maybe by calling SetActiveWindow().
But what message gets sent when the window is restored? I was thinking WM_SHOW, or WM_RESTORE, but they don't exist.
Another question, and if you answer this the first question is irrelevant because I will no longer need to use that workaround: Is there a better method of bringing all tool-windows to the front?
Give the tool windows the WS_POPUP style (and not WS_OVERLAPPED), and make the main window their parent (strictly it is their owner window). That way the tool windows will remain on top of the main window. This may (or may not) be what you want.
The naive answer to the question is to listen to WM_SIZE and respond to a wParam value of SIZE_RESTORED.
The other obvious possibility is to make all the tool windows be owned by the main window. So long as you are happy for the tool windows always to be on top of the main window, this will solve your problem. The owned windows will be hidden when the owner is minimized, and re-shown when the owner is restored.
Learn more about ownership in the MSDN topic on Window Features.
By now everyone writing for Windows probably knows that applications cannot (officially) steal focus from foreground processes, and why. But I have just managed to steal focus, inadvertently, and don't understand how this is even possible.
I have a Delphi app that user brings up with a hotkey (or by a mouse click, or by Alt+Tab), selects a piece of text and hits Enter. My app then minimizes (hides to the tray, even), and pastes the text user just selected into the active window. Nothing new here, plenty of similar projects out there - clipboard extenders, glossaries, macro programs, etc.
What is puzzling to me is that after doing all the above and then sleeping for 1500 ms, I restore my main form and it gets the focus back! It becomes the foreground window, even though it wasn't 1500 ms ago (tested; Windows 7 32-bit.).
In fact, I don't want this at all, so before restoring my main form I record which window has foreground and I give it back to that window after it's been given to me. I'm just curious why my app gets to be in the foreground when by rules it should not. Maybe I don't understand the rules as fully as I thought I did?
If you look at the documentation for SetForegroundWindow you see a list of conditions for the call to succeed, one of them is "The process received the last input event." So if the user does not do anything after pressing enter in your app you still have the right to steal focus. I don't know if Delphi calls SetForegroundWindow for you when the window is restored but it might be something to look into.
I don't know how you restore your window but using SW_SHOWNOACTIVATE with ShowWindow might help...
I'd need to detect when the user alt-tabs to the 'Desktop' on Windows 7. The resulting HCBT_ACTIVATE message, intercepted by my global CBT hook, contains the HWND reference to a window with WorkerW set as it's class. Safe (enough) to assume there aren't many visible top level alt tab windows with WorkerW as their class? Perhaps there is a better way you'd suggest to detect that the alt-tab activated window indeed corresponds to the window switching operation that gets you to the desktop?
Comparing the handle to the value returned by GetDesktopWindow() could be useful.
To all Win32 professionals. Let's say we have completed existing application with window. The task is to write another application with (my) window. My window must always align its left edge to existing window right edge while user moves existing window across the screen (my window not allowed to move by user).
Precondition: a) Existing window can not be subclassed b) Windows hooks are not a case.
Yes, looks right. I'd not asked this question if it not become a problem. Forgot to say that OS is Vista 2, application is IE. I try to make an application that follows IE main window, align it edge. Subclassing of IE not allowed, and SetWindowsHook not works correctly under regular user (when user have admin privileges application works normally). Such way as all of you talking about works under Windows prior to Vista.
And looks like there is no trivial way to solve this task. Thank you all.
I think you can't without a hook. SetWindowLong allows you to set a WndProc, but this won't work if the window belongs to a different application.
If you dont want/cant subclass or set global hooks, you can look into the following:
Implement your code in a DLL
Call CreateRemoteThread on LoadLibrary's address and your DLL's name to inject your DLL into the target process
In the DLL's DllMain, you can SetWindowHook just on the thread that owns the window. This is a local hook and doesn't require special privileges and is very nice to the system.
In your hook function, process WM_WINDOWPOSCHANGED on the main window's HWND and adjust your window accordingly.