📄 winvideo.h
字号:
/* Copyright 2005-2007 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Threading Building Blocks is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Threading Building Blocks; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA As a special exception, you may use this file as part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, or you compile this file and link it with other files to produce an executable, this file does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License.*//////// Common internal implementation of Windows-specific stuff //////////////#ifndef _CRT_SECURE_NO_DEPRECATE#define _CRT_SECURE_NO_DEPRECATE#endif#include "video.h"#include <fcntl.h>#include <io.h>#include <iostream>#include <fstream>#pragma comment(lib, "gdi32.lib")#pragma comment(lib, "user32.lib")// maximum mumber of lines the output console should havestatic const WORD MAX_CONSOLE_LINES = 500;const COLORREF RGBKEY = RGB(8, 8, 16); // at least 8 for 16-bit paletteHWND g_hAppWnd; // The program's window handleHANDLE g_handles[2] = {0,0};// thread and wake up eventunsigned int * g_pImg = 0; // drawing memoryint g_sizex, g_sizey;static video * g_video = 0;WNDPROC g_pUserProc = 0;HINSTANCE video::win_hInstance = 0;int video::win_iCmdShow = 0;static WNDCLASSEX * gWndClass = 0;static HACCEL hAccelTable = 0;static DWORD g_msec = 0;static int g_fps = 0, g_updates = 0, g_skips = 0;bool DisplayError(LPSTR lpstrErr, HRESULT hres = 0); // always returns falseLRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);//! Create windowbool WinInit(HINSTANCE hInstance, int nCmdShow, WNDCLASSEX *uwc, const char *title, bool fixedsize){ WNDCLASSEX wndclass; // Our app's windows class if(uwc) { memcpy(&wndclass, uwc, sizeof(wndclass)); g_pUserProc = uwc->lpfnWndProc; } else { memset(&wndclass, 0, sizeof(wndclass)); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.lpszClassName = title; } wndclass.cbSize = sizeof(wndclass); wndclass.hInstance = hInstance; wndclass.lpfnWndProc = InternalWndProc; wndclass.style |= CS_HREDRAW | CS_VREDRAW; wndclass.hbrBackground = CreateSolidBrush(RGBKEY); if( !RegisterClassExA(&wndclass) ) return false; int xaddend = GetSystemMetrics(fixedsize?SM_CXFIXEDFRAME:SM_CXFRAME)*2; int yaddend = GetSystemMetrics(fixedsize?SM_CYFIXEDFRAME:SM_CYFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); if(wndclass.lpszMenuName) yaddend += GetSystemMetrics(SM_CYMENU); // Setup the new window's physical parameters - and tell Windows to create it g_hAppWnd = CreateWindowA(wndclass.lpszClassName, // Window class name title, // Window caption !fixedsize ? WS_OVERLAPPEDWINDOW : // Window style WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, CW_USEDEFAULT, // Initial x pos: use default placement 0, // Initial y pos: not used here g_sizex+xaddend,// Initial x size g_sizey+yaddend,// Initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // Creation parameters return g_hAppWnd != NULL;}//! create console window with redirectionstatic bool RedirectIOToConsole(void){ int hConHandle; size_t lStdHandle; CONSOLE_SCREEN_BUFFER_INFO coninfo; FILE *fp; // allocate a console for this app AllocConsole(); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); coninfo.dwSize.Y = MAX_CONSOLE_LINES; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); // redirect unbuffered STDOUT to the console lStdHandle = (size_t)GetStdHandle(STD_OUTPUT_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); if(hConHandle <= 0) return false; fp = _fdopen( hConHandle, "w" ); *stdout = *fp; setvbuf( stdout, NULL, _IONBF, 0 ); // redirect unbuffered STDERR to the console lStdHandle = (size_t)GetStdHandle(STD_ERROR_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); if(hConHandle > 0) { fp = _fdopen( hConHandle, "w" ); *stderr = *fp; setvbuf( stderr, NULL, _IONBF, 0 ); } // redirect unbuffered STDIN to the console lStdHandle = (size_t)GetStdHandle(STD_INPUT_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); if(hConHandle > 0) { fp = _fdopen( hConHandle, "r" ); *stdin = *fp; setvbuf( stdin, NULL, _IONBF, 0 ); } // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog // point to console as well std::ios::sync_with_stdio(); return true;}video::video() : red_mask(0xff0000), red_shift(16), green_mask(0xff00), green_shift(8), blue_mask(0xff), blue_shift(0), depth(24){ assert(g_video == 0); g_video = this; title = "Video"; running = threaded = calc_fps = false; updating = true;}//! optionally call it just before init() to set own void video::win_set_class(WNDCLASSEX &wcex){ gWndClass = &wcex;}void video::win_load_accelerators(int idc){ hAccelTable = LoadAccelerators(win_hInstance, MAKEINTRESOURCE(idc));}bool video::init_console(){ if(RedirectIOToConsole()) { if(!g_pImg && g_sizex && g_sizey) g_pImg = new unsigned int[g_sizex * g_sizey]; if(g_pImg) running = true; return true; } return false;}video::~video(){ if(g_video) terminate();}DWORD WINAPI thread_video(LPVOID lpParameter){ video *v = (video*)lpParameter; v->on_process(); return 0;}static bool loop_once(video *v){ // screen update notify if(g_updates) { if(g_video->updating) { g_skips += g_updates-1; g_fps++; } else g_skips += g_updates; g_updates = 0; UpdateWindow(g_hAppWnd); } // update fps DWORD msec = GetTickCount(); if(v->calc_fps && msec >= g_msec+1000) { double sec = (msec - g_msec)/1000.0; char buffer[256], n = _snprintf(buffer, 128, "%s: %d fps", v->title, int(double(g_fps + g_skips)/sec)); if(g_skips) _snprintf(buffer+n, 128, " - %d skipped = %d updates", int(g_skips/sec), int(g_fps/sec)); SetWindowTextA(g_hAppWnd, buffer); g_msec = msec; g_skips = g_fps = 0; } // event processing, including painting MSG msg; if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if( msg.message == WM_QUIT ) { v->running = false; return false; } if( !hAccelTable || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return true; // try again } return false;}//! Do standart event loopvoid video::main_loop(){ // let Windows draw and unroll the window InvalidateRect(g_hAppWnd, 0, false); g_msec = GetTickCount(); // let's stay for 0,5 sec while(g_msec + 500 > GetTickCount()) { loop_once(this); Sleep(1); } g_msec = GetTickCount(); // now, start main process if(threaded) { g_handles[0] = CreateThread ( NULL, // LPSECURITY_ATTRIBUTES security_attrs 0, // SIZE_T stacksize (LPTHREAD_START_ROUTINE) thread_video, this, // argument 0, 0); if(!g_handles[0]) { DisplayError("Can't create thread"); return; } else g_handles[1] = CreateEvent(NULL, false, false, NULL); while(running) { while(loop_once(this)); Sleep(0); // give time for processing when running on single CPU DWORD r = MsgWaitForMultipleObjects(2, g_handles, false, INFINITE, QS_ALLINPUT^QS_MOUSEMOVE); if(r == WAIT_OBJECT_0) break; // thread terminated } running = false; if(WaitForSingleObject(g_handles[0], 300) == WAIT_TIMEOUT) TerminateThread(g_handles[0], 0); if(g_handles[0]) CloseHandle(g_handles[0]); if(g_handles[1]) CloseHandle(g_handles[1]); g_handles[0] = g_handles[1] = 0; } else on_process();}//! Refresh screen picturebool video::next_frame(){ if(!running) return false; g_updates++; if(!threaded) while(loop_once(this)); else if(g_handles[1]) { SetEvent(g_handles[1]); Sleep(0); } return true;}//! Change window titlevoid video::show_title(){ if(g_hAppWnd) SetWindowTextA(g_hAppWnd, title);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -