Windows 8 Tray notification bug - windows

I'm trying to create simple Powershell script on Windows 8, that will notify me via system tray notification balloon. Code is very simple:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = "D:\1.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = "I'm there"
$objNotifyIcon.BalloonTipTitle = "Hello!"
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(10000)
1.ico is custom icon really existing on disc.
It works as it should except one small thing. I prefer to have taskbar on top of my window and it seems to make troubles for balloon: it is painted under taskbar (screen: https://dl.dropbox.com/u/1138313/systraybug.PNG).
I made test application in C# with notifyIcon and got same result. But another applications like Dropbox or Skydrive haven't such problem and my script with taskbar on bottom works perfect too.
I didn't find any style options in docs for NotifyIcon. Is it annoying bug or I can fix it?
Regards.
UPS: It seems, that however Dropbox app has same problem (shame on me, didn't see at first time). So this is system bug, I guess.

This is known bug in Windows. The only way you may be able to override the behavior of the taskbar is to find the handle of the balloon and then use SetWindowPos to make it topmost:
BOOL WINAPI SetWindowPos(
_In_ HWND hWnd,
_In_opt_ HWND hWndInsertAfter,
_In_ int X,
_In_ int Y,
_In_ int cx,
_In_ int cy,
_In_ UINT uFlags
);
MSDN: "A window can be made a topmost window either by setting the hWndInsertAfter parameter to HWND_TOPMOST and ensuring that the SWP_NOZORDER flag is not set, or by setting a window's position in the Z order so that it is above any existing topmost windows. When a non-topmost window is made topmost, its owned windows are also made topmost. Its owners, however, are not changed." See SetWindowPos for more info.
Another strategy is to demote the taskbar. Use this code to find the topmost window:
HWND FindMyTopMostWindow()
{
DWORD dwProcID = GetCurrentProcessId();
HWND hWnd = GetTopWindow(GetDesktopWindow());
while(hWnd)
{
DWORD dwWndProcID = 0;
GetWindowThreadProcessId(hWnd, &dwWndProcID);
if(dwWndProcID == dwProcID)
return hWnd;
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
}
return NULL;
}
Then demote the window or set the zorder of your window higher.

I had the same problem and discovered that the shape of the balloon depend on the size of the message body.
Namely, if your message body has up to 60 chars, round-shaped balloon will be displayed, and for longer messages, new and standard square-shaped balloon will be used.
I am not using the PowerShell to interact with system tray, but WPF NiotifyIcon library for tray icon display within WPF apps.
HTH

Related

How can I detect that window (class Windows.UI.Core.CoreWindow) is visible on Windows 10? [duplicate]

I have a Win32 application that determines whether there are any visible, non-iconic, minimizable windows being shown. To the best of my knowledge it's worked fine for Win9x through to Win8.1, but under Windows 10 it often finds several windows that aren't actually visible on the screen.
To try to identify what's going on I've written a simple test application that enumerates and records all such windows. Here's the essence of the EnumWindows callback code:
BOOL CALLBACK EnumFunc( HWND hWnd, LPARAM lParam )
{
if ( IsWindowVisible( hWnd ) )
{
if ( !IsIconic( hWnd ) )
{
const LONG style = GetWindowLong( hWnd, GWL_STYLE );
if ( WS_MINIMIZEBOX & style )
{
// record window info
}
}
}
return TRUE;
}
Most of the phantom windows under Windows 10 belong to background store app processes such as Mail, Calculator, and Photos. These are listed under the Background processes section of Task Manager, and if I use Task Manager to end those background tasks, their phantom window is no longer found by my test application.
In the above screen shot from my test application you can see that all but 1 of the offending windows belong to threads of the same process id 7768, which is ApplicationFrameHost.exe. The final window with process id 11808 is explorer.exe.
I've looked at the phantom windows with Spy++ and can't see any particular style combination that would help in uniquely identifying them.
I've had a suggestion that the undocumented Windows "bands" may be involved, but I've tried using the (undocumented, so this may be wrong) API:
BOOL WINAPI GetWindowBand (HWND hWnd, PDWORD pdwBand);
but it returns a band of 1 for any window, so doesn't differentiate these phantoms.
How to reliably identify these phantom windows?
The approved way of detecting these phantom windows is to use DwmGetWindowAttribute and DWMWA_CLOAKED.
Here's the code I've used:
static bool IsInvisibleWin10BackgroundAppWindow( HWND hWnd )
{
int CloakedVal;
HRESULT hRes = DwmGetWindowAttribute( hWnd, DWMWA_CLOAKED, &CloakedVal, sizeof( CloakedVal ) );
if ( hRes != S_OK )
{
CloakedVal = 0;
}
return CloakedVal ? true : false;
}
Thanks to Scot Br from MS for posting the answer here
Top-level windows of class ApplicationFrameWindow are containers for Windows Store apps. First, here is the window of Mail shown in Spy:
This is truly visible (not phantom). You can tell that it is because the first child is a window of class Windows.UI.Core.CoreWindow. Interestingly, the owner process of the ApplicationFrameWindow is APPLICATIONFRAMEHOST, but the owner process of the Windows.UI.Core.CoreWindow is a different one: HXMAIL. (I've not seen a child window owned by a different process than the parent one before!)
Compare that with a phantom window (as identified in your RWTool):
It is missing the child of class Windows.UI.Core.CoreWindow.
This suggests an answer to your question: If a top-level window is of class ApplicationFrameWindow, iterate it's children. If the first child has class Windows.UI.Core.CoreWindow, the window is visible, otherwise it is not (i.e. it is phantom).
But what if an old-fashioned, non-store app happened to have a top-level window of class ApplicationFrameWindow? It would not have a child of Windows.UI.Core.CoreWindow. Yet it is visible. How to tell this is an ordinary app and not a Windows Store app? I don't have a foolproof way. You could also check for the existence of the other child windows of a Store app: ApplicationFrameTitleBarWindow and ApplicationFrameInputSinkWindow. The chances of a non-Store app having this exact Windows hierarchy is vanishingly small.
EDIT
The ApplicationFrameWindow's (and also Windows.UI.Core.CoreWindow) have the WS_EX_NOREDIRECTIONBITMAP style set:
The window does not render to a redirection surface. This is for windows that do not have visible content or that use mechanisms other than surfaces to provide their visual.
At minimum, you could check for this style instead of special casing ApplicationFrameWindow. Though to see if any content was truly visible, you'd still need to make that depend on whether it has a child of Windows.UI.Core.CoreWindow.

Any way to block/remove keyboard hook in uncontrolled window's Menubar?

I'm sending keystrokes to an inactive Adobe Flash Projector window with PostMessage, that part works perfectly. I leave it running in the background and it interferes very little with my normal computer usage, which is the intent. The problem comes when I programmatically send the W (or less frequently Q) key while I happen to be holding Ctrl intended for a different windows shortcut. This triggers Ctrl-Q or Ctrl-W, both of which immediately close the Adobe Flash Projector. Ctrl-F and Ctrl-O have some undesirable effects as well.
EDIT: I'm not interested in solutions that briefly release the Ctrl key.
Is there anyway I can unhook shortcut keys from a third party window? It uses a standard OS menubar across the top of the window which is where the shortcuts are listed, so surely there's a way to reassign, unassign, or block it, right?
In the past I tried using these dlls to break the menu. It made it disappear but didn't break the shortcuts.
DllCall("SetMenu", uint, this.id, uint, 0)
hMenu := DllCall("GetSystemMenu", "UInt",this.id, "UInt",1)
DllCall("DestroyMenu", "Uint",hMenu)
Sorry for the strange syntax, this is from an early version of my program written in autohotkey.
The language I'm using now is C#, but I assume the solution uses a .dll, so that's not as important. Feel free to suggest or change my tags.
You can try to make inactive (WS_DISABLED - use GetWindowStyle and SetWindowStyle) the main window of destination application (the Window that contains menu).
You can try to find which functions are used by application and rewrite them in local copy of application with VirtualProtect and injecting assembler (dangerous if you have no knowledge about virtualization of memory). Check the application use GetKeyState or GetAsyncKeyState (it will be visible after opening the application in text editor).
You can try:
HMENU hMenu=GetMenu(applicationMainWindow);
SetMenu(applicationMainWindow,0);
// here send your input with SendMessageW instead of PostMessageW
SetMenu(applicationMainWindow,hMenu);
Each program can use various methods to handle user keyboard input. In this case probably is used GetAsyncKeyState or GetKeyState (for Ctrl) if you didn't send it and Ctrl is detected.
If it won't help you, please add code with your PostMessage to your question.
BTW. Instead of destroying GetSystemMenu you can clear appropriate window style and after sending input restore it (if the problem is System Menu - probability near 1%).
Using the program Resource Tuner's free trial, I opened up flashplayer_28_sa.exe, went to Accelerator Table (Apparently accelerator means shortcut in the context of Menus), and deleted the offending shortcuts. Then I saved it, and it failed to save, and I saved it again, and again, and again, and then it worked, although I did nothing differently that time.
I think it would work with other shortcuts for programs with standard windows menus.
Although I didn't end up using this method, (because changing the menus was ineffectual for blocking the shortcuts for those menu items), I found various interesting ways to modify a third party window's menus. I'll leave some of what I found here because while it relate to my question, it doesn't solve my problem. Comments are based on my fallible understanding of what they do.
Various externals:
[DllImport("user32.dll")]
//get hMenu of the window's menu
static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
//Attach hMenu to a window. if hMenu is 0, attach no menu (remove menu)
static extern bool SetMenu(IntPtr hWnd, IntPtr hMenu);
[DllImport("user32.dll")]
//Destroy hMenu
private static extern bool DestroyMenu(IntPtr hMenu);
[DllImport("user32.dll")]
//Destroy Destroy submenu at position within menu
private static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);
[DllImport("user32.dll")]
//Like GetMenu, but gets the restore/move/size/minimize/etc menu that you get when clicking on the little icon in the top left of a window (not the window's menu
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
//Adds a menu to a menu
private static extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
//Removes a menu from a menu
private static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, int uFlags);
[DllImport("user32.dll")]
//Like AppendMenu, but specifies position
private static extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
//Lets you set various properties of a menu (grayed out, checked, etc)
private static extern bool ModifyMenu(IntPtr hMenu, uint uPosition, uint uFlags, IntPtr uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
//gets the hMenu for a submenu
private static extern IntPtr GetSubMenu(IntPtr hMenu, int pos);
Notes on their parameters:
hWnd is the handle of a window with a standard menu.
hMenu is the menu handle, which can be the handle of the root level menu (Like File, Edit, Help) or a submenu item (Like open, copy, About ...). You can get these with GetSubMenu or GetSystemMenu or
uPosition is an integer position, 0 being the first one.
uFlags can be found on each function's individual page which you can find at https://msdn.microsoft.com/en-us/library/ff468865%28v=vs.85%29.aspx
lpNewItem refers to the string of text shown on the menu item.
uIDNewItem is a pointer like hMenu that will get inserted at the defined location

Finding handle for a button in the window of another program

I need some help. I wrote my questions at the end and will first explain what exactly my code is supposed to do:
I am making a program that will communicate with other programs. What I need my software to do is be able to click on a button on another program, and I believe the appropriate code to do this would be:
SendMessage(hWnd, Msg, wParam, lParam);
with
Msg = B_Click
wParam = 0;
lParam = 0;
however I am not sure how to get the hWnd which is the handle of a specific button on a specific window of another program that is running at the same time. I have read somewhere that I could possibly do the following:
HWND buttonHandle = FindWindowEx(hwndParent, hwndChildAfter, lpszClass, lpszWindow);
where:
HWND hwndParent = A handle to the parent window whose child windows are to be searched
HWND hwndChildAfter = if its null child windows are of the parent window are looked through
LPCTSTR lpszClass = (NOT SURE WHAT THIS IS)
LPCTSTR lpszWindow = (NOT SURE WHAT THIS IS)
I have a few issues with the FindWindowEX() function however.
Question 1: The window I am looking at has various buttons, so how would the function know which one of the 3 i am looking at?
Question 2: What are the lpszClass and lpszWindow variables and how might I get them?
Question 3: Is this even the right approach? If it's not, please point me to the right direction!
You don't need the handle of the button, you need the handle of its parent window. The button sends BN_CLICKED to its parent window. Look up the button's ID with spy++. Then use EnumChildWindows of the parent to look at all the child windows. For each child use GetWindowLong with GWL_ID to check its ID.

programmatically moving the mouse while the computer is locked

I have a program which monitors user's presence by monitoring the mouse movements. I need to make that program think that a user is present at all times. Programmatically moving the mouse every once in a while is very simple. However, I can't make this work when the computer is locked.
I work on Windows XP and have no need for the solution to support Vista or 7.
I had a similar issue. Simulating a mouse click instead worked for me... just get your screen position and keep tapping it.
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
[DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, uint dwExtraInf);
// tap on a timer somewhere inside the app region
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);

Why does clicking a child window not always bring the application to the foreground?

When an application is behind another applications and
I click on my application's taskbar icon, I expect the entire application to
come to the top of the z-order, even if an app-modal, WS_POPUP dialog box is
open.
However, some of the time, for some of my (and others') dialog boxes, only the dialog box comes to the front; the rest of the application stays behind.
I've looked at Spy++ and for the ones that work correctly, I can see
WM_WINDOWPOSCHANGING being sent to the dialog's parent. For the ones that
leave the rest of the application behind, WM_WINDOWPOSCHANGING is not being
sent to the dialog's parent.
I have an example where one dialog usually brings the whole app with it and the other does not. Both the working dialog box and the non-working dialog box have the same window style, substyle, parent, owner, ontogeny.
In short, both are WS_POPUPWINDOW windows created with DialogBoxParam(),
having passed in identical HWNDs as the third argument.
Has anyone else noticed this behavioral oddity in Windows programs? What messages does the TaskBar send to the application when I click its button? Who's responsibility is it to ensure that all of the application's windows come to the foreground?
In my case the base parentage is an MDI frame...does that factor in somehow?
I know this is very old now, but I just stumbled across it, and I know the answer.
In the applications you've seen (and written) where bringing the dialog box to the foreground did not bring the main window up along with it, the developer has simply neglected to specify the owner of the dialog box.
This applies to both modal windows, like dialog boxes and message boxes, as well as to modeless windows. Setting the owner of a modeless popup also keeps the popup above its owner at all times.
In the Win32 API, the functions to bring up a dialog box or a message box take the owner window as a parameter:
INT_PTR DialogBox(
HINSTANCE hInstance,
LPCTSTR lpTemplate,
HWND hWndParent, /* this is the owner */
DLGPROC lpDialogFunc
);
int MessageBox(
HWND hWnd, /* this is the owner */
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
Similary, in .NET WinForms, the owner can be specified:
public DialogResult ShowDialog(
IWin32Window owner
)
public static DialogResult Show(
IWin32Window owner,
string text
) /* ...and other overloads that include this first parameter */
Additionally, in WinForms, it's easy to set the owner of a modeless window:
public void Show(
IWin32Window owner,
)
or, equivalently:
form.Owner = this;
form.Show();
In straight WinAPI code, the owner of a modeless window can be set when the window is created:
HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent, /* this is the owner if dwStyle does not contain WS_CHILD */
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
or afterwards:
SetWindowLong(hWndPopup, GWL_HWNDPARENT, (LONG)hWndOwner);
or (64-bit compatible)
SetWindowLongPtr(hWndPopup, GWLP_HWNDPARENT, (LONG_PTR)hWndOwner);
Note that MSDN has the following to say about SetWindowLong[Ptr]:
Do not call SetWindowLongPtr with the GWLP_HWNDPARENT index to change the parent of a child window. Instead, use the SetParent function.
This is somewhat misleading, as it seems to imply that the last two snippets above are wrong. This isn't so. Calling SetParent will turn the intended popup into a child of the parent window (setting its WS_CHILD bit), rather than making it an owned window. The code above is the correct way to make an existing popup an owned window.
When you click on the taskbar icon Windows will send a WM_ACTIVATE message to your application.
Are you sure your code is passing the WM_ACTIVATE message to the DefWindowProc window procedure for processing?
Is the dialog's parent window set correctly?
After I posted this, I started my own Windows Forms application and reproduced the problem you describe. I have two dialogs, one works correctly the other does not and I can't see any immediate reason is to why they behave differently. I'll update this post if I find out.
Raymond Chen where are you!

Resources