How do I add vertical scrollbar to a fullscreen win32 console? - c++

When I set my win32 console to full screen, the vertical scrollbar disappears. When the text goes to the bottom of the screen, it does not scroll up. Newly written output is not presented to the user because it is below.
This is the style:
if (isFullScreen)
{
// Set the full screen window style.
style = GetWindowLong(handle, GWL_STYLE);
style &= ~(WS_BORDER | WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPEDWINDOW);
SetWindowLong(handle, GWL_STYLE, style);
// Minimalize, then show maximized to avoid the cursor blink bug in conhost.exe.
ShowWindow(handle, SW_MINIMIZE);
ShowWindow(handle, SW_SHOWMAXIMIZED);
// Set the font size
setFontSize(fontSize);
}
I searched the web but it's understandably not common.
How can I add the vertical scrollbar to this while in full screen?

On my computer, I can realize the appearance of full screen console and vertical scrollbar. My system is Win10, using vs2017.
This is my code.
#include "pch.h"
#include <iostream>
#include <Windows.h>
void full_screen()
{
HWND hwnd = GetForegroundWindow();
int cx = GetSystemMetrics(SM_CXSCREEN); /* Screen width pixels */
int cy = GetSystemMetrics(SM_CYSCREEN); /* Screen Height Pixel */
LONG l_WinStyle = GetWindowLong(hwnd, GWL_STYLE); /* Get window information */
/* Set window information to maximize the removal of title bar and border*/
SetWindowLong(hwnd, GWL_STYLE, (l_WinStyle | WS_POPUP | WS_MAXIMIZE) & ~WS_CAPTION & ~WS_THICKFRAME & ~WS_BORDER);
SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
}
int main()
{
full_screen();
while(1)
{
std::cout << "Hello World!\n";
}
return 0;
}
Debug Result:

The official way to set a console to fullscreen is to call SetConsoleDisplayMode().
Under Windows 10 Pro Version 1803 the following code shows a vertical scrollbar without further ado:
#include <iostream>
#include <windows.h>
int main()
{
HANDLE const hConsole = ::GetStdHandle( STD_OUTPUT_HANDLE );
if( hConsole == INVALID_HANDLE_VALUE ||
! ::SetConsoleDisplayMode( hConsole, CONSOLE_FULLSCREEN_MODE, nullptr ) )
{
DWORD const err = ::GetLastError();
std::cerr << "Failed to set console fullscreen mode. System error: " << err << "\n";
return 1;
}
for( int i = 0; i < 200; ++i )
{
std::cout << "Hello World!\n";
}
return 0;
}
Note that SetConsoleDisplayMode() can fail if the process is not attached to a console (e. g. by passing the flag CREATE_NO_WINDOW to CreateProcess()) or if STDOUT is redirected to a file.

Related

C++ when pressing close: minimize to system tray and keep running

