Last active
June 9, 2024 20:46
-
-
Save daaximus/a402fad67aca8339f7cc743cd55b7c27 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <gdiplus.h> | |
#include <string> | |
#include <iostream> | |
#include <fstream> | |
using namespace Gdiplus; | |
#pragma comment (lib,"Gdiplus.lib") | |
int get_encoder_clsid( const WCHAR* format, CLSID* clsid ) | |
{ | |
UINT num_encoders = 0; | |
UINT size_encoders = 0; | |
ImageCodecInfo* codec_info = nullptr; | |
GetImageEncodersSize( &num_encoders, &size_encoders ); | |
if ( size_encoders == 0 ) return -1; | |
codec_info = static_cast< ImageCodecInfo* >( malloc( size_encoders ) ); | |
if ( codec_info == nullptr ) return -1; | |
GetImageEncoders( num_encoders, size_encoders, codec_info ); | |
for ( UINT it = 0; it < num_encoders; ++it ) | |
{ | |
if ( wcscmp( codec_info[ it ].MimeType, format ) == 0 ) | |
{ | |
*clsid = codec_info[ it ].Clsid; | |
free( codec_info ); | |
return it; | |
} | |
} | |
free( codec_info ); | |
return -1; | |
} | |
void capture_screenshot( const std::wstring& filename, HWND hwnd ) | |
{ | |
GdiplusStartupInput gdipsi; | |
ULONG_PTR token; | |
GdiplusStartup( &token, &gdipsi, nullptr ); | |
const HDC hdc_screen = GetDC( nullptr ); | |
const HDC hdc_capture = CreateCompatibleDC( hdc_screen ); | |
int left = GetSystemMetrics( SM_XVIRTUALSCREEN ); | |
int top = GetSystemMetrics( SM_YVIRTUALSCREEN ); | |
int width = GetSystemMetrics( SM_CXVIRTUALSCREEN ); | |
int height = GetSystemMetrics( SM_CYVIRTUALSCREEN ); | |
if ( hwnd != nullptr ) | |
{ | |
RECT window_rect; | |
GetWindowRect( hwnd, &window_rect ); | |
left = window_rect.left; | |
top = window_rect.top; | |
width = window_rect.right - window_rect.left; | |
height = window_rect.bottom - window_rect.top; | |
} | |
const HBITMAP hbm = CreateCompatibleBitmap( hdc_screen, width, height ); | |
SelectObject( hdc_capture, hbm ); | |
BitBlt( hdc_capture, 0, 0, width, height, hdc_screen, left, top, SRCCOPY ); | |
Bitmap* bitmap = Bitmap::FromHBITMAP( hbm, nullptr ); | |
CLSID png_clsid; | |
get_encoder_clsid( L"image/png", &png_clsid ); | |
bitmap->Save( filename.c_str(), &png_clsid, nullptr ); | |
delete bitmap; | |
DeleteObject( hbm ); | |
DeleteDC( hdc_capture ); | |
ReleaseDC( nullptr, hdc_screen ); | |
GdiplusShutdown( token ); | |
} | |
HWND main_window = nullptr; | |
LRESULT CALLBACK window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam ) | |
{ | |
switch ( message ) | |
{ | |
case WM_DESTROY: | |
PostQuitMessage( 0 ); | |
return 0; | |
case WM_ACTIVATE: | |
if ( wparam == WA_INACTIVE ) | |
{ | |
ShowWindow( hwnd, SW_MINIMIZE ); | |
return 0; | |
} | |
break; | |
case WM_KEYDOWN: | |
switch ( wparam ) | |
{ | |
case VK_TAB: | |
if ( ( GetKeyState( VK_MENU ) & 0x1 ) != 0 ) | |
ShowWindow( hwnd, SW_MINIMIZE ); | |
return 0; | |
case VK_LWIN: | |
case VK_RWIN: | |
ShowWindow( hwnd, SW_MINIMIZE ); | |
return 0; | |
case VK_ESCAPE: | |
PostQuitMessage( 0 ); | |
return 0; | |
default: break; | |
} | |
break; | |
default: break; | |
} | |
return DefWindowProc( hwnd, message, wparam, lparam ); | |
} | |
void capture_gamers() | |
{ | |
HWND backup_hwnd = main_window; | |
// gamer vision brrrrrrrr... | |
for ( auto n = 0; ; n++ ) | |
{ | |
if ( GetAsyncKeyState( VK_F1 ) & 0x1 ) | |
{ | |
if ( main_window ) | |
main_window = nullptr; | |
else | |
main_window = backup_hwnd; | |
} | |
std::wstring filename = L"ss_" + std::to_wstring( n ) + L".png"; | |
capture_screenshot( filename, main_window ); | |
Sleep( 1000 ); | |
} | |
} | |
// While window is active, screenshots capture the client window. If you alt-tab, it will not capture the window and results in | |
// a single null box. In this junk, if the window handle becomes invalid, it will screenshot the entire screen (press F1 and | |
// review the screenshots). | |
// | |
int WINAPI WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmd_line, int cmd_show ) | |
{ | |
WNDCLASSEX wcex; | |
wcex.cbSize = sizeof( WNDCLASSEX ); | |
wcex.style = CS_HREDRAW | CS_VREDRAW; | |
wcex.lpfnWndProc = window_proc; | |
wcex.cbClsExtra = 0; | |
wcex.cbWndExtra = 0; | |
wcex.hInstance = instance; | |
wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION ); | |
wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); | |
wcex.hbrBackground = HBRUSH( COLOR_WINDOW + 1 ); | |
wcex.lpszMenuName = NULL; | |
wcex.lpszClassName = L"OhNoScreenshots"; | |
wcex.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); | |
RegisterClassEx( &wcex ); | |
main_window = CreateWindowEx( | |
0, | |
L"OhNoScreenshots", | |
L"FairFight Never Did This! /s", | |
WS_POPUP | WS_VISIBLE, | |
0, 0, | |
GetSystemMetrics( SM_CXSCREEN ), | |
GetSystemMetrics( SM_CYSCREEN ), | |
nullptr, nullptr, | |
instance, nullptr ); | |
ShowWindow( main_window, cmd_show ); | |
UpdateWindow( main_window ); | |
CreateThread( nullptr, 0, reinterpret_cast< LPTHREAD_START_ROUTINE >( capture_gamers ), nullptr, 0, nullptr ); | |
MSG msg; | |
while ( GetMessage( &msg, nullptr, 0, 0 ) ) | |
{ | |
TranslateMessage( &msg ); | |
DispatchMessage( &msg ); | |
} | |
return int( msg.wParam ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment