xref: /oneTBB/examples/common/gui/gdivideo.cpp (revision c21e688a)
1d86ed7fbStbbdev /*
2*c21e688aSSergey Zheltov     Copyright (c) 2005-2022 Intel Corporation
3d86ed7fbStbbdev 
4d86ed7fbStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
5d86ed7fbStbbdev     you may not use this file except in compliance with the License.
6d86ed7fbStbbdev     You may obtain a copy of the License at
7d86ed7fbStbbdev 
8d86ed7fbStbbdev         http://www.apache.org/licenses/LICENSE-2.0
9d86ed7fbStbbdev 
10d86ed7fbStbbdev     Unless required by applicable law or agreed to in writing, software
11d86ed7fbStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
12d86ed7fbStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d86ed7fbStbbdev     See the License for the specific language governing permissions and
14d86ed7fbStbbdev     limitations under the License.
15d86ed7fbStbbdev */
16d86ed7fbStbbdev 
17d86ed7fbStbbdev // common Windows parts
18d86ed7fbStbbdev #include "winvideo.hpp"
19d86ed7fbStbbdev // include GDI+ headers
20d86ed7fbStbbdev #include <gdiplus.h>
21d86ed7fbStbbdev // and another headers
22d86ed7fbStbbdev #include <stdio.h>
23d86ed7fbStbbdev 
24d86ed7fbStbbdev // tag linking library
25d86ed7fbStbbdev #pragma comment(lib, "gdiplus.lib")
26d86ed7fbStbbdev 
27d86ed7fbStbbdev // global specific variables
28d86ed7fbStbbdev Gdiplus::Bitmap* g_pBitmap; // main drawing bitmap
29d86ed7fbStbbdev ULONG_PTR gdiplusToken;
30d86ed7fbStbbdev Gdiplus::GdiplusStartupInput gdiplusStartupInput; // GDI+
31d86ed7fbStbbdev 
32d86ed7fbStbbdev //! display system error
DisplayError(LPSTR lpstrErr,HRESULT hres)33d86ed7fbStbbdev bool DisplayError(LPSTR lpstrErr, HRESULT hres) {
34d86ed7fbStbbdev     static bool InError = false;
35d86ed7fbStbbdev     int retval = 0;
36d86ed7fbStbbdev     if (!InError) {
37d86ed7fbStbbdev         InError = true;
38d86ed7fbStbbdev         LPCSTR lpMsgBuf;
39d86ed7fbStbbdev         if (!hres)
40d86ed7fbStbbdev             hres = GetLastError();
41d86ed7fbStbbdev         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
42d86ed7fbStbbdev                           FORMAT_MESSAGE_IGNORE_INSERTS,
4357f524caSIlya Isaev                       nullptr,
44d86ed7fbStbbdev                       hres,
45d86ed7fbStbbdev                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
46d86ed7fbStbbdev                       (LPTSTR)&lpMsgBuf,
47d86ed7fbStbbdev                       0,
4857f524caSIlya Isaev                       nullptr);
49d86ed7fbStbbdev         retval = MessageBox(g_hAppWnd, lpstrErr, lpMsgBuf, MB_OK | MB_ICONERROR);
50d86ed7fbStbbdev         LocalFree((HLOCAL)lpMsgBuf);
51d86ed7fbStbbdev         InError = false;
52d86ed7fbStbbdev     }
53d86ed7fbStbbdev     return false;
54d86ed7fbStbbdev }
55d86ed7fbStbbdev 
56d86ed7fbStbbdev //! Win event processing function
InternalWndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)57d86ed7fbStbbdev LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
58d86ed7fbStbbdev     switch (iMsg) {
59d86ed7fbStbbdev         case WM_MOVE:
60d86ed7fbStbbdev             // Check to make sure our window exists before we tell it to repaint.
61d86ed7fbStbbdev             // This will fail the first time (while the window is being created).
62d86ed7fbStbbdev             if (hwnd) {
6357f524caSIlya Isaev                 InvalidateRect(hwnd, nullptr, FALSE);
64d86ed7fbStbbdev                 UpdateWindow(hwnd);
65d86ed7fbStbbdev             }
66d86ed7fbStbbdev             return 0L;
67d86ed7fbStbbdev 
68d86ed7fbStbbdev         case WM_PAINT: {
69d86ed7fbStbbdev             PAINTSTRUCT ps;
70d86ed7fbStbbdev             Gdiplus::Graphics graphics(BeginPaint(hwnd, &ps));
71d86ed7fbStbbdev             // redraw just requested area. This call is as fast as simple DrawImage() call.
72d86ed7fbStbbdev             if (g_video->updating)
73d86ed7fbStbbdev                 graphics.DrawImage(g_pBitmap,
74d86ed7fbStbbdev                                    ps.rcPaint.left,
75d86ed7fbStbbdev                                    ps.rcPaint.top,
76d86ed7fbStbbdev                                    ps.rcPaint.left,
77d86ed7fbStbbdev                                    ps.rcPaint.top,
78d86ed7fbStbbdev                                    ps.rcPaint.right,
79d86ed7fbStbbdev                                    ps.rcPaint.bottom,
80d86ed7fbStbbdev                                    Gdiplus::UnitPixel);
81d86ed7fbStbbdev             EndPaint(hwnd, &ps);
82d86ed7fbStbbdev         }
83d86ed7fbStbbdev             return 0L;
84d86ed7fbStbbdev 
85d86ed7fbStbbdev         // Process all mouse and keyboard events
86d86ed7fbStbbdev         case WM_LBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 1); break;
87d86ed7fbStbbdev         case WM_LBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -1); break;
88d86ed7fbStbbdev         case WM_RBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 2); break;
89d86ed7fbStbbdev         case WM_RBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -2); break;
90d86ed7fbStbbdev         case WM_MBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 3); break;
91d86ed7fbStbbdev         case WM_MBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -3); break;
92d86ed7fbStbbdev         case WM_CHAR: g_video->on_key((int)wParam); break;
93d86ed7fbStbbdev 
94d86ed7fbStbbdev         // some useless stuff
95d86ed7fbStbbdev         case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop
96d86ed7fbStbbdev         case WM_DISPLAYCHANGE: return 0;
97d86ed7fbStbbdev 
98d86ed7fbStbbdev         // Now, shut down the window...
99d86ed7fbStbbdev         case WM_DESTROY: PostQuitMessage(0); return 0;
100d86ed7fbStbbdev     }
101d86ed7fbStbbdev     // call user defined proc, if exists
102d86ed7fbStbbdev     return g_pUserProc ? g_pUserProc(hwnd, iMsg, wParam, lParam)
103d86ed7fbStbbdev                        : DefWindowProc(hwnd, iMsg, wParam, lParam);
104d86ed7fbStbbdev }
105d86ed7fbStbbdev 
106d86ed7fbStbbdev ///////////// video functions ////////////////
107d86ed7fbStbbdev 
init_window(int sizex,int sizey)108d86ed7fbStbbdev bool video::init_window(int sizex, int sizey) {
109d86ed7fbStbbdev     assert(win_hInstance != 0);
110d86ed7fbStbbdev     g_sizex = sizex;
111d86ed7fbStbbdev     g_sizey = sizey;
112d86ed7fbStbbdev     if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, true)) {
113d86ed7fbStbbdev         DisplayError("Unable to initialize the program's window.");
114d86ed7fbStbbdev         return false;
115d86ed7fbStbbdev     }
116d86ed7fbStbbdev     ShowWindow(g_hAppWnd, SW_SHOW);
11757f524caSIlya Isaev     Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
118d86ed7fbStbbdev     g_pImg = new unsigned int[sizex * sizey];
119d86ed7fbStbbdev     g_pBitmap =
120d86ed7fbStbbdev         new Gdiplus::Bitmap(g_sizex, g_sizey, 4 * g_sizex, PixelFormat32bppRGB, (BYTE*)g_pImg);
121d86ed7fbStbbdev     running = true;
122d86ed7fbStbbdev     return true;
123d86ed7fbStbbdev }
124d86ed7fbStbbdev 
terminate()125d86ed7fbStbbdev void video::terminate() {
126d86ed7fbStbbdev     delete g_pBitmap;
12757f524caSIlya Isaev     g_pBitmap = nullptr;
128ba947f18SIlya Isaev 
129d86ed7fbStbbdev     Gdiplus::GdiplusShutdown(gdiplusToken);
13057f524caSIlya Isaev     g_video = nullptr;
131d86ed7fbStbbdev     running = false;
132ba947f18SIlya Isaev 
133d86ed7fbStbbdev     delete[] g_pImg;
13457f524caSIlya Isaev     g_pImg = nullptr;
135d86ed7fbStbbdev }
136d86ed7fbStbbdev 
137d86ed7fbStbbdev //////////// drawing area constructor & destructor /////////////
138d86ed7fbStbbdev 
drawing_area(int x,int y,int sizex,int sizey)139d86ed7fbStbbdev drawing_area::drawing_area(int x, int y, int sizex, int sizey)
140d86ed7fbStbbdev         : base_index(y * g_sizex + x),
141d86ed7fbStbbdev           max_index(g_sizex * g_sizey),
142d86ed7fbStbbdev           index_stride(g_sizex),
143d86ed7fbStbbdev           pixel_depth(24),
144d86ed7fbStbbdev           ptr32(g_pImg),
145d86ed7fbStbbdev           start_x(x),
146d86ed7fbStbbdev           start_y(y),
147d86ed7fbStbbdev           size_x(sizex),
148d86ed7fbStbbdev           size_y(sizey) {
149d86ed7fbStbbdev     assert(x < g_sizex);
150d86ed7fbStbbdev     assert(y < g_sizey);
151d86ed7fbStbbdev     assert(x + sizex <= g_sizex);
152d86ed7fbStbbdev     assert(y + sizey <= g_sizey);
153d86ed7fbStbbdev 
154d86ed7fbStbbdev     index = base_index; // current index
155d86ed7fbStbbdev }
156d86ed7fbStbbdev 
update()157d86ed7fbStbbdev void drawing_area::update() {
158d86ed7fbStbbdev     if (g_video->updating) {
159d86ed7fbStbbdev         RECT r;
160d86ed7fbStbbdev         r.left = start_x;
161d86ed7fbStbbdev         r.right = start_x + size_x;
162d86ed7fbStbbdev         r.top = start_y;
163d86ed7fbStbbdev         r.bottom = start_y + size_y;
164d86ed7fbStbbdev         InvalidateRect(g_hAppWnd, &r, false);
165d86ed7fbStbbdev     }
166d86ed7fbStbbdev }
167