How to detect if any app goes fullscreen or exiting fullscreen? - c++

I need to disable notifications at my app when there is another app fullscreen like powerpoint or VLC to do not bother a user.
For now, I get to this code, but it always returns true. Whether there is some app fullscreen or not. I am not sure whether this should work only for app bars or also taskbar.
HWND hWnd;
hWnd = FindWindow(L"Shell_TrayWnd", nullptr);
if( hWnd )
{
APPBARDATA apd;
apd.cbSize = sizeof(APPBARDATA);
apd.hWnd = hWnd;
bool uState = bool(SHAppBarMessage(ABN_FULLSCREENAPP , &apd));
if(uState)
qDebug()<<"fullscreen";
else
qDebug()<<"not fullscreen";
}

ABN_FULLSCREENAPP is not a message you send to the shell, it's a message the shell sends to you when an application enters or leaves full screen mode. The message is sent to the owner of an app bar created with ABM_NEW.
Documentation is here.
My reading of the documentation is that you have to create an app bar to receive this message but you may be able to set it to zero height or width with ABM_SETPOS if you want to hide it.

Related

C++ Set window below (or above) the icons on the desktop

I'm trying to place a window either above or below the icons on the desktop. I mostly just want it to stay attached to the desktop at all times. Similar to Rainmeter or Wallpaper engine. So far, everything I tried either disables interaction, or gets minimized when you use the "Show Desktop" button. Any ideas on how to achieve this? I'm using electron and a native module in node to do this.
It's an old subject, but I'll find out how to do it recently and answer it.
The method is to find the handle of SHELLDLL_DefView, the parent of the desktop window, and then make the SHELLDLL_DefView handle the parent of my window to fix it to the desktop.
The method is to find the handle of SHELLDLL_DefView, the owner of the desktop window, and then make the SHELLDLL_DefView handle the owner of my window to fix it to the desktop.
SHELLDLL_DefView is located under the Progma or WorkerW handle. This is a code to prevent ShowDesktop from being used in the Electget package created by ffi-napi to attach the Electron browserWindow to the desktop.
const GWLP_HWNDPARENT = -8;
// find SHELLDLL_DefView in Progma
const progman = user32.FindWindowExA(ref.NULL, ref.NULL, 'Progman', ref.NULL);
let defView = user32.FindWindowExA(progman, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
// find SHELLDLL_DefView in WorkerW
if (!defView) {
const desktopHWnd = user32.GetDesktopWindow();
let workerW = 0;
do {
workerW = user32.FindWindowExA(desktopHWnd, workerW, 'WorkerW', ref.NULL);
defView = user32.FindWindowExA(workerW, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
} while (!defView && workerW);
}
if (!defView) return false;
// make the SHELLDLL_DefView handle the parent of my window
user32.SetWindowLongPtrA(hWnd, GWLP_HWNDPARENT, defView);
This allows you to create a window where you can click and interact without being hidden by ShowDesktop.
2022-03-29
There was a wrong word, so I corrected it. According to doc, it is not a parent window, but an owner window. In the doc, it is strange that the GWLP_HWNDPARENT constant is related to the parent window. However, when tested with Spy++, the corresponding constant changes the owner window.

How do I create a Window in App B so that App A may use it to render instead of using it's own Window

Folks, I apologize if this sounds like a newbie questions, but I am not very familiar with Windows development as a whole. So I was given App A, which does a lot of things and one particular function is to render a duck picture. Internally it created the Window with the title 'DrawingBoard' and later on when the program is ready to render it will try to find this "DrawingBoard" window. I was only told that this is how App A finds the window to render the duck:
static const TCHAR TITLE_NAME[] = "DrawingBoardParent";
static const TCHAR TITLE_CLASS_NAME[] = "DrawingBoard";
HWND parent = FindWindowExA(NULL, NULL, NULL, TITLE_NAME);
while (parent != NULL)
{
//find the child window by window title
window = findWindowRecursive(parent, TITLE_CLASS_NAME);
if (window != NULL)
{
break;
}
//no child by the given title name found, go down one level
parent = FindWindowExA(NULL, parent, NULL, TITLE_NAME);
}
Now I need to create App B and I want to create my own "DrawingBoard" window on App B. Because App A uses the above algorithm to find the rendering window, instead of using it's own App A "DrawingBoard" Window, it will use my App B "DrawingBoard" Window.
Questions:
1) Is this within the realm of possibility at all ?
2) Say if both App A & B have two windows with the same title "DrawingBoard". Which one does FindWindowEx(NULL, NULL, NULL, ""DrawingBoard"); return ?
3) If FindWindowEx always returns the handle for App A "DrawingBoard" window. How do I hack it so it will return App B "DrawingBoard" window.
Thanks for the help folks.
Say if both App A & B have two windows with the same title "DrawingBoard". Which one does FindWindowEx(NULL, NULL, NULL, ""DrawingBoard") return?
That is ill-defined. It will return one of them. You cannot influence which is returned.
If FindWindowEx always returns the handle for App A "DrawingBoard" window. How do I hack it so it will return App B "DrawingBoard" window.
You cannot. The other app is broken. Its search for a window that it created is broken, since it can yield the wrong window, a window from another process.
You can avoid getting caught out by this app by using a different name for your window. However you really ought to either fix or remove the defective program. That's the sane way forward.

Sending BM_CLICK message to Windows 10 application not working

I have an installation dialog (made with nsis) that has two buttons (install and cancel). I'm trying to write automated tests for the install process using low level win32 api. To click on the button(s) I use the following code:
char windowName[] = "Desktop Application Setup";
char cancelButtonText[] = "Cancel";
HWND hWndMainWindow = NULL;
HWND hButton = NULL;
hWndMainWindow = FindWindow(NULL, windowName);
if (hWndMainWindow)
{
hButton = FindWindowEx(hWndMainWindow, NULL, NULL, cancelButtonText);
if (hButton)
{
SendMessage(hButton, BM_CLICK, 0, 0);
}
}
On Windows 7, this works perfectly. On Windows 10, it simply does nothing. It finds the button, it sends the message, but the click just doesn't happen.
Is this some security thing introduced in Windows 10? Is it a known issue?
it is better to send WM_COMMAND with the ID of the button, but the way you are doing works also if Lang is always in English. but the problem with your case is that buttons on dialog usually have an "&" to indicate the keyboard short cut, and usually hidden by system unless you press alt key. (like menus).
so: text of the button is most likely to be "&cancel"

Windows Mobile C++ Tray Icon

I'm trying to place my application that is mainly running in the background in a 'tray-like' area on the Windows Mobile 6.5.
I do it the obvious way by with Shell_NotifyIcon
BOOL ShowTrayIcon(HWND hWnd, HINSTANCE hIns, BOOL bShowIcon)
{
BOOL bRet = FALSE;
g_structNotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
g_structNotifyIconData.hIcon = LoadIcon(hIns, MAKEINTRESOURCE(IDI_GPSCOMPASS));
g_structNotifyIconData.hWnd = hWnd;
g_structNotifyIconData.uCallbackMessage = WM_SYSTRAY_MSG;
g_structNotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON;
g_structNotifyIconData.szTip[0] = 'Bzz';
g_structNotifyIconData.uID = ID_TRAY;
if (bShowIcon)
bRet = Shell_NotifyIcon(NIM_ADD, &g_structNotifyIconData);
else
bRet = Shell_NotifyIcon(NIM_DELETE, &g_structNotifyIconData);
return bRet;
}
This is where i am trying to place the icon :
Tray icon within the 'today' area http://www.fotoszok.pl/upload/666d99dc.jpg
The Shell_NotifyIcon does the thing but the Icon is not shown on the Today screen, i can see it's in the tray from any place except the Today/Home screen.
Now I've read somewhere that this is because the Tray area in Today screen is reserved for system notifications and 'we' can't place any icons in there - well if that's true, can somebody please confirm that?
Indeed, Shell_NotifyIcon doesn't support adding the icon in the Today screen. This is even one of the first things mentioned in the function documentation:
This function sends a message to the system to add, modify, or delete an application-specific icon from the taskbar status area. It does not affect icons appearing on the home screen.
You can try using SHNotificationAdd.

Motif: Intercept close box event and prevent application exit? (C++)

How do I intercept when the user clicks on a motif window's (widget's) close box, and how do I prevent the Motif window manager to close the entire calling application on the close box being clicked (so that my app can close the Motif application context and windows and continue to run)? I've tried to find out myself with Google, tuts and docs, but no dice. C++ required.
This seems to work (found on the inet):
#include <Xm/Protocols.h>
Boolean SetCloseCallBack (Widget shell, void (*callback) (Widget, XtPointer, XtPointer))
{
extern Atom XmInternAtom (Display *, char *, Boolean);
if (!shell)
return False;
Display* disp = XtDisplay (shell);
if (!disp)
return False;
// Retrieve Window Manager Protocol Property
Atom prop = XmInternAtom (disp, const_cast<char*>("WM_PROTOCOLS"), False);
if (!prop)
return False;
// Retrieve Window Manager Delete Window Property
Atom prot = XmInternAtom (disp, const_cast<char*>("WM_DELETE_WINDOW"), True);
if (!prot)
return False;
// Ensure that Shell has the Delete Window Property
// NB: Necessary since some Window managers are not
// Fully XWM Compilant (olwm for instance is not)
XmAddProtocols (shell, prop, &prot, 1);
// Now add our callback into the Protocol Callback List
XmAddProtocolCallback (shell, prop, prot, callback, NULL);
return True;
}
Setting such a callback will prevent the application being closed as a result of the close event being handle be the default event handlers.
Won't vendorShellWidgetClass do the trick for you? As in, closing just the motif app context and not the window..
IIRC, on X11, when you click a window's close box, the window manager sends a signal to your application, which tells it to exit. Whether you use motif or gtk or Qt is irrelevant since the close box belongs to the WM, not your application.
You need to catch the unix signal to prevent your application from closing.