Cannot become the key window after setting the window to a fake full screen on OSX 10.6.8 - osx-snow-leopard

My application initially had a window (Def). Then it spawned a new window (New). All the two windows can be switched from the Window sub menu item or by the space control.
But if I tried to set the "New" window to a fake full screen mode on OSX 10.6.8, there would be a problem that if I switched to the "Def" window either by menu or space control. I cannot "fully" switch back to "New" window.
// setting a fake full screen window on 10.6.8
NSApplicationPresentationOptions prereqOptions =
NSApplicationPresentationAutoHideDock |
NSApplicationPresentationAutoHideMenuBar;
[[NSApplication sharedApplication]
setPresentationOptions:prereqOptions];
[[self window] setToolbar:nil];
[[self window] setStyleMask:NSBorderlessWindowMask];
[[self window] setFrame:[[NSScreen mainScreen] frame]
display:YES];
The "fully" means I can see the "New" is brought to the top of screen, but the window controller cannot receive the notification "NSWindowDidBecomeKeyNotification". Furthermore, by
[NSApp keyWindow], I can see the key window is always the "Def". And I can always see the "Def" is checked in the Window submenu.
Anyone had ever encountered this issue?

Finally after 2 days investigation, the answer goes back to the documentation of NSWindow.
There are two related methods.
(BOOL)canBecomeKeyWindow
Return Value
YES if the window can become the key window, otherwise, NO.
Discussion
Attempts to make the window the key window are abandoned if this method returns NO. The NSWindow implementation returns YES if the window has a title bar or a resize bar, or NO otherwise.
And
canBecomeMainWindow
Indicates whether the window can become the application’s main window.
(BOOL)canBecomeMainWindow
Return Value
YES when the window can become the main window; otherwise, NO.
Discussion
Attempts to make the window the main window are abandoned if this method returns NO. The NSWindow implementation returns YES if the window is visible, is not an NSPanel object, and has a title bar or a resize mechanism. Otherwise it returns NO.
So the conclusion is that if the window doesn't have a title bar or resize bar, it by default cannot become a main and key window. When setting the window to the fake full screen on 10.6.8 by [NSWindow setStyleMask:NSBorderlessWindowMask], the title bar is gong.
To resolve this issue, one needs to override the above 2 methods with returning YES.

Related

Win32 C++ ListView WM_CONTEXTMENU Issue

I have a ListView with which I'd like to use a context menu that changes depending on selection. I'm making sure that I'm first able to display a menu when the right mouse button has been released (as per normal context menu behaviour).
In my ListView WNDPROC I'm using WM_CONTEXTMENU to display the context menu. The menu however is displayed at the location the cursor began the selection, not at the end.
From the MS documentation:
DefWindowProc generates the WM_CONTEXTMENU message when it processes the WM_RBUTTONUP or WM_NCRBUTTONUP message or when the user types SHIFT+F10. The WM_CONTEXTMENU message is also generated when the user presses and releases the VK_APPS key.
When I inspect the call stack, with a breakpoint in WM_CONTEXTMENU, I see that the message sent prior to WM_CONTEXTMENU was 0x0204 or WM_RBUTTONDOWN containing the coordinates of the cursor at this time. This probably explains the menu location issue, but why would this be happening?
When I hold the RMB down outside of the ListView and release it inside, the context menu still appears and I can see from the call stack that the last message was 0x0205 or WM_RBUTTONUP.
Not sure whether I have something wrong in my code, or I'm not understanding something. Any help on this issue would be greatly appreciated, thanks.
Rather than relying on the WM_RBUTTON(DOWN|UP) messages to determine the mouse coordinates, the WM_CONTEXTMENU's own lParam gives you the mouse's screen coordinates of the message that generated the WM_CONTEXTMENU. If those coordinates are not what you are expecting, you can use GetMessagePos() instead, which will report the screen coordinates at the time WM_CONTEXTMENU was generated. Either way, you can then convert the screen coordinates into ListView client coordinates using ScreenToClient() or MapWindowPoints().
Just be sure you also handle the case where the popup menu is being invoked by the user via keyboard input rather than mouse click. In that case, the lParam of WM_CONTEXTMENU will carry the screen coordinates [x=-1,y=-1], and you can query the ListView for the position of its selected item(s) using LVM_GETITEMPOSITION or LVM_GETITEMRECT as needed, then convert that position to screen coordinates using ClientToScreen() or MapWindowPoints(), and then display the popup menu at that screen location.

Is this how I make custom controls both transparent and flicker-free in Windows? Or do I have one of these steps wrong?

I could begin by asking the question outright or by citing my sources (this, this, this, and this) descriptively, but I'll walk you ll through what I'm trying to do instead.
Let's start with a main window. It has its own window class whose hbrBackground is set to COLOR_BTNFACE + 1. Now let's do
EnableThemeDialogTexture(hwnd, ETDT_ENABLE | ETDT_USETABTEXTURE)
so the tab control we're about to add will be drawn with visual styles. (Try Windows XP with the standard Luna theme for best results.) Now let's add a tab control and two tabs.
On the first tab, we create an instance (let's call it container) of a new window class. This window class is going to hold various controls. I could set hbrBackground to COLOR_BTNFACE + 1, but then it will draw over the tab background. So I want this new child window to be transparent. So what I do is
set the class hbrBackground to GetStockObject(HOLLOW_BRUSH)
set container's extended style to WS_EX_TRANSPARENT
set the class WM_ERASEBKGND handler to do SetBkMode((HDC) wParam, TRANSPARENT); return 0; to set the device context and have Windows draw the transparent background.
So far so good, right? I'm not sure if I'm really doing all this correctly, and I'd like this to also be flicker-free, which doesn't seem to happen: when I resize the window (at least in wine) I get either flicker or garbage drawn (even in child controls, somehow!). Windows XP in a VM just shows flicker. I tried tweaking some settings but to no avail.
But wait, now I want to have another control, one that just draws some bitmap data. On the next tab, create another container, then have a third window class area as a child of that. area only draws in the upper-left 100x100 area and has scrollbars; the rest of the window area should be transparent.
Right now, what I have for area is:
the window class hbrBackground set to NULL and styles CS_HREDRAW and CS_VREDRAW set
the extended window style being 0
the WM_ERASEBKGND simply doing return 1;
the WM_PAINT filling the entire update rect with COLOR_BTNFACE + 1 before drawing, and rendering all of it
This is flicker-free, but obviously not transparent. NOW I'm really not sure what to do, because I want the area to be transparent in such a way that it shows the tab control background. Again, I tried tweaking settings to bring them closer to what I tried above with container, but I got either flicker or invalidation leftovers when I tried.
So how do I get both of these custom control types (the container and the drawing area) to be both flicker-free and transparent?
I presently must target Windows XP at a minimum, though if the solution would be easier with Vista+ only I'd be happy to keep that solution on the side in case I ever drop XP support (unfortunately Stack Overflow doesn't let me hand out silver medals...).
Thanks!
To paint your window in a manner that is "flicker free", you will need to paint your window to a bitmap, then copy the bitmap to the destination device context. On Windows XP, you will need to create a bitmap, adjust the origin of the drawing DC and then paint your window. On Vista and later you can use BeginBufferedPaint and its associated routines to do the buffering for you.
Once you have buffered painting working, you can then use WM_PRINTCLIENT to paint your window's parent window into the your drawing DC before you do any actual drawing. Unfortunately, not all windows will support WM_PRINTCLIENT.
You could consider using DrawThemeParentBackground, rather than WM_PRINTCLIENT directly.
Combining these two methods together will leave you with transparent flicker-free drawing.

Tracking tooltip causes grey "trail" of excruciatingly slow repaint

Let me first decribe the symptoms of the problem. I'll then give additional facts and explain my question.
Symptoms
I have written a custom Windows control. The control paints itself in response to a WM_PAINT message. It also uses tracking tooltips (ie the tracking feature of the TOOLTIPS_CLASS common control).
When I drag the mouse over the control, the tooltip nicely follows the mouse. The problem is that it leaves a grey streak in its wake. This streak takes an observable amount of time to repaint -- as you can see from the attached image, I was able to hit PRNTSCRN and take a screenshot of it before the control had time to repaint itself.
(What is even more peculiar is that the WM_PAINT handler doesn't appear to have run even once. But note that the code that causes the tooltip to track is in WM_MOUSEMOVE, and that is obviously being perfectly responsive.)
Facts
Please assume vanilla C using Win32 libraries.
The WM_PAINT handler is actually very fast. The control has a number of features that require repainting the entire client area, and this is imperceptible to the user.
Indeed, some features run animations that repaint the whole client area at 15-24fps.
It is also decently efficient and doesn't repaint much more than the update rectangle on any given repaint.
The WM_ERASEBKGND handler does nothing and simply returns 1.
I never erase the background, I simply paint over it.
The window has the following style bits set:
ws: WS_CHILD | WS_VISIBLE
ex: WS_EX_COMPOSITED
cs: CS_DBLCLKS
The parent window is a top-level window with the following style bits set:
ws: WS_TILEDWINDOW | WS_CLIPSIBLINGS | WS_VISIBLE
ex: WS_EX_WINDOWEDGE
cs: CS_REDRAW | CS_DBLCLKS
The control's window class background brush is GetStockObject(NULL_BRUSH).
The only other way I have found to cause the same kind of "trail" is by dragging another top-level window over my control. The area that is temporarily obscured by the dragged top-level window leaves the same trail.
Giving the control's window class the CS_SAVEBITS style doesn't seem to make any difference. I still get the same perceptible trail of slow repaints.
Questions
Why am I getting the grey at all, especially if I set CS_SAVEBITS?
What can I do to make the grey go away?
Should I call UpdateWindow() each time I move the tooltip?
But this doesn't solve the issue of other top-level windows being dragged over top of my control.
Help!
Adding the WS_CLIPCHILDREN style bit to the parent window made this issue go away.
For whatever reason, when a window is partly obscured and then revealed, the OS is very generous with the WM_ERASEBKGND messages and very stingy with the WM_PAINT messages. What was happening is that the parent's WM_ERASEBKGND handler was erasing over top of my control. Adding WS_CLIPCHILDREN causes the parent window to clip its erasing.
Funnily enough, this solution worked for my control, which simply ignores the WM_ERASEBKGND message, but didn't work for standard BUTTON controls with style BS_GROUPBOX style. I expect this is because of the same generous WM_ERASEBKGND policy. The standard button control probably dutifully erases its background in handling that message and then vainly waits around for a WM_PAINT message.

How to hide window from "Applications" tab in task manager?

I have question regarding the CreateWindowEx function. I have 2 windows, a main one and a popup one. I want a popup window to hide everywhere. It is currently not displayed in taskbar and it is not even visible in alt+tab menu. However it is visible on "Applications" tab in task manager. What flags do I need to use in CreateWindowEx to hide my popup window from there?
Current code:
hHistoryWindow = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_LAYERED, szAppName, L"HistoryWindow", WS_EX_TOPMOST | WS_POPUP, WIDTH, TOP, width, height, NULL, NULL, hInstance, NULL);
I also wanted to ask, whether I need to release a bitmap resource from "static" window before using DestroyWindow() function? I set image to a "static" window this way:
SendMessage (hStatic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hWhiteStone);
Is it enough to release hWhiteStone or do I need to release also handle returned by SendMessage() (- or is it done automatically by DestroyWindow)?
Thank you for any info.
Kra
Make it a child of your main window. Do this by changing the fourth last parameter to the HWND of your main window. This SHOULD make windows treat your popup window as part of the same application as your main window.

How to detect that WPF window has been snapped in Windows 7

Windows 7 has the snapping feature which 'snaps' a window to the edges, and changes the one dimension of the window size to match the same dimension of the screen, and then choses another size for the other dimension.
I want to detect that it has happened so that in my WindowStyle.None window with custom chrome, I can implement the proper behavior for double clicking the titlebar.
The snapping does not alter the WindowState, so I cannot detect that it has happened. Since only one dimension of window is set to match the the screen, I can not distinquish between a snapped window and a user resized window. Does Win7 send out a specific message, or include a flag in the WM_xxxx messages when it causes a resize? Is the formula to the other dimension (not the one matching the screen) defined anywhere so that I can check if both dimensions match that of a snapped window?
have you tried using spy++ to watch window messages to see what gets sent in what order? maybe there's an extra mesage in there that windows is using.

Resources