Drawing in a Win32 Console on C++? - c++

What is the best way to draw things in the Console Window on the Win 32 platform using C++?
I know that you can draw simple art using symbols but is there a way of doing something more complex like circles or even bitmaps?

Yes, it is possible.
Get the HWND of the console window using GetConsoleWindow and then draw in it.
#define _WIN32_WINNT 0x601
#include <windows.h>
#include <stdio.h>
int main() {
// Get window handle to console, and device context
HWND console_handle = GetConsoleWindow();
HDC device_context = GetDC(console_handle);
//Here's a 5 pixels wide RED line [from initial 0,0] to 300,300
HPEN pen = CreatePen(PS_SOLID, 5, RGB(255, 0, 0));
SelectObject(device_context, pen);
LineTo(device_context, 300, 300);
ReleaseDC(console_handle, device_context);
getchar();
return 0;
}
Note: GetConsoleWindow was introduced in Windows 2000. It's available when _WIN32_WINNT is set to 0x500 or greater.

No you can't just do that because Win32 console doesn't support those methods. You can however use GDI to draw on the console window.
This is a great example of drawing a bitmap on a console by creating a child window on it:
http://www.daniweb.com/code/snippet216431.html
And this tells you how to draw lines and circles:
http://www.daniweb.com/code/snippet216430.html
This isn't really drawing in the console though. This is sort of drawing "over" the console but it still does the trick pretty well.

It is possible, albeit totally undocumented, to create a console screen buffer that uses an HBITMAP that is shared between the console window process and the calling process. This is the approach that NTVDM takes to display graphics once a DOS application switches to graphics mode.
See it.

As Nick Brooks has pointed out, you can use GDI calls in console apps, but the graphics cannot appear in the same window as the text console I/O. This may not matter since you can draw text elements in GDI.
A simplified interface to GDI calls in console apps is provided by WinBGIm. It is a clone of Borland's DOS BGI API, but with extensions to handle resizable windows, mouse input, and 24bit colour models. Since it is available as source code, it also serves a good demonstration of using GDI in this way.
It is possible to either have both a console and the GDI window, or you can suppress the console window by specifying that the application is a GUI app (the -mwindows linker option in GNU toolchain) - note that specifying a GUI app really only suppresses the console, it is only really a GUI app if it has a message loop. Having the console is good for debugging, since it is where stdout and stderr are output to by default.

Not without usng ASCII art. Back in the days of DOS it was "fairly" easy to do by redesigning the character bitmaps. It might only be possible in windows by creating your own font, but im really not sure thats possible

Related

C++ Drawing directly to the screen (like an overlay)

Many laptops nowadays have FN hot keys to change volume, brightness, etc. and usually display a visual cue that is rendered on the screen completely above the operating system. For new Windows 8/8.1 systems this visual even appears outside of the desktop in the metro side. They cannot be drawing inside of a borderless window otherwise it wouldn't show up over the metro interface.
I have tried researching whether DirectX can draw directly to the screen but it doesn't appear it can. I don't even know if I should look into OpenGL... ?
I had some success using GDI; specifically the GetDC function with the parameter NULL to grab the screen device.
#include <Windows.h>
int main() {
const HDC dc = GetDC(NULL);
while (1) {
Rectangle(dc, 100, 100, 500, 500);
}
}
However, this requires re-rendering everything repeatedly because my region of the screen can be overwritten by other windows changing in the background. And even with it re-rendering in a loop, there is massive screen flicker.
How do the OEM manufacturers of these laptops achieve this?
Thanks.
It looks like these are borderless windows.
For example, have a look at the task switcher window:
Related question:
Windows 8 Layered Windows Over Metro Apps
If you want a window on top of Metro, you need it to declare accessibility.

Drawing on the screen

