I know this may sound to be a duplicate question but trust me it's not.
I have referred this question, but was not of much help as I am trying with a console application and the answerer himself tells he does not know the reason why ShowCursor(FALSE) does not work for console applications.
This thread did not help me either.
Here are the things I tried:
Using ShowCursor():
while(ShowCursor(false)>=0); //did not work
I first suspected that it was because of this statement in the msdn :
When Windows starts up, it checks if you have a mouse. If so, then the cursor show count is initialized to zero; otherwise, it is initialized to negative one.
I thought maybe in the latest windows, it doesn't recognize the connected mouse or the trackpad as an installed mouse and maybe that's why it didn't work. The following code shows it is not the case:
void UsingShowCursor()
{
CURSORINFO info;
info.cbSize = sizeof(CURSORINFO);
cout << ShowCursor(FALSE);
cout << ShowCursor(FALSE);
cout << ShowCursor(FALSE);
GetCursorInfo( &info ); //info.flags is CURSOR_SHOWING
}
Because I get -1, -2, -3. That means the initial show cursor count is obviously 0 and it does identify the installed mouse.
And another thing to note is that the GetCursorInfo() also tells that the cursor is showing.
Using SetCursor()
void UsingSetCursor()
{
HCURSOR prev = SetCursor(NULL);
int i = 0;
while(i++<10)
{
cout<<i<<endl;
Sleep(1000);
}
if( SetCursor(prev) == NULL ) //check if the previos cursor was NULL
cout<<"cursor was hidden and shown after 10 secs\n";
}
Doesn't work either.
This also did not work:
SetCursor(LoadCursor(NULL, NULL));
Edit:
Using LoadImage
Did not work either.
void UsingLoadImage()
{
// Save a copy of the default cursor
HANDLE arrowHandle = LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED);
HCURSOR hcArrow = CopyCursor(arrowHandle);
HCURSOR noCursorHandle = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR,1,1,LR_SHARED); //a single pixel thick cursor so that it wont be visible
HCURSOR noCursor = CopyCursor(noCursorHandle);
SetSystemCursor(noCursor, OCR_NORMAL);
int i =0 ;
while(i++<10)
{
cout<<i<<endl;
Sleep(1000);
}
//revert to previous cursor
SetSystemCursor(hcArrow, OCR_NORMAL);
DestroyCursor(hcArrow);
}
What can be the mistake? How can we hide the mouse for a console application?
You can use LoadImage() to achieve what you want. Here is the modified working version of the function UsingLoadImage() you quoted in the question. You have to include a cursor resource file to your visual studio project. Download the cursor from here or create your own.
Resource Files->Add->Existng Item and browse to the nocursor.cur file.
void UsingLoadImage()
{
// Save a copy of the default cursor
HANDLE arrowHandle = LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED);
HCURSOR hcArrow = CopyCursor(arrowHandle);
// Set the cursor to a transparent one to emulate no cursor
HANDLE noCursorHandle = LoadImage(GetModuleHandle(NULL), L"nocursor.cur", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE); //worked
//HANDLE noCursorHandle = LoadCursorFromFile(L"nocursor.cur"); //this also worked
HCURSOR noCursor = CopyCursor(noCursorHandle);
SetSystemCursor(noCursor, OCR_NORMAL);
int i =0 ;
while(i++<10)
{
cout<<i<<endl;
Sleep(1000);
}
SetSystemCursor(hcArrow, OCR_NORMAL);
DestroyCursor(hcArrow);
}
This would replace the normal arrow cursor with the transparent one. If you want to hide all the other cursor like the text, loading, hand cursors etc you have to hide them individually. If you don't want that to be the case, then you should opt out of the console application as many commenters have pointed out.
Hope this helps.
Related
I am writing a C++ Windows program that displays game stats/friends info over games using a Win32 window and a DirectX11 renderer. (that renders a UI that is controlled with the mouse and keyboard)
The window is overlaid on top of the game’s window and has the flags WS_EX_TRANSPARENT and WS_POPUP set.
When the window is activated, I set WS_EX_LAYERED to capture inputs.
The created window is positioned on top of the target window if GetWindow(target_, GW_HWNDPREV) is different from the handle of the created window.
It is placed on top of it by calling SetWindowPos with SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS.
I’ve double-checked that the flags are set correctly and that the functions are being called.
I also tried using ShowWindow with the SW_SHOW flag, but the result remained unchanged.
I’m currently running my tests on Portal 2, but ideally, I would want this to work on the majority of games. (OS used is Windows 11 22H2)
To activate the window and release the mouse capture from the game, I am calling SetForegroundWindow, SetActiveWindow, and SetFocus, all with the HWND of my window.
This approach works correctly when I run the program from Visual Studio, but when I run the compiled executable, the mouse remains locked in the game.
Both builds were tested in debug and release mode, and I really can't figure out why this is happening.
LRESULT Renderer::WndProc(...) {
switch (message) {
case WM_SIZE:
// resize buffers and recreate render target view
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(handle, message, w_param, l_param);
}
bool Window::Create(...) {
// ...
hwnd_ = CreateWindowEx(
wndclass,
class_name_.c_str(),
title_.c_str(),
WS_POPUP,
0, 0, 10, 10,
nullptr,
nullptr,
nullptr,
nullptr
);
SetLayeredWindowAttributes(hwnd_, 0, 255, LWA_ALPHA);
UpdateWindow(hwnd_);
constexpr MARGINS margin = {-1, -1, -1, -1};
const auto result = DwmExtendFrameIntoClientArea(hwnd_, &margin);
// ...
}
void Window::Activate() {
// Remove the WS_EX_LAYERED attribute.
SetClickThrough(false);
SetForegroundWindow(hwnd_);
SetActiveWindow(hwnd_);
SetFocus(hwnd_);
}
// ----------------------
// Sample main routine pseudocode:
// ----------------------
renderer->window.Create(...);
while (renderer->is_running()) {
renderer->BeginFrame();
// Position the window on top of the game found.
renderer->window().FollowTarget();
// Toggle the visibility using the F2 key.
// If transitioning from hidden to visible, call the window
// activation routine.
if (utils::KeyPressed(VK_F2)) {
if (ui->is_visible()) {
// .. window deactivation not included
ui->set_visible(false);
}
else {
renderer->window().Activate();
ui->set_visible(true);
}
}
ui->Draw(renderer);
renderer->Present();
}
I considered using a low-level keyboard/mouse hook to capture inputs, or offscreen rendering and presenting it in the game using a DirectX hook, but I’d rather avoid it as it would require many games to manually whitelist it.
Is there something else I’m missing or a different approach I should be taking?
This is my very first C++ application. I have absolutely no experience in C++ or Windows application programming so any feedback/help is appreciated. Please let me know if I am making any mistakes or not following best practices in my code.
I am trying to write a C++ program that replicates the behaviour of the WIN + D
keyboard shortcut, but only affects the windows on the monitor with the mouse.
Inspite of checking IsWindowVisible() and IsIconic() there are some system windows that get minimized and maximized, resulting in weird glitches like:
All icons from the desktop get minimized, and a gray bar appears
A blank instance of Microsoft Edge opens
The Windows Settings app appears out of nowhere
The code to minimize the windows:
static std::stack<HWND> minimizedWindowPointers;
Monitors monitors;
RECT activeMonitorRect;
static BOOL CALLBACK windowEnumerator(HWND w, LPARAM l){
if(!IsWindowVisible(w) || IsIconic(w) || getWindowTitle(w).size() == 0) return true;
RECT r;
GetWindowRect(w, &r);
if(doRectsIntersect(r, activeMonitorRect)){
SendMessage(w, WM_SYSCOMMAND, SC_MINIMIZE, 0);
minimizedWindowPointers.push(w);
}
return true;
}
void minimizeWindowsOnActiveMoniter(){
if(monitors.getRectOfMonitorWithPointer(&activeMonitorRect)) return;
EnumDesktopWindows(NULL, windowEnumerator, NULL);
areWindowsMinimized = true;
}
void maximizeWindowsOnActiveMoniter(){
HWND w;
for(int i = minimizedWindowPointers.size(); i > 0; i--){
w = minimizedWindowPointers.top();
minimizedWindowPointers.pop();
if(IsIconic(w)){
SendMessage(w, WM_SYSCOMMAND, SC_RESTORE, 0);
std::wcout << "MAXIMIZING: " << getWindowTitle(w) << std::endl;
}
}
areWindowsMinimized = false;
}
I am running Windows 10 Pro, with Visual Studio 19 Preview.
GetWindowLong can get the window flags with GWL_STYLE. Check for WS_CAPTION and WS_MINIMIZEBOX. I would also check for WS_VISIBLE again for good measure.
In VC++, I use EnumWindows(...), GetWindow(...), and GetWindowLong(), to get the list of windows and check whether the window is top window (no other window as owner), and whether the window is visible (WS_VISIBLE). However, although my desktop is showing only 5 windows, this EnumWindows is giving me 50 windows, how funny! Any Windows geek here please help me clarify...
The way to list out only windows in taskbar (or similarly in Alt-Tab box) is described by Raymond in this article on MSDN blog:
Which windows appear in the Alt+Tab list?
And this is the super function to check whether a window is shown in alt-tab:
BOOL IsAltTabWindow(HWND hwnd)
{
TITLEBARINFO ti;
HWND hwndTry, hwndWalk = NULL;
if(!IsWindowVisible(hwnd))
return FALSE;
hwndTry = GetAncestor(hwnd, GA_ROOTOWNER);
while(hwndTry != hwndWalk)
{
hwndWalk = hwndTry;
hwndTry = GetLastActivePopup(hwndWalk);
if(IsWindowVisible(hwndTry))
break;
}
if(hwndWalk != hwnd)
return FALSE;
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
// Tool windows should not be displayed either, these do not appear in the
// task bar.
if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
return FALSE;
return TRUE;
}
Credited to the source code here:
http://www.dfcd.net/projects/switcher/switcher.c
The windows that you are talking about, with an X button and a title bar, etc. are not the only kind of windows. Buttons, dropdown menus, labels, icons, text boxes, the task bar, and just about everything else is a window too1. So EnumWindows is doing exactly what it's supposed to do: enumerate all the top level windows.
1 Even though this is true, EnumWindows only enumerates the top level windows. That means it won't enumerate any child windows:
The EnumWindows function does not enumerate child windows, with the exception of a few top-level windows owned by the system that have the WS_CHILD style.
However, many things on your desktop are windows as well, not just the "windows" you're thinking about.
The answer provided by #jondinham does work perfectly for me. So I work out my own solution.
1.Problems I met with previous solution
Running on Windows 10 home edition 1909., I get two extra unexpected Windows "Calculator" and "Setting".
In addition, windows of Tencent QQ can not be detected, because the following fails:
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
However, I think the bug may be resulted by the particularity of Tencent QQ, I can not even make its' window TOPMOST with DeferWindowPos.
Perhaps someone can help me figure out why this happened and help improving the previous solution by #jondinham.
2.My Solution
I tried to examing the icons of the windows, and filter out windows that does not have its own icon or uses the icon same as the system default. I use code snippets from answer and answer and do some modification. This solution works very well for me.
HICON get_windows_HICON_critical(HWND hwnd)
{
// Get the window icon
HICON icon = reinterpret_cast<HICON>(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
if (icon == 0) {
// Alternative method. Get from the window class
icon = reinterpret_cast<HICON>(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
}
// Alternative method: get the first icon from the main module (executable image of the process)
if (icon == 0) {
icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// // Alternative method. Use OS default icon
// if (icon == 0) {
// icon = ::LoadIcon(0, IDI_APPLICATION);
// }
if(icon == ::LoadIcon(0, IDI_APPLICATION)){
// Filter out those with default icons
icon = 0;
}
return icon;
}
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
HICON icon = get_windows_HICON_critical(hWnd);
if(icon!=0){
std::cout << hWnd << ": " << windowTitle << std::endl;
}
}
return TRUE;
}
3.Problems with my solution
My solution can not deal with Windows Store APP, according to this question.
For all people looking to find a way to remove Invisible windows like Settings or Microsoft Store from the list:
These windows are cloaked, meaning they still have the dwStyle WS_VISIBLE, but the user can't see them.
You can detect this using the function DwmGetWindowAttribute. The dwAttribute you want to get is DWMWA_CLOAKED (enum constant 14). Only if the value in pvAttribute after the method call is 0, the window is not cloacked.
I have a problem with a program we're developing. It is written using MFC but does not use unicode. We have made a translation into simplified chinese. So far this is our first and only localization. We have moved all strings to resources to make them translateable. Everything seems to work fine on our computers (both Win7 and XP) but for some customers computers running windows XP we get problems:
On those computers all translated strings work except for those we enter into tree cotrols (CTreeCtrl is used directly). I'm not sure if it is the tree control or the text we enter that causes the problem, but the font seems to not get substituted in those controls. My guess is that maybe it does not get substituted because some of the strings also contain latin characters. Still, that kind of substitution seems to work in other places of the program and not all strings entered into the tree contain those characters either.
So my first question is: Is there a way to get to know what is happening inside the control? We can have remote access to the computers where the problem is happening but running a debugger on them may be a little tricky. What kind of tools can be used to diagnose this problem?
One possible solution that crossed my mind was to subclass the tree controls to get more control over the actual text drawing, maybe using the approach from http://blogs.msdn.com/b/oldnewthing/archive/2004/07/16/185261.aspx to get around the problem. Could this be effective or would it just be an awful lot of work for nothing?
Thanks a lot!
Ok, it seems on their system there was either a bug in the tree control implementation or they had some systemwide addin that hooked into the drawing in some way. What I ended up doing was to do custom drawing through notifications in the tree view and then using font linking to resolve the fonts. I dont think font linking would be necessary, though, because I think most of the time it ended up doing just TextOutW() with the preselected font anyway.
Here is a somewhat simplified code sample of what I ended up with:
void MyDlg::OnCustomDrawTreeItem( NMHDR* pNMHDR, LRESULT* pResult )
{
if (!mpFontLink)
{
*pResult = CDRF_DODEFAULT;
return;
}
LPNMTVCUSTOMDRAW pCustomdraw = (LPNMTVCUSTOMDRAW) pNMHDR;
switch(pCustomdraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
{
// Ask to do custom draw
*pResult = CDRF_NOTIFYITEMDRAW;
break;
}
case CDDS_ITEMPREPAINT:
{
// Ask for post paint notification
*pResult = CDRF_NOTIFYPOSTPAINT;
break;
}
case CDDS_ITEMPOSTPAINT:
{
// Get the rect of only the item, not the tree stuff
RECT rcItem;
m_pageTree.GetItemRect((HTREEITEM) pCustomdraw->nmcd.dwItemSpec, &rcItem, TRUE);
// Erase the item background in case the previous string drawn was wider
HDC hDC = pCustomdraw->nmcd.hdc;
FillRect( hDC, &rcItem, (HBRUSH) GetClassLongPtr(m_pageTree.GetSafeHwnd(), GCLP_HBRBACKGROUND));
pageStruct *pS = (pageStruct*) pCustomdraw->nmcd.lItemlParam;
DWORD dwFontCodepages = 0, dwStrCodepages = 0;
HFONT hOriginalFont = (HFONT)GetCurrentObject(hDC, OBJ_FONT);
HRESULT hr = mpFontLink->GetFontCodePages( hDC, hOriginalFont, &dwFontCodepages);
OML_CStringW tData = pS->csCaption.GetBuffer();
// Set up position etc
DWORD dwAlignOrig = GetTextAlign(hDC);
if (!(dwAlignOrig & TA_UPDATECP)) {
SetTextAlign(hDC, dwAlignOrig | TA_UPDATECP);
}
POINT ptOrig;
MoveToEx(hDC, 2 + rcItem.left, 1 + rcItem.top, &ptOrig);
SetTextColor( hDC, pCustomdraw->clrText );
SetBkColor( hDC, pCustomdraw->clrTextBk );
// Loop over the parts of the text
TuInt32 nIndex = 1;
while (nIndex <= tData.GetLength())
{
long nActualChars = 0;
wchar_t *pStr = (wchar_t*)tData.BaseGetItemP( nIndex );
TuInt32 nChars = 1 + tData.GetLength() - nIndex;
hr = mpFontLink->GetStrCodePages(pStr, nChars,
dwFontCodepages, &dwStrCodepages, &nActualChars);
if (dwStrCodepages & dwFontCodepages)
{
// We end up here almost every time, that is why TextOutW would probably be enough.
// This part is supported by the original font (or the GDI can help us switch automatically)
TextOutW(hDC, 0, 0, pStr, nActualChars);
}
else
{
// We need to link
HFONT hLinked;
if (FAILED(hr = mpFontLink->MapFont(hDC, dwStrCodepages, 0, &hLinked)))
{
// Fail: Output the rest without linking
TextOutW( hDC, 0, 0, pStr, nChars );
break;
}
// Output with linked font
SelectObject(hDC, hLinked);
TextOutW( hDC, 0, 0, pStr, nActualChars);
SelectObject(hDC, hOriginalFont);
mpFontLink->ReleaseFont( hOriginalFont );
}
nIndex += nActualChars;
}
OML_LOG_1( "_END:");
// Reset alignment mode
if (!(dwAlignOrig & TA_UPDATECP)) {
SetTextAlign(hDC, dwAlignOrig);
MoveToEx(hDC, ptOrig.x, ptOrig.y, NULL);
}
*pResult = CDRF_SKIPDEFAULT;
}
default:
{
*pResult = CDRF_DODEFAULT;
break;
}
}
} /* OnCustomDrawTreeItem */
In VC++, I use EnumWindows(...), GetWindow(...), and GetWindowLong(), to get the list of windows and check whether the window is top window (no other window as owner), and whether the window is visible (WS_VISIBLE). However, although my desktop is showing only 5 windows, this EnumWindows is giving me 50 windows, how funny! Any Windows geek here please help me clarify...
The way to list out only windows in taskbar (or similarly in Alt-Tab box) is described by Raymond in this article on MSDN blog:
Which windows appear in the Alt+Tab list?
And this is the super function to check whether a window is shown in alt-tab:
BOOL IsAltTabWindow(HWND hwnd)
{
TITLEBARINFO ti;
HWND hwndTry, hwndWalk = NULL;
if(!IsWindowVisible(hwnd))
return FALSE;
hwndTry = GetAncestor(hwnd, GA_ROOTOWNER);
while(hwndTry != hwndWalk)
{
hwndWalk = hwndTry;
hwndTry = GetLastActivePopup(hwndWalk);
if(IsWindowVisible(hwndTry))
break;
}
if(hwndWalk != hwnd)
return FALSE;
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
// Tool windows should not be displayed either, these do not appear in the
// task bar.
if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
return FALSE;
return TRUE;
}
Credited to the source code here:
http://www.dfcd.net/projects/switcher/switcher.c
The windows that you are talking about, with an X button and a title bar, etc. are not the only kind of windows. Buttons, dropdown menus, labels, icons, text boxes, the task bar, and just about everything else is a window too1. So EnumWindows is doing exactly what it's supposed to do: enumerate all the top level windows.
1 Even though this is true, EnumWindows only enumerates the top level windows. That means it won't enumerate any child windows:
The EnumWindows function does not enumerate child windows, with the exception of a few top-level windows owned by the system that have the WS_CHILD style.
However, many things on your desktop are windows as well, not just the "windows" you're thinking about.
The answer provided by #jondinham does work perfectly for me. So I work out my own solution.
1.Problems I met with previous solution
Running on Windows 10 home edition 1909., I get two extra unexpected Windows "Calculator" and "Setting".
In addition, windows of Tencent QQ can not be detected, because the following fails:
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
However, I think the bug may be resulted by the particularity of Tencent QQ, I can not even make its' window TOPMOST with DeferWindowPos.
Perhaps someone can help me figure out why this happened and help improving the previous solution by #jondinham.
2.My Solution
I tried to examing the icons of the windows, and filter out windows that does not have its own icon or uses the icon same as the system default. I use code snippets from answer and answer and do some modification. This solution works very well for me.
HICON get_windows_HICON_critical(HWND hwnd)
{
// Get the window icon
HICON icon = reinterpret_cast<HICON>(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
if (icon == 0) {
// Alternative method. Get from the window class
icon = reinterpret_cast<HICON>(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
}
// Alternative method: get the first icon from the main module (executable image of the process)
if (icon == 0) {
icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// // Alternative method. Use OS default icon
// if (icon == 0) {
// icon = ::LoadIcon(0, IDI_APPLICATION);
// }
if(icon == ::LoadIcon(0, IDI_APPLICATION)){
// Filter out those with default icons
icon = 0;
}
return icon;
}
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
HICON icon = get_windows_HICON_critical(hWnd);
if(icon!=0){
std::cout << hWnd << ": " << windowTitle << std::endl;
}
}
return TRUE;
}
3.Problems with my solution
My solution can not deal with Windows Store APP, according to this question.
For all people looking to find a way to remove Invisible windows like Settings or Microsoft Store from the list:
These windows are cloaked, meaning they still have the dwStyle WS_VISIBLE, but the user can't see them.
You can detect this using the function DwmGetWindowAttribute. The dwAttribute you want to get is DWMWA_CLOAKED (enum constant 14). Only if the value in pvAttribute after the method call is 0, the window is not cloacked.