Popup window without stealing focus from other fullscreen programs - c++

Hi so the title describes it pretty well, I'm currently working on a software that will be installed on a POS system now when an event occurs this program needs to create a popup for the cashier to confirm what my concern is that since this is a separate program from the POS if the POS is fullscreen (not windowed) It will steal focus from the POS thus having to wait 2 seconds while window flashes to black fullscreen pos goes down then popup comes up and then having to restore the POS.
I need to be able to get around this problem of POS minimizing and having the cashier's input as well.
Here is what I'm currently attempting.
// Create the window object
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW,
ClsName, WndName,
WS_POPUPWINDOW | WS_CAPTION,
200, 120, 200, 320,
NULL, NULL, hInstance, NULL);
// Find out if the window was created
if( !hWnd ) // If the window was not created,
return 0; // stop the application
// Display the window to the user
Sleep(10000); //Used so I can open a fullscreen window to test
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
UpdateWindow(hWnd);
Thank you for your help :)

Related

Draw on Windows 10 wallpaper in C++

Is there a way to get an handle to Windows's wallpaper (behind icons) in C++ in order to draw on it?
That would allow to make an active desktop (discontinued after Windows XP) equivalent, a Wallpaper Engine equivalent, or any other similar tool. (Temperature and resources usage monitoring on the wallpaper in my case).
Note: the handle returned by GetDesktopWindow() returns the window at desktop icons level, not behind it.
Solutions from similar questions aren't working for me.
Specifically i tried VLC media player's wallpaper mode code.
Key code is:
hwnd = FindWindow( _T("Progman"), NULL );
if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
if( !hwnd )
{
msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
"wallpaper mode not supported" );
return;
}
But it will not draw on the wallpaper.
Credits to this draw behind desktop icons C# page as reference. The article explains the theory behind the solution, which applies regardless of the programming language being used.
Long story short, the smooth fading animation you see on Windows 10 when changing wallpaper is achieved by creating a new window that does exactly what you're asking for, drawing under the icons. That window achieves the fade-in effect for the new wallpaper, and is created by the Program Manager.
In the mentioned article you can see together with C# implementation an explanation of every step. Here i'll write a C++ equivalent keeping comments from the source.
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL);
HWND* ret = (HWND*)lParam;
if (p)
{
// Gets the WorkerW Window after the current one.
*ret = FindWindowEx(NULL, hwnd, L"WorkerW", NULL);
}
return true;
}
HWND get_wallpaper_window()
{
// Fetch the Progman window
HWND progman = FindWindow(L"ProgMan", NULL);
// Send 0x052C to Progman. This message directs Progman to spawn a
// WorkerW behind the desktop icons. If it is already there, nothing
// happens.
SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
// We enumerate all Windows, until we find one, that has the SHELLDLL_DefView
// as a child.
// If we found that window, we take its next sibling and assign it to workerw.
HWND wallpaper_hwnd = nullptr;
EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd);
// Return the handle you're looking for.
return wallpaper_hwnd;
}
The C-like casts can be replaced with reinterpret_casts, according to your coding preferences.
One note that isn't mentioned in the article:
Since when changing wallpaper a new WorkerW window is generated to achieve the fading effect, if the user tries to change wallpaper while your program is actively drawing and refreshing your instance of WorkerW, the user set background will be placed on top of your drawing, start fading in until it reaches 100% opacity, and lastly be destroyed, leaving your WorkerW still running.

WM_PAINT return 0 causing cpu usage 2%

Im having a problem with my WM_Paint
If i make it return 0/1 it makes my cpu to stay around 1% even if the program is minimised.
My paint window is using OpenGL
If i break from WM_PAINT it causes drawing isues when resizing
case WM_PAINT:
{
application->paint_window();
return 0;
}
window = std::make_unique<platform::window>(
L"Main window",
CW_USEDEFAULT, CW_USEDEFAULT,
1200, 600,
WS_OVERLAPPEDWINDOW /*| WS_CLIPSIBLINGS | WS_CLIPCHILDREN*/, 0,
CS_OWNDC,
this, process_message
);
while (::GetMessage(&msg, 0, 0, 0) > 0)
{
if (!::TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
edit:
if i remove my function call in WM_PAINT my cpu goes up to 15%.
why does it go so high if im not doing anything.
As explained under the WM_PAINT message:
The system sends this message to a window procedure when changes to the window have altered the content of the client area.
The system keeps an internal update region to determine, whether any parts of the window need painting. It is the application's responsibility to then validate the area it has painted to (either by a call to BeginPaint, ValidateRect, or ValidateRgn).
Failing to validate the region that no longer needs to be updated will have the system re-generate a WM_PAINT message. That leads to the resource consumption you observe.

C++: A Lingering 'ghost' window appears..?

My program - among other things - changes the console window appearance (mainly the window size and border).
Now on my computer, everything is working perfectly at the moment, but when I run the application in VirtualBox, or on a different computer, I get the following:
The window on the top-left corner of the image is not actually a window. It's an image of a window, that you can't click. (mouse clicks go through it)
You can get rid of it by stretching the selection rectangle on the desktop over it, or if you highlight (for example) a button that is under it. Also, you can move a window over it, which makes it disappear completely.
The black rectangle on the bottom-right corner of the image is my console window, which is displayed correctly.
My question is, how to get rid of the 'ghost' window with C++?
I tried Googling a bit, but all I could find was ChangeDisplaySettings(0, 0);, which on my computer doesn't do anything (probably because I don't even have this problem on my computer), and in VirtualBox, it first appears to momentarily make the console window fullscreen and then back to the way it was. (the screen flickers the first time you run the application)
Although it does remove the ghost window, I don't want the screen to flicker like that, so this is not what I'm looking for.
EDIT:
As I can't really figure out what would be relevant code for this problem, I'll just dump pretty much all the code that has anything to do with changing the window itself in my program.
CSBIEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
GetConsoleScreenBufferInfoEx(hCon, &CSBIEx);
CSBIEx.dwSize.X = 49;
CSBIEx.dwSize.Y = 21;
SetConsoleScreenBufferInfoEx(hCon, &CSBIEx);
srWnd.Bottom = 20;
srWnd.Left = 0;
srWnd.Right = 48;
srWnd.Top = 0;
SetConsoleWindowInfo(hCon, TRUE, &srWnd);
GetClientRect(hWnd, &rClnt);
rClnt.top += 1;
rClnt.bottom -= 2;
rClnt.right -= 1;
SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP);
exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
exStyle &= ~WS_EX_CLIENTEDGE;
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle);
BringWindowToTop(hWnd);
SetWindowPos(hWnd, HWND_TOPMOST, ((rScr.right / 2) - rClnt.right / 2) - 1, (rScr.bottom / 2) - rClnt.bottom / 2, 0, 0, SWP_FRAMECHANGED | SWP_DRAWFRAME | SWP_NOSIZE);
SetWindowRgn(hWnd, CreateRectRgnIndirect(&rClnt), 1);
ShowWindow(hWnd, SW_SHOWNORMAL);
//ChangeDisplaySettings(0, 0);
2ND EDIT:
I don't know if it's of any help, but I noticed that if I use ChangeDisplaySettings(NULL, 0); instead of ChangeDisplaySettings(0, 0); it doesn't do anything. That's pretty weird considering that NULL is #defined 0..
If no one can figure anything out, I'll probably just end up using ChangeDisplaySettings(0, 0);.
InvalidateRect(NULL, NULL, TRUE);
Was the thing that I was looking for.
Are you running an "Aero" theme on your computer? If so, switch to the classic theme. Betcha you will see the problem manifest itself. I think your app is not handling the WM_PAINT message properly. The Aero themes send far fewer WM_PAINT messages. The OS does the painting with bitmaps that it saves.
EDIT: Try calling these with the new dimensions:
BOOL WINAPI SetConsoleDisplayMode(
_In_ HANDLE hConsoleOutput,
_In_ DWORD dwFlags,
_Out_opt_ PCOORD lpNewScreenBufferDimensions
);
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033%28v=vs.85%29.aspx
BOOL WINAPI SetConsoleWindowInfo(
_In_ HANDLE hConsoleOutput,
_In_ BOOL bAbsolute,
_In_ const SMALL_RECT *lpConsoleWindow
);
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686125%28v=vs.85%29.aspx
You can also try sending yourself a WM_PAINT message with DispatchMessage.

Float GLUT window on top without titlebar on OSX

I'm creating a simple commandline applicatiation that starts a GLUT window.
I need that GLUT window to be always on top and remove the titlebar.
Basically GLUT does not provide anything for this so i'm looking into other options. On Windows i would do something like:
glutCreateWindow( "dpd" ); //create window with glut
HWND hwnd = FindWindow( "GLUT", "dpd" );
SetWindowPos( hwnd, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOREPOSITION | SWP_NOSIZE ); //set the window always-on-top
But how can i do such a thing on OSX? (C++)
I already use some Carbon code to remove the menubar, but the titlebar is still visible:
SetSystemUIMode(kUIModeAllHidden,KWindowNoTitleBarAttribute);
i'm new to OSX development and out of ideas..
thanks
Ok, i found out that there is now way to make changes / ajustments to a glut window. So i finaly created a workaround: i start glut on one thread, on an other thread i created a fullscreen window with a transparent background and created a dynamic backgroundimage (png) with a viewport with just the size of the GLUT window without the titlebar. Sound kind a ugly but hey, it works, the client does get the result they want within budget :)
If you think there is a better solution for this without creating a manual openGL implementation please let me know!

Win32: Bring a window to top

I have a Windows program which has two 2 windows in it:
hwnd (main interface)
hwnd2 (toplevel window, no parent, created by hwnd)
When I double click on hwnd, I need hwnd2 to pop up and show some data, so I use this function to bring hwnd2 to top:
BringWindowToTop(hwnd2);
hwnd2 is brought to top, but there is one thing odd. When I click on hwnd2 again, hwnd (main interface) pops itself up again automatically.
I tried to use the following function to solve this problem, but non of them works.
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
//doesn't work
BringWindowToTop(hwnd2); //This is the function brings hwnd2 to top
SetForegroundWindow(hwnd2); //doesn't work
SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
//doesn't work
SetWindowPos(hwnd2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
// hwnd2 "always" on top, not what I want
SetActiveWindow(hwnd2); // doesn't work too (for replying to Magnus Skog, thanks)
SwitchToThisWindow(hwnd2, TRUE);// got the same problem with BringWindowToTop function
SwitchToThisWindow(hwnd2, FALSE);
How could I solve this problem?
Thanks in advance.
(for replying to aJ, hwnd2 doesn't have parent because it needs to be a toplevel window so it can be in front/back of other windows)
(hwnd2 is a media player which is composed of several windows, one of the windows is for video dispaly, two other trackbar controls for progress bar and volume bar, one Toolbar control for control panel.)
(There is one this might help, no matter which window I click on hwnd2, hwnd pops up automatically as loong as "the mouse is on top of hwnd in Z-order", including menu bar and non-client area, etc.)
(This media player is writen in Direct Show. I use IVideoWindow::put_Owner to put video window as the video owner, Direct Show internally creates a sub-video window as a child of the video window. Except for this sub-video window which I can't see the source code, I don't see any thing suspicious in hwnd2.)
I found the reason, which is because of Direct Show. I use multithread to execute it, and then the problem's solved. But...why??
This problem can be resolved by using PostMessage (rather than SendMessage).
try this,it is said coming from M$
HWND hCurWnd = ::GetForegroundWindow();
DWORD dwMyID = ::GetCurrentThreadId();
DWORD dwCurID = ::GetWindowThreadProcessId(hCurWnd, NULL);
::AttachThreadInput(dwCurID, dwMyID, TRUE);
::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
::SetForegroundWindow(m_hWnd);
::SetFocus(m_hWnd);
::SetActiveWindow(m_hWnd);
::AttachThreadInput(dwCurID, dwMyID, FALSE);
In order to bring a window to top, you should get your window handle,thread handle, the windows thread handle who is in foreground
then we attach our thread to foreground window thread and get input by AttachThreadInput, then we set our window z order
to topmost and then restore its z order to normal, call SetForegroundWindow,SetFocus,SetActiveWindow to make sure our window is brought to top and is active and have focus
then deattach the input queue from the old foreground window thread, make our thread the only one who capture the input events
So why should We call AttachThreadInput, it is because
SetFocus sets the keyboard focus to the specified window. The window must be
attached to the calling thread's message queue.
What does AttachThreadInput do?
The AttachThreadInput function can be used to allow a set of threads
to share the same input state. By sharing input state, the threads
share their concept of the active window. By doing this, one thread
can always activate another thread's window. This function is also
useful for sharing focus state, mouse capture state, keyboard state,
and window Z-order state among windows created by different threads
whose input state is shared.
We use SetWindowPos to bring the windows to topmost and show the window if the window is hidding by using SWP_HIDEWINDOW
SetWindowPos function changes the size, position, and Z order of a
child, pop-up, or top-level window. These windows are ordered
according to their appearance on the screen. The topmost window
receives the highest rank and is the first window in the Z order
If your problem is your window is also minimized , you should add one line code to the end
ShowWindow(m_hWnd, SW_RESTORE);
Both work great:
::SetForegroundWindow(wnd)
or
::SetWindowPos(m_hWnd, // handle to window
HWND_TOPMOST, // placement-order handle
0, // horizontal position
0, // vertical position
0, // width
0, // height
SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE// window-positioning options
);
But remember that the last one sets the window always on top.
After many tries and errors.I found following solution to this problem:
SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); // restore the minimize window
SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
//redraw to prevent the window blank.
RedrawWindow(hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN );
The hwnd is your windows HWND . Please do not just copy and paste. You also need use GetLastError to check api error after every api call.
I have confirm following result on my win7:
Can restore minimize window and no error return.
If the window already top, the window title will blink and no error return.
If the window has closed, it will return the error "0x578 Invalid window handle."
It can bring the window to the top on all not top-most window and no error return.(For example it will behind the top-most taskmanager)
It do not make the window top-most. The user can make other window on top of it.
SwitchToThisWindow works best for me.
Have you tried SetActiveWindow()?
This will restore an app if minimized and bring it to the front:
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
//work great!
Var
WndHandle:HWND;
begin
WndHandle :=FindWindowEx(0,0,nil,'Calculator');
PostMessage(WndHandle,WM_SHOWWINDOW,SW_RESTORE,0);
SetForegroundWindow(WndHandle);
end;