How do I hide the mouse cursor in a Win32 console? - c++

I have a function that sets a Win32 console to full screen. The problem is when it goes into full screen, it's not hiding the mouse cursor.
It doesn't seem to matter if it's in full screen or not. The mouse cursor still shows when I call ShowCursor(FALSE). How can it be hidden?
As in the docs for ShowCursor(), the cursor will hide if the function returns a value greater than 0. If it's negative, it will hide. The value is returning -2 for me, so it should hide in this case, but it is not.
bool Console::setFullScreen(const bool fullScreen)
{
HWND handle;
if (fullScreen)
{
// Hide the scrollbar
showScrollBar(false);
// Set the window style
handle = GetConsoleWindow();
LONG style = GetWindowLong(handle, GWL_STYLE);
style &= ~(WS_BORDER | WS_CAPTION | WS_THICKFRAME);
SetWindowLong(handle, GWL_STYLE, style);
// Set the window to full screen in windowed mode
ShowWindow(getHandle(), SW_MAXIMIZE);
// Hide the cursor
ShowCursor(FALSE); // Fails
}
else
{
showScrollBar(true);
// Set the window style
handle = GetConsoleWindow();
LONG style = GetWindowLong(handle, GWL_STYLE);
style |= WS_BORDER;
style |= WS_CAPTION;
style |= WS_THICKFRAME;
SetWindowLong(handle, GWL_STYLE, style);
// Set the window to full screen in windowed mode
ShowWindow(getHandle(), SW_NORMAL);
// Show the cursor
ShowCursor(TRUE);
}
return true;
}

I haven't tried this, but you can probably change the mouse cursor of the console window by calling GetConsoleWindow to get the HWND of the console window, then calling SetClassLong to set the cursor.
HCURSOR hNewCursor = LoadCursor(/* whatever*/);
SetClassLong(GetConsoleWindow(), GCL_HCURSOR, hNewCursor);
To make the cursor disappear, create a cursor which is entirely transparent.

Related

Switch progressbar from normal to marquee

I have a Dialog that has an progress bar.
I wan't to add a Method to that dialog that sets the progressbar to marquee.
I try following:
void CDownloader::SetIntermediate(wstring info)
{
SetDlgItemText(IDC_DOWNLOADER_LABEL, info.c_str());
auto style = GetWindowLong(GWL_STYLE);
style &= ~( PBS_SMOOTH | PBS_SMOOTHREVERSE | PBS_VERTICAL);
style |= PBS_MARQUEE;
SetWindowLong(GWL_STYLE, style);
RECT windowRect;
GetWindowRect(&windowRect);
SetWindowPos(HWND_TOP, &windowRect,SWP_FRAMECHANGED);
HWND progress = GetDlgItem(IDC_DOWNLOADER_PROGRESS);
::SendMessage(progress, PBM_SETMARQUEE, TRUE, 100);
}
However this does not work :(
I set the Window Style to MARQUEE removing styles that may conflict with it, using setWindowPos to update the style and the set the Progress to MARQUEE.
I can set the progress bar in the designer to marquee, but can't switch bac to normal.
For all that whant the correct code:
void CDownloader::SetPending(bool value)
{
if(value)
{
HWND progress = GetDlgItem(IDC_DOWNLOADER_PROGRESS);
auto style = ::GetWindowLong(progress, GWL_STYLE);
style |= PBS_MARQUEE;
::SetWindowLong(progress, GWL_STYLE, style);
::SendMessage(progress, PBM_SETMARQUEE, TRUE,0);
}
else
{
HWND progress = GetDlgItem(IDC_DOWNLOADER_PROGRESS);
auto style = ::GetWindowLong(progress, GWL_STYLE);
style &= ~PBS_MARQUEE;
::SetWindowLong(progress, GWL_STYLE, style);
::SendMessage(progress, PBM_SETMARQUEE, FALSE,0);
}
}

CreateWindowEx posts WM_SIZE?

CreateWindowEx API really posts WM_SIZE message?
When I create a window via CreateWindowEx as full screen mode,
CreateWindowEx posts WM_SIZE but window mode doesn't.
My code sets the window style like this :
if(bFullscr)
{
//When the window is in full screen mode.
nStyle = WS_POPUP;
nExtraStyle = WS_EX_APPWINDOW;
}
else
{
//Otherwise.
nStyle = WS_OVERLAPPEDWINDOW;
nExtraStyle = (WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
}
And changes display settings like this (full screen mode only) :
if(bFullscr)
{
DEVMODE sScrSet;
memset(&sScrSet, 0, sizeof(DEVMODE));
sScrSet.dmSize = sizeof(DEVMODE);
sScrSet.dmPelsWidth = nWidth;
sScrSet.dmPelsHeight = nHeight;
sScrSet.dmBitsPerPel = nColorBit;
sScrSet.dmFields = (DM_BITSPERPEL | DM_PELSHEIGHT | DM_PELSWIDTH);
if(ChangeDisplaySettings(&sScrSet, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
//Error routine.
}
}
I'm really wonder why CreateWindowEx posts WM_SIZE message selectively.
If you simply want to resize the window, somewhere in your code you should have ShowWindow(hWnd, nCmdShow); change it as follows:
ShowWindow(hWnd, SW_SHOWDEFAULT);//show normal
ShowWindow(hWnd, SW_SHOWMAXIMIZED);//show maximized (full screen)
SetWindowPos(hWnd, NULL, 10, 10, 300, 300, SWP_SHOWWINDOW);//show at specific position
Also you could use WS_MAXIMIZE in CreateWindow, but that could complicate things. Window usually has WS_OVERLAPPEDWINDOW or WS_POPUP|WS_CAPTION|WS_SYSMENU. You should pick one and keep it simple.
When Window size changes, it receives WM_SIZE, you can catch that and examine it.

SDL2 toggle SDL_WINDOW_RESIZABLE state for fake fullscreen

To do a "fake" fullscreen window in SDL2 without a modeset you can create a borderless, maximized window using something like this.
int idx = SDL_GetWindowDisplayIndex(g_displayWindow);
SDL_Rect bounds;
SDL_GetDisplayBounds(idx, &bounds);
//SDL_SetWindowResizable(g_displayWindow, SDL_FALSE);
SDL_SetWindowBordered(g_displayWindow, SDL_FALSE);
SDL_SetWindowPosition(g_displayWindow, bounds.x, bounds.y);
SDL_SetWindowSize(g_displayWindow, bounds.w, bounds.h);
For non-resizable windows, this works perfectly. On windows created with SDL_WINDOW_RESIZABLE there is an annoying grey border on the bottom and right edges of the screen (on windows). Unfortunately there isn't a SDL_SetWindowResizable function (as of SDL 2.0.4). How can we get rid of the resizing border without recreating the window?
SDL_WINDOW_FULLSCREEN_DESKTOP and SDL_WINDOW_FULLSCREEN both do a modeset which I want to avoid - it takes longer, it's harder to alt-tab out of, and if the game hits a breakpoint in the debugger it can lock up the whole system.
This is what I came up with - tested and works on windows.
void SDL_SetWindowResizable(SDL_Window *win, SDL_bool resizable)
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(g_displayWindow, &info);
#if WIN32
HWND hwnd = info.info.win.window;
DWORD style = GetWindowLong(hwnd, GWL_STYLE);
if (resizable)
style |= WS_THICKFRAME;
else
style &= ~WS_THICKFRAME;
SetWindowLong(hwnd, GWL_STYLE, style);
#endif
}
The SDL_SetWindowResizable() function was added in SDL 2.0.5 which was released in Oct 2016. Announcing SDL 2.0.5
Assuming your SDL_Window pointer (that you got from SDL_CreateWindow()) is named window, use:
/* To disable resizing: */
SDL_SetWindowResizable(window, SDL_FALSE);
/* To enable resizing: */
SDL_SetWindowResizable(window, SDL_TRUE);

Clearing the screen after switching away from fullscreen mode?

So I've got an OpenGL application running that can toggle between fullscreen mode and windowed mode. It currently does this by resizing the window and changing styles.
However, it seems to not invalidate the screen when switching from fullscreen mode to windowed mode, which leaves things I've drawn lingering onscreen after the switch.
Interestingly, it only exhibits this behavior in single monitor mode. If I'm running with multiple monitors, it invalidates okay, and clears my drawing.
I don't think this is a driver bug, as it's happening on two separate computers using two separate video cards(although admittedly they are both nVidia.), I'm thinking I'm doing something wrong somewhere.
I've tried a bunch of methods for getting Windows to clear the screen of my previously fullscreen drawings, but nothing seems to work. InvalidateRect(), RedrawWindow(), ChangeDisplaySettings()...
Specifically:
InvalidateRect(m_hwnd, &rectx, true); // rect being the dimensions of either the screen or my window.
InvalidateRect(HWND_DESKTOP, NULL, TRUE); // Doesn't seem to do anything.
RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW);
ChangeDisplaySettings(NULL, 0);
Well, actually, one thing that does seem to work is ShowWindow(hwnd, SW_HIDE) before resizing. However that loses focus for a moment, allowing other applications to grab my application's input, and seems a bad way to go about it.
I should note that I'm not doing any actual display mode changes when I'm seeing this behavior; just staying at the current resolution for fullscreen.
I'm a bit clueless where I'm going wrong. Simplified code:
if(m_isFullscreen)
{
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
}
else
{
ChangeDisplaySettings(&m_dmSavedScreenSettings, 0);
}
if(m_isFullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(false);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
if(m_isRunning) // Because ShowCursor uses a counter to indicate, and windowed mode defaults to cursor on, we don't need to increment the counter and double it being on.
{
ShowCursor(true);
}
}
RECT rect;
rect.left = 0;
rect.top = 0;
if(m_isFullscreen) { rect.right = 1280; } else { rect.right = 640; }
if(m_isFullscreen) { rect.bottom = 1024; } else { rect.bottom = 480; }
AdjustWindowRectEx(&rect, dwStyle, false, dwExStyle);
SetWindowLongPtr(m_hwnd, GWL_STYLE, dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, dwExStyle);
if(m_isFullscreen)
{
MoveWindow(m_hwnd, 0, 0, 1280, 1024, true);
}
else
{
MoveWindow(m_hwnd, 0, 0, 640, 480, true); // windowed
}
And that's more or less it. Some other supporting code and error checking, but that's what I'm doing... dmSavedSettings is saved before m_hwnd is assigned from NULL, and not afterwards. My initial window creation works fine, and fullscreen works fine. It's just returning to Windowed after being fullscreen that's the issue.
If you set a null background brush in your window class, windows will not be cleared automatically. You must add a WM_PAINT handler that calls your OpenGL display handler, which in turn clears the viewport (glClearColor) and redraws.
As datenwolf mentions in another answer's comment, you want to use SetWindowPos() instead of MoveWindow() when making use of SetWindowLongPtr().
My dirty background problems were solved by calling ChangeDisplaySettings(NULL, 0) AFTER resizing my window. Doing it before does little, but afterwards appears to work fine.

CDialog doesnt show in task bar

Im trying to get a CDialog that has no border or frame to show in the task bar.
It is created in the InitInstance of CWinApp (used to update the app) and i have tried setting the WS_EX_APPWINDOW flag but it still doesnt show in the task bar.
Any ideas?
Edit:
As defined in the resource:
IDD_UPDATEFORM_DIALOG DIALOGEX 0, 0, 246, 124
STYLE WS_POPUP
EXSTYLE WS_EX_APPWINDOW
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
END
As used:
UpdateForm *dlg = new UpdateForm(UPDATE_FILES, CWnd::GetDesktopWindow());
INT_PTR nResponse = dlg->DoModal();
UpdateForm::UpdateForm(int updateType, CWnd* pParent) : CDialog(IDD_UPDATEFORM_DIALOG, pParent)
{
m_bInit = false;
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON);
m_Progress = new DesuraProgress();
m_updateType = updateType;
}
Still Shows up like so:
http://update.goldeneyesource.net/lodle/noicon.jpg http://update.goldeneyesource.net/lodle/noicon.jpg
Edit #2:
To set the icon for this window (essentially a splash screen), you can send the window a WM_SETICON message along with a desired icon.
For a dialog, you can do this in OnInitDialog(). Here's a snippet that uses the default windows information icon as noted here: LoadIcon # MSDN.
// CHelperDlg message handlers
BOOL CHelperDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 32516 is also known as IDI_INFORMATION
HICON hIcon = LoadIcon(0, MAKEINTRESOURCE(32516));
// 0 in WPARAM is 'small version'
::SendMessage(GetSafeHwnd(), WM_SETICON, 0, (LPARAM)hIcon);
// 1 in WPARAM is 'large version'
::SendMessage(GetSafeHwnd(), WM_SETICON, 1, (LPARAM)hIcon);
// No cleanup as HICONs are free from disposal rules.
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
--
Edit:
I created a second project to mimic your update, but I don't see any differences except the inclusion of DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS) in my .rc file. These dialog style definitions don't affect the display of the dialog.
I've uploaded key parts for my minimal example to http://gist.github.com/461057 for your reference, in case you'd like to try adding this dialog ahead of yours for testing.
Also, I'm using VS2010. I have VS2008 available if you'd like me to repeat this test in that version as well.
--
Original:
Try specifying the desktop window (via CWnd::GetDesktopWindow()) as the parent window when you create the dialog.
// Member Variable
CHelperDlg *dlg;
// Meanwhile, elsewhere...
dlg = new CHelperDlg();
dlg->Create(IDD_HELPERDLG, CWnd::GetDesktopWindow());
dlg->ShowWindow(SW_SHOW);
// or...
// dlg->DoModal();
Also, don't forget to destroy the dialog when you're done with it, either in the destructor of the class owner, or other convenient location.
I figured out a hack to get this to work. Instead of disabling the toolbar/caption bar styles to get no border, i used SetWindowRgn to clip the frame and title bar. Same affect, less issues.
RECT rect;
GetWindowRect(&rect);
int w = rect.right - rect.left;
int h = rect.bottom - rect.top;
HRGN region = CreateRoundRectRgn(5, 30, w-5, h-5-30, 5, 5);
SetWindowRgn(region, true);