I have an app in c++ for windows, which should minimize the window of the command line when the user presses the close button. It shouldn't be in the taskbar anymore and have an icon in the system tray.
What I mean is: when user presses close button, the program should only "hide" like i described.
I can only manage to make the program have an icon in the tray while running, but can't make it stay running when x is pressed
Thanks for help!
this is my code so far:
#include <iostream>
#include <Windows.h> // needed for console window and system tray functionality
// global variables
NOTIFYICONDATA trayIcon; // structure for the tray icon
HWND hwnd = GetConsoleWindow(); // handle to the console window
// function prototypes
void minimizeToTray(); // function to minimize the console window to the system tray
int main()
{
// set up the tray icon
trayIcon.cbSize = sizeof(NOTIFYICONDATA);
trayIcon.hWnd = hwnd;
trayIcon.uID = 1;
trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
trayIcon.hIcon = (HICON)LoadImage(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); // specify the icon file
trayIcon.uCallbackMessage = WM_USER + 1; // message identifier for tray icon clicks
trayIcon.uVersion = NOTIFYICON_VERSION_4;
strcpy_s(trayIcon.szTip, "Program Running");
// add the tray icon to the system tray
Shell_NotifyIcon(NIM_ADD, &trayIcon);
std::cout << "Program running..." << std::endl;
// set up a message loop to handle tray icon clicks and window messages
MSG msg;
while (true) // infinite loop
{
// check for messages
while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
{
// if the user clicks the close button, minimize the window to the tray
if (msg.message == WM_CLOSE)
{
minimizeToTray();
continue; // skip the rest of the message loop
}
// if the user clicks the tray icon, restore the window
if (msg.message == WM_USER + 1)
{
ShowWindow(hwnd, SW_RESTORE);
}
// pass the message to the default window procedure
DispatchMessage(&msg);
}
// do other tasks here
}
// remove the tray icon before exiting the program
Shell_NotifyIcon(NIM_DELETE, &trayIcon);
return 0;
}
// function to minimize the console window to the system tray
void minimizeToTray()
{
// hide the console window
ShowWindow(hwnd, SW_HIDE);
// update the tray icon
trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
Shell_NotifyIcon(NIM_MODIFY, &trayIcon);
}
When the user "closes" the window it should just hide and not close entirely, like ms teams or discord do
After testing your code, it definitely fails. It cannot get the message WM_CLOSE. Just as Hans Passant said, you can use SetConsoleCtrlHandler() to attached to the console receive the signal.
Here is my code. It runs well.
It used ShellExecuteW() API to restart the program to implement minimization.
Setting SW_MINIMIZE, it will minimize in the task bar.
Setting SW_HIDE, it will minimize in the system tray. But it cannot be opened again.
#include <Windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
NOTIFYICONDATA trayIcon;
HWND hwnd = GetConsoleWindow();
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
char mesg[128];
switch (CEvent)
{
case CTRL_C_EVENT:
MessageBox(NULL,
L"CTRL+C received!", L"CEvent", MB_OK);
break;
case CTRL_BREAK_EVENT:
MessageBox(NULL,
L"CTRL+BREAK received!", L"CEvent", MB_OK);
break;
case CTRL_CLOSE_EVENT:
ShellExecuteW(NULL, L"open", L"yourexe.exe", NULL, NULL, SW_MINIMIZE);
break;
case CTRL_LOGOFF_EVENT:
MessageBox(NULL,
L"User is logging off!", L"CEvent", MB_OK);
break;
case CTRL_SHUTDOWN_EVENT:
MessageBox(NULL,
L"User is logging off!", L"CEvent", MB_OK);
break;
}
return TRUE;
}
int main()
{
trayIcon.cbSize = sizeof(NOTIFYICONDATA);
trayIcon.hWnd = hwnd;
trayIcon.uID = 1;
trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
trayIcon.hIcon = (HICON)LoadImage(NULL, L"icon1.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
trayIcon.uCallbackMessage = WM_USER + 1;
trayIcon.uVersion = NOTIFYICON_VERSION_4;
Shell_NotifyIcon(NIM_ADD, &trayIcon);
std::cout << "Program running..." << std::endl;
MSG msg;
if (SetConsoleCtrlHandler(
(PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE)
{
printf("Unable to install handler!\n");
return -1;
}
while (true)
{
while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
{
if (msg.message == WM_CLOSE)
{
continue;
}
if (msg.message == WM_USER + 1)
{
ShowWindow(hwnd, SW_RESTORE);
}
DispatchMessage(&msg);
}
}
Shell_NotifyIcon(NIM_DELETE, &trayIcon);
return 0;
}

C++ changing image on user input in WinAPI

I am having issues in getting my .bmp image displayed to change to another one on user input. The image can be successfully printed at the start (title.bmp), but is supposed to change when pressing 1 or 2 followed by enter (to introduction.bmp & start.bmp). I must be missing something!
Where this happens is around the bottom of the code from while (running == 1) { so skip down to there.
I am using loadImage("title.bmp"); to print my images (I change the filename appropriately of course), and cin >> menuSelection; to pause the program and wait until the user presses one or two followed by enter.
I've searched many, many pages on how to print and change images in WinAPI, and this is the closest I can get. If there is any other information I have missed please tell me and I will comment it. Thanks in advance for helping!
//These are the libraries (external files) to include at the start.
#include <cstdio>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
//Defining the [global] variables that will be used throughout the program
int running = 1;
int menuSelection = 0;
int userInput;
int userInputDummy;
int intPointer;
//Starter variables used in creating a window and printing images. These are global.
HDC imageDC; // the DC to hold our image
HBITMAP imageBmp; // the actual bitmap which contains the image (will be put in the DC)
HBITMAP imageBmpOld; // the DC's old bitmap (for cleanup)
const int screenSize_X = 640;
const int screenSize_Y = 480;
//Functions! Sections of code to re-used in the program
// Function to load the image into our DC so we can draw it to the screen
void loadImage(const char* pathname)
{
imageDC = CreateCompatibleDC(NULL); // create an offscreen DC
imageBmp = (HBITMAP)LoadImageA( // load the bitmap from a file
NULL, // not loading from a module, so this is NULL
pathname, // the path we're loading from
IMAGE_BITMAP, // we are loading a bitmap
0, 0, // don't need to specify width/height
LR_DEFAULTSIZE | LR_LOADFROMFILE// use the default bitmap size (whatever the file is), and load it from a file
);
imageBmpOld = (HBITMAP)SelectObject(imageDC, imageBmp); // put the loaded image into our DC
}
// Function to clean up
void cleanUpImage()
{
SelectObject(imageDC, imageBmpOld); // put the old bmp back in our DC
DeleteObject(imageBmp); // delete the bmp we loaded
DeleteDC(imageDC); // delete the DC we created
}
// The function to draw our image to the display (the given DC is the screen DC)
void drawImage(HDC screen)
{
BitBlt(
screen, // tell it we want to draw to the screen
0, 0, // as position 0,0 (upper-left corner)
screenSize_X, // width of the rect to draw
screenSize_Y, // height of the rect
imageDC, // the DC to get the rect from (our image DC)
0, 0, // take it from position 0,0 in the image DC
SRCCOPY // tell it to do a pixel-by-pixel copy
);
}
// A callback to handle Windows messages as they happen
LRESULT CALLBACK wndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l)
{
// what kind of message is this?
switch (msg)
{
// we are interested in WM_PAINT, as that is how we draw
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC screen = BeginPaint(wnd, &ps); // Get the screen DC
drawImage(screen); // draw our image to our screen DC
EndPaint(wnd, &ps); // clean up
}break;
// we are also interested in the WM_DESTROY message, as that lets us know when to close the window
case WM_DESTROY:
PostQuitMessage(0);
break;
}
// for everything else, let the default window message handler do its thing
return DefWindowProc(wnd, msg, w, l);
}
// A function to create the window and get it set up
HWND createWindow(HINSTANCE inst)
{
WNDCLASSEX wc = { 0 }; // create a WNDCLASSEX struct and zero it
wc.cbSize = sizeof(WNDCLASSEX); // tell windows the size of this struct
wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); // tell it to use the normal arrow cursor for this window
wc.hInstance = inst; // give it our program instance
wc.lpfnWndProc = wndProc; // tell it to use our wndProc function to handle messages
wc.lpszClassName = TEXT("DisplayImage"); // give this window class a name.
RegisterClassEx(&wc); // register our window class with Windows
// the style of the window we want... we want a normal window but do not want it resizable.
int style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; // normal overlapped window with a caption and a system menu (the X to close)
// Figure out how big we need to make the window so that the CLIENT area (the part we will be drawing to) is
// the desired size
RECT rc = { 0,0,screenSize_X,screenSize_Y }; // desired rect
AdjustWindowRect(&rc, style, FALSE); // adjust the rect with the given style, FALSE because there is no menu
return CreateWindow( // create the window
TEXT("DisplayImage"), // the name of the window class to use for this window (the one we just registered)
TEXT("Display an Image"), // the text to appear on the title of the window
style | WS_VISIBLE, // the style of this window (OR it with WS_VISIBLE so it actually becomes visible immediately)
100, 100, // create it at position 100,100
rc.right - rc.left, // width of the window we want
rc.bottom - rc.top, // height of the window
NULL, NULL, // no parent window, no menu
inst, // our program instance
NULL); // no extra parameter
}
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// _________________________________________________________________________________________
// The actual entry point for the program!
// This is Windows' version of the 'main' function:
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show)
{
// load our image
loadImage("title.bmp");
// create our window
HWND wnd = createWindow(inst);
// Do the message pump! keep polling for messages (and respond to them)
// until the user closes the window.
MSG msg;
while (GetMessage(&msg, wnd, 0, 0)) // while we are getting non-WM_QUIT messages...
TranslateMessage(&msg); // translate them
DispatchMessage(&msg); // and dispatch them (our wndProc will process them)
{
while (running == 1) {
//Welcoming the user to the program, and asking them what they want to do (starts functions)
cin >> menuSelection;
//Selecting the introduction option
if (menuSelection == 1) {
loadImage("introduction.bmp");
cin >> userInputDummy;
menuSelection = 0;
}
//Selecting the start option
else if (menuSelection == 2) {
loadImage("start");
cin >> userInputDummy;
menuSelection = 0;
}
//Selecting the exit option
else if (menuSelection == 3) {
menuSelection = 0;
running = 0;
}
}
// once the user quits....
cleanUpImage();
return 0;
return EXIT_SUCCESS;
}
}
you cannot use cin in win32 use an editbox then get the user's input from it as character string then if you want convert it to an integer value otherwise use the API:
GetDlgItemInt(...);
you are also handling only GetMessage in while-loop while you only handle dispatchmessage outside the loop which means you handle it only once, when getmessage fails (the end of program) so the result is a freezing windows as long as there's no one who takes messages from getmessage to the target windo.
the solution: make DispatchMessage inside while loop:
another thing: you pass hwnd to getmessage the result destroying the window won't make the application exit.
take a look at GetMessage() when passing a non-null value:
link text
the correct thing in your case:
while (GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
* don't load image inside loop just load at the time wanted:
make an edit box with style ES_NUMBER and another button names for example change image so when clicked take the content of edit box convert it to integer, check whether it is 1 or 2 then load imaged depending the value.
you may ask "why I can't use iostream input and output streams in win32" because I ask you "where is console windows?" and if it is here what is the role of while-loop (blocking waiting for messages)?

SetLayeredWindowAttributes with disabled Aero

I have a program that puts a transparent window on top of the desktop where a user can do some free hand drawing with the mouse. The program works fine as long as Aero is enabled but when Aero is disabled (on Windows 7) it fails - I cannot draw and the mouse doesn't change to the mouse shape I set for the window.
The code looks like this (MFC):
//=============================================================================
// PreCreateWindow
//-----------------------------------------------------------------------------
// Public function to create the window based on global properties
//=============================================================================
BOOL CDrawWnd::PreCreateWindow(CREATESTRUCT& cs)
{
HBRUSH hBgBrush = ::CreateSolidBrush(m_crBackgroundColor);
HCURSOR hcursor = NULL;
if (m_uiCursor)
hcursor = AfxGetApp()->LoadCursor(m_uiCursor);
else if (m_Cursor)
hcursor = AfxGetApp()->LoadStandardCursor(m_Cursor); // By default IDC_CROSS
try
{
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, hcursor, hBgBrush);
}
catch(.../*CResourceException ex*/)
{
/*ex.ReportError();*/
MessageBox(_T("AfxRegisterWndClass failed"));
}
return CWnd::PreCreateWindow(cs);
}
//=============================================================================
// CreateWnd
//-----------------------------------------------------------------------------
// Public function to create the window based on global properties
//=============================================================================
bool CDrawWnd::CreateWnd()
{
CreateEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, _T("WsmLayeredWindowClass"), _T("Layered Draw Window"), WS_POPUP, m_StartWndRect, NULL, NULL, NULL);
if (m_hWnd)
{
// Make this window transparent
if (!SetLayeredWindowAttributes(m_crBackgroundColor, (255 * m_Transparency) / 100, LWA_COLORKEY))
{
TRACE(_T("\nSetLayeredWindowAttributes failed: 0x%lX"), GetLastError());
}
ShowWindow(SW_SHOW);
GetWindowRect(&m_rDrawingSurface);
return true;
}
return false;
}
CDrawWnd is derived from CWnd. CDrawWnd::CreateWnd() is called to create the window. In the case it doesn't work
SetLayeredWindowAttributes(m_crBackgroundColor, (255 * m_Transparency) / 100, LWA_COLORKEY)
fails even though GetLastError() returns 0.