I'm currently developing an application with OpenCV to do visual recognition of elements on the screen.
While a visual representation of the process is not needed, it would be very useful for debugging purposes if I could find a way to draw circles, lines and possibly text directly on the screen, without having an app window.
There are certain applications that, for instance, draw HUDs over the screen. How do they go about doing that?
I need a way for my drawing to always be at the front. In general, all the ways I managed to find involve painting on a window (WinAPI, Direct2D, OpenGL). Is there a workaround to make it appear like it's simply a layover on the desktop (including all open windows)?
for the purpose of debugging, just literally draw on the screen. IIRC GetDC(0) will get you a device context for the screen, but check out that whole family of functions. in Windows 7 it doesn't even foul up other applications' displays, and reportedly it's likewise "safe" on the mac.
for example, this draws an ellipse in the upper left of the screen:
#include <windows.h>
int main()
{
HDC const dc = GetDC( 0 );
Ellipse( dc, 10, 10, 200, 200 );
}
the graphic disappears if it's on top of a window and that window is moved.
You can achieve the device context (DC) of the screen, and draw in that DC as usual. The output will be directed to the screen. To achieve that, call WinApi GetDC("DISPLAY"), if i'm not mistaken.

C++ - How to screen-capture, except for some windows

Situation: I have a software that performs screen sharing over the Internet, where one user acts as a presenter, and other users act as viewers/attendees.
Besides the presentation windows, the presenter also has a set of NON-SHARING-WINDOWS that appear on the screen (a button bar for start sharing/stop sharing/etc., a Skype window etc.).
The presenter can configure from the setup of the screen sharing software to make these NON-SHARING-WINDOWS invisible (i.e. they will not appear in the screen sharing that is being sent to the attendees, but the window content behind them will appear in the screenshot).
The screenshots are sent at approximately 10 frames-per-second, or faster.
Question: how can I programmatically capture the screen, except for these NON-SHARING-WINDOWS windows?
Notes:
Because of the higher frames-per-second value, I cannot minimize/maximize/set alpha for these windows, because then the windows will flicker. The application is written in Win32 C++.
I would use layered windows, but because of the Windows 7 Desktop Composition feature, this is not usable out-of-the-box (and in Windows 8, you cannot use DwmEnableComposition anymore to temporarily and programmatically disable composition)
I could use the layered window approach for Windows XP/2000/7 etc., and a different approach for Windows 8 (if there is one), though I would prefer a single process that works on all systems
I could also try to "compose" the screenshots by capturing individual images (of the desktop, the windows that need to be captured) and using their z-index to create the final image, but because of the required frames-per-second value, this process would be too slow.
In windows even the desktop is considered a window and has its own HWND.
It seems however, not easily possible to only copy the "wallpaper" on its own.
So i basically see two ways to do that.
1. Copy the entire desktop e.g. BitBlt(GetWindowDC(GetDesktopWindow()),...)
OR
Use GetWindow and traverse the window list in backward direction starting from the Desktop-Window whose HWND you just can determine with GetDesktopWindow(), Like this:
// paint on a black DC
hwnd=GetDesktopWindow()
while (hwnd = GetWindow(hwnd, GW_HWNDPREV))
{
// is this window not shared? continue
// else bitblt it into our dc
}
Hope i gave some inspiration :-)
If someone knows a way how to copy ONLY the desktop without its child windows please let me know.
You can use Magnifier API.
There is a function in magnifier API that allows you to exclude specific windows from your target window (your window with 1x magnification where magnifier renders).
You can set this window to full screen and make it transparent and then use PrintWindow function.
The function: https://learn.microsoft.com/en-us/windows/desktop/api/magnification/nf-magnification-magsetwindowfilterlist
Sample projects:
https://www.codeproject.com/Articles/607288/Screenshot-using-the-Magnification-library
https://code.msdn.microsoft.com/windowsdesktop/Magnification-API-Sample-14269fd2
I'm aware this question is pretty old, but I ran into the same problem and it was very, very hard to find any information at all regarding this.
Since Windows 10 version 2004 (build 10.0.19041), the SetWindowDisplayAffinity API has been expanded to include a flag called WDA_EXCLUDEFROMCAPTURE (0x00000011). This will remove the window from images captured with BitBlt
The window is displayed only on a monitor. Everywhere else, the window does not appear at all.
One use for this affinity is for windows that show video recording controls, so that the controls are not included in the capture.
Introduced in Windows 10 Version 2004. See remarks about compatibility regarding previous versions of Windows.
For versions before 2004, it will use the existing WDA_MONITOR flag.
I have tested this with a screen capture of the desktop and I am unsure what would happen if you were to use a window DC.
So I guess a possible solution would be:
// get window handle
hWnd = (...)
BOOL result = SetWindowDisplayAffinity(m_hWnd, WDA_EXCLUDEFROMCAPTURE);
// do bitblt stuff
mabye you can use Magnification API, even Microsoft said The MagImageScalingCallback function is deprecated in Windows 7 and later, and should not be used in new applications. There is no alternate functionality., but it still work on Windows 10;
Here is the overview of this API : https://learn.microsoft.com/en-us/previous-versions/windows/desktop/magapi/magapi-intro
The sample code of Microsoft is here : https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Magnification
If you want to get the screenshot rgb data, you can use this api MagSetImageScalingCallback to set callback of Magnifier window, every time you use MagSetWindowSource or InvalidRect of magnifer window, this callback function MagImageScalingCallback will be called, so you can get screenshot rgb data here.
I think that to limit the capture content within a big window will be more simple. otherwise you will need to cut some windows from the screen capture.

How to draw to screen in c++?

How would I draw something on the screen ? not the console window but the entire screen, preferably with the console minimised.
Also, would it show up on a printscreen ?
What I want to do is create something like a layer on top of the screen that only me and my aplication are aware of yet still be able to use aplications as usual.
Here's an example:
Let's say I want 2 yellow squares 5 by 5 pixels in size appearing in the center of the screen on top of all the other applications, unclickable and invisible to a printscreen.
[Edit]
I forgot to mention that I'm using Visual Studio 2010 on Windows XP.
in windows you can use the GetDC-function.
just a minimalistic example:
#include <Windows.h>
#include <iostream>
void drawRect(){
HDC screenDC = ::GetDC(0);
::Rectangle(screenDC, 200, 200, 300, 300);
::ReleaseDC(0, screenDC);
}
int main(void){
char c;
std::cin >> c;
if (c == 'd') drawRect();
std::cin >> c;
return 0;
}
but since Windows Vista it is very slow
C++ has no notion of a "screen" and especially none of "graphics". The functionality needed is provided by your operating system. On many systems you will need a "Window" and draw on it. To do this portably, a library like Qt might help. A Windows solution was given by Oops. Maybe you want to use some OpenGL library, or Windows' DirectDraw/Direct3D from DirectX, in case you want to do some 3D stuff with your graphics.
Windows offers GDI/+, WPF, and DirectX (including Direct2D on Vista+).
The (rather nice but not recently updated) graphics library anti-grain geometry has very simple bindings to display its demos on a variety of windowing systems, you could look at those for examples. But for anything much more involved you're probably talking about operating system specific libraries.

Best Method for Minimizable Fullscreen Window

I'm coding a short game in C++ and Win32, and I want to be able to make it in fullscreen with a fixed size. I also want the user to be able to switch focus between the game window and other windows as much as he/she wants without any weird screen glitches.
So far I know of the ChangeDisplaySettings function and creating the window with the WS_POPUP style at initialization to make it fullscreen. To detect the user switching focus to other windows by way of alt+tab or otherwise, what messages should I be handling on the window's WndProc or should I be using another function? When loss of focus is detected should I only call ChangeDisplaySettings(NULL, 0); or are there other functions I should call as well? And what method should I use to handle focus back into the window?
Also can anyone give me some info on how to make it work smoothly for different screen sizes?
Thanks for any help.
If you want an exclusive full screen window, use DirectX.
But I don't recommend it. Changing the display mode causes glitches, rearranges the users icons and so on. Whether done by you, or Direct X.
Rather create a normal window at your native res, and let the user maximize it if wanted.
You could also use the GDI+ library of Windows XP (and newer) to use hardware-accelerated stretching (draw in 640x480, let GDI+ resize it to the native resolution). Then you don't need exclusive mode of DirectDraw nor ChangeDisplaySettings.
Also drawing into a 640x480 big background buffer and bit blitting it on the drawing surface via StretchBlt can be a performant solution.