Win32 Console Disable System Menu Buttons

I want to disable/grey a system menu button on the console window, particularly the minimize button. I've tried functions mentioned on another thread, but even after using them, the console window still doesn't have the minimize button grayed out. I have also looked into the DeleteMenu() function, but it doesn't seem to have the option to grey out buttons.
Here's the test code:
#include <Windows.h>
using namespace std;
int main()
{
//SetConsoleTitle(L"CPU Information");
HWND consoleWindow = GetConsoleWindow();
HMENU hMenu = GetSystemMenu(consoleWindow, FALSE);
EnableMenuItem(hMenu, SC_MINIMIZE, MF_BYCOMMAND | MF_GRAYED);
DrawMenuBar(consoleWindow);
return 0;
}
GetWindowLong + SetWindowLong FTW!
int main(int argc, _TCHAR* argv[])
{
HWND consoleWindow = GetConsoleWindow();
LONG style = GetWindowLong(consoleWindow , GWL_STYLE);
style = style & ~(WS_MINIMIZEBOX);
SetWindowLong(consoleWindow, GWL_STYLE, style);
return 0;
}
This will grey-out and disable both the minimize box in the top-right corner of the window as well as the "minimize" option from the system menu.

am trying to create class to encapsulate toolbar but the background turns black. c++ win32api

I created a simple class to hide the details of creating a toolbar in win32 API but I don't like the toolbars it is producing. (See image for clarification. I don't have reputation points so I have just posted a link)
http://i35.tinypic.com/1zmfeip.jpg
I have no idea now the black background is coming into my application.
Here is the class declaration in file CToolBar.h
#ifndef _CTOOLBAR_H
#define _CTOOLBAR_H
#include<windows.h>
#include<commctrl.h>
class CToolBar
{
public:
CToolBar();//constructor
~CToolBar();//destructor
void AddButton(int iconID, int command);//add Both a button, its icon and its command ID
void Show();//display the toolbar
void Initialise(HINSTANCE hInst, HWND hParent);
protected:
HINSTANCE m_hInst;
HWND m_hParent;
HWND m_hToolBar;
HIMAGELIST m_hImageList;
TBBUTTON m_Tbb[4]; //toolbar buttons
int m_numberButtons;
};
#endif
here is the implementation in file CToolBar.cpp
//CToolBar.cpp
#include "CToolBar.h"
#include<windows.h>
#include<commctrl.h>
CToolBar::CToolBar()//the constructor
{
m_hImageList=ImageList_Create(32, 32, ILC_COLOR32, 0, 15);//returns NULL if the function fails
//finish other initialisations
InitCommonControls();//initialise commctrl.dll whatever.. or else your toolbar wont appear
}
void CToolBar::Initialise(HINSTANCE hInst, HWND hParent)
{
m_hInst=hInst;
m_hParent=hParent;
m_hToolBar=CreateWindowEx(
WS_EX_PALETTEWINDOW ,
TOOLBARCLASSNAME,
"",
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |WS_VISIBLE|TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | CCS_TOP ,
0, 0,
0, 0,
m_hParent,
NULL,
m_hInst,
0);
}
CToolBar::~CToolBar()//destructor
{
ImageList_Destroy(m_hImageList);
}
void CToolBar::AddButton(int iconID, int command)
{
HICON hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(iconID));
ImageList_AddIcon(m_hImageList, hIcon);
DeleteObject(hIcon);
if(iconID!= -1)//-1 means the separator. The rest are mere buttons
{
m_Tbb[m_numberButtons].iBitmap =m_numberButtons;
m_Tbb[m_numberButtons].idCommand = command;
m_Tbb[m_numberButtons].fsState = TBSTATE_ENABLED;
m_Tbb[m_numberButtons].fsStyle = TBSTYLE_BUTTON;
m_Tbb[m_numberButtons].dwData = 0;
m_Tbb[m_numberButtons].iString = 0;
}
else//ie if (iconID== -1) ; then display the separator. the command value is ignored
{
m_Tbb[m_numberButtons].iBitmap =-1;
m_Tbb[m_numberButtons].idCommand = 0;
m_Tbb[m_numberButtons].fsState = TBSTATE_ENABLED;
m_Tbb[m_numberButtons].fsStyle = TBSTYLE_SEP;
m_Tbb[m_numberButtons].dwData = 0;
m_Tbb[m_numberButtons].iString = 0;
}
m_numberButtons++;
}
void CToolBar::Show()
{
SendMessage(m_hToolBar, TB_SETIMAGELIST , (WPARAM)0, (LPARAM)m_hImageList);
SendMessage(m_hToolBar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);//message for backward
//compatibility
SendMessage(m_hToolBar, TB_ADDBUTTONS, m_numberButtons, (LPARAM)m_Tbb);
SendMessage(m_hToolBar,WM_SIZE,0,0);
ShowWindow(m_hToolBar, SW_SHOW);
}
How i used the class
in main.cpp, i created a global instance of the class.
CToolBar myToolBar;
in the callback procedure, under WM_CREATE, I used some member functions.
case WM_CREATE:
myToolBar.Initialise(g_hInst,hwnd);
myToolBar.AddButton(IDI_OPEN, ID_OPEN);
myToolBar.AddButton(IDI_MAIN,ID_OPEN);//Separator button
myToolBar.AddButton(IDI_CLOSE, ID_CLOSE);
myToolBar.AddButton(IDI_CLOSEALL, ID_CLOSE);
myToolBar.Show();
break;
That's about it.
Try modifying the flags parameter of ImageList_Create to include ILC_MASK as well
Looks like you are using bitmap with transparency channel. GDI does not support alpha channel. It uses special color which will be transparent. If you want to support 32-bit bitmaps you could use GDI+ for drawing such bitmaps. Another option is to use CAplhaToolbar which already supports bitmaps with alpha transparency.