1 #ifdef WIN32
2 #ifdef _MSC_VER
3
4 #include <windows.h>
5 #include <stdio.h>
6 #include "DisplayDD.h"
7 #include "Log.h"
8
9 namespace DisplayOutput
10 {
11 bool m_bWaitForInputIdleDS = false;
12 CBackBufDD CDisplayDD::m_dd;
CDisplayDD()13 CDisplayDD::CDisplayDD() : CDisplayOutput()
14 {
15 m_WindowHandle = NULL;
16 m_ParentWindowHandle = NULL;
17 m_bScreensaver = false;
18 m_bWaitForInputIdleDS = false;
19 }
20
21
~CDisplayDD()22 CDisplayDD::~CDisplayDD()
23 {
24 }
25
InitDD(HWND hWnd)26 bool CDisplayDD::InitDD(HWND hWnd)
27 {
28 if (m_bFullScreen)
29 {
30 return m_dd.SetExclusive(hWnd, hWnd, true);
31 }
32 else
33 {
34 if (m_bPreview)
35 {
36 if (m_dd.Create(hWnd, m_ParentWindowHandle) == FALSE || m_dd.CreateSurface(m_Width, m_Height) == FALSE)
37 {
38 g_Log->Info(m_dd.GetLastErrorString());
39 return false;
40 }
41 }
42 else
43 if (m_dd.Create(hWnd, m_ParentWindowHandle) == FALSE || m_dd.CreateSurface(m_Width, m_Height) == FALSE)
44 {
45 g_Log->Info(m_dd.GetLastErrorString());
46 return false;
47 }
48 }
49 return true;
50 }
51
wndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)52 LRESULT CALLBACK CDisplayDD::wndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
53 {
54 PAINTSTRUCT ps;
55
56 switch( msg )
57 {
58 case WM_USER:
59 // All initialization messages have gone through. Allow 500ms of idle time, then proceed with initialization.
60 SetTimer( hWnd, 1, 500, NULL );
61 g_Log->Info( "Starting 500ms preview timer" );
62 break;
63
64 case WM_TIMER:
65 // Initial idle time is done, proceed with initialization.
66 m_bWaitForInputIdleDS = false;
67 g_Log->Info( "500ms preview timer done" );
68 KillTimer( hWnd, 1 );
69 break;
70
71 case WM_PAINT:
72 {
73 if (BeginPaint( hWnd, &ps ) != NULL)
74 EndPaint( hWnd, &ps );
75 return 0;
76 }
77
78 case WM_CLOSE:
79 DestroyWindow(hWnd);
80 break;
81
82 case WM_DESTROY:
83 m_dd.Destroy();
84 PostQuitMessage(0);
85 break;
86
87 case WM_KEYUP:
88 {
89 CKeyEvent *spEvent = new CKeyEvent();
90 spEvent->m_bPressed = true;
91
92 switch( wParam )
93 {
94 case VK_TAB: spEvent->m_Code = CKeyEvent::KEY_TAB; break;
95 case VK_LWIN: spEvent->m_Code = CKeyEvent::KEY_LALT; break;
96 case VK_MENU: spEvent->m_Code = CKeyEvent::KEY_MENU; break;
97 case VK_LEFT: spEvent->m_Code = CKeyEvent::KEY_LEFT; break;
98 case VK_RIGHT: spEvent->m_Code = CKeyEvent::KEY_RIGHT; break;
99 case VK_UP: spEvent->m_Code = CKeyEvent::KEY_UP; break;
100 case VK_DOWN: spEvent->m_Code = CKeyEvent::KEY_DOWN; break;
101 case VK_SPACE: spEvent->m_Code = CKeyEvent::KEY_SPACE; break;
102 case 0x46: spEvent->m_Code = CKeyEvent::KEY_F; break;
103 case VK_CONTROL:spEvent->m_Code = CKeyEvent::KEY_CTRL; break;
104 case VK_F1: spEvent->m_Code = CKeyEvent::KEY_F1; break;
105 case VK_F2: spEvent->m_Code = CKeyEvent::KEY_F2; break;
106 case VK_F3: spEvent->m_Code = CKeyEvent::KEY_F3; break;
107 case VK_F4: spEvent->m_Code = CKeyEvent::KEY_F4; break;
108 case VK_F8: spEvent->m_Code = CKeyEvent::KEY_F8; break;
109 case VK_ESCAPE: spEvent->m_Code = CKeyEvent::KEY_Esc; break;
110 }
111
112 spCEvent e = spEvent;
113 m_EventQueue.push( e );
114 }
115 break;
116
117 case WM_LBUTTONUP:
118 {
119 CMouseEvent *spEvent = new CMouseEvent();
120 spEvent->m_Code = CMouseEvent::Mouse_LEFT;
121 spEvent->m_X = MAKEPOINTS( lParam ).x;
122 spEvent->m_Y = MAKEPOINTS( lParam ).y;
123 spCEvent e = spEvent;
124 m_EventQueue.push( e );
125 }
126 break;
127
128 case WM_RBUTTONUP:
129 {
130 CMouseEvent *spEvent = new CMouseEvent();
131 spEvent->m_Code = CMouseEvent::Mouse_RIGHT;
132 spEvent->m_X = MAKEPOINTS( lParam ).x;
133 spEvent->m_Y = MAKEPOINTS( lParam ).y;
134 spCEvent e = spEvent;
135 m_EventQueue.push( e );
136 }
137 break;
138
139 case WM_MOUSEMOVE:
140 {
141 CMouseEvent *spEvent = new CMouseEvent();
142 spEvent->m_Code = CMouseEvent::Mouse_MOVE;
143
144 spEvent->m_X = MAKEPOINTS( lParam ).x;
145 spEvent->m_Y = MAKEPOINTS( lParam ).y;
146
147 spCEvent e = spEvent;
148 m_EventQueue.push( e );
149 }
150 break;
151
152 case WM_POWERBROADCAST:
153 switch( LOWORD( wParam ) )
154 {
155 case PBT_APMBATTERYLOW:
156 case PBT_APMSUSPEND:
157 {
158 CPowerEvent *spEvent = new CPowerEvent();
159 spCEvent e = spEvent;
160 m_EventQueue.push( e );
161 }
162 }
163 break;
164 case WM_SIZE:
165 {
166 RECT rc;
167 GetClientRect( hWnd, &rc );
168 if (!m_dd.IsExclusive())
169 m_dd.CreateSurface(rc.right - rc.left, rc.bottom - rc.top);
170 }
171 break;
172
173 default:
174 {
175 return DefWindowProc( hWnd, msg, wParam, lParam );
176 }
177 }
178 return 0;
179 }
180
181
createwindow(uint32 _w,uint32 _h,const bool _bFullscreen)182 HWND CDisplayDD::createwindow( uint32 _w, uint32 _h, const bool _bFullscreen )
183 {
184 m_bFullScreen = _bFullscreen;
185 HMODULE hInstance = GetModuleHandle(NULL);
186
187 if( _bFullscreen )
188 {
189 WNDCLASS cls = {0};
190
191 cls.hCursor = NULL;//LoadCursor( NULL, IDC_ARROW );
192 cls.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(1));
193 cls.lpszMenuName = NULL;
194 cls.lpszClassName = TEXT("ElectricsheepWndClass");
195 cls.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
196 cls.hInstance = hInstance;
197 cls.style = CS_VREDRAW | CS_HREDRAW;
198 cls.lpfnWndProc = (WNDPROC)CDisplayDD::wndProc;
199 cls.cbWndExtra = 0;
200 cls.cbClsExtra = 0;
201 RegisterClass( &cls );
202
203 RECT rc = {0};
204 DWORD dwStyle;
205
206 dwStyle = WS_VISIBLE | WS_POPUP;
207 HWND hWnd = CreateWindowEx( WS_EX_TOPMOST, L"ElectricsheepWndClass", L"Electricsheep", dwStyle, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL );
208 m_ParentWindowHandle = hWnd;
209 return hWnd;
210 }
211
212 WNDCLASS wndclass;
213 RECT windowRect;
214 SetRect( &windowRect, 0, 0, _w, _h );
215
216 ZeroMemory( &wndclass, sizeof(WNDCLASS) );
217
218 wndclass.style = CS_HREDRAW | CS_VREDRAW;
219 wndclass.lpfnWndProc = (WNDPROC)CDisplayDD::wndProc;
220 wndclass.cbClsExtra = 0;
221 wndclass.cbWndExtra = 0;
222 wndclass.hInstance = hInstance;
223 wndclass.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(1));
224 wndclass.hCursor = NULL;//LoadCursor (NULL, IDC_ARROW);
225 wndclass.hbrBackground = NULL;
226 wndclass.lpszMenuName = NULL;
227 wndclass.lpszClassName = L"ElectricsheepWndClass";
228
229 if( !RegisterClass (&wndclass) )
230 {
231 g_Log->Info("Failed to register window class");
232 return 0;
233 }
234
235 unsigned long exStyle;
236 unsigned long style;
237
238 exStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
239 style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
240
241 AdjustWindowRectEx( &windowRect, style, false, exStyle );
242 _w = windowRect.right - windowRect.left;
243 _h = windowRect.bottom - windowRect.top;
244 HWND hWnd = CreateWindowEx( exStyle, L"ElectricsheepWndClass", L"Electricsheep", style, 0, 0, _w, _h, NULL, NULL, hInstance, NULL );
245 m_ParentWindowHandle = hWnd;
246 return hWnd;
247 }
248
Initialize(HWND _hWnd,bool _bPreview)249 bool CDisplayDD::Initialize( HWND _hWnd, bool _bPreview )
250 {
251 m_bScreensaver = true;
252 m_bPreview = _bPreview;
253
254 HMODULE hInstance = GetModuleHandle( NULL );
255
256 WNDCLASS wc = {0};
257
258 wc.style = CS_VREDRAW | CS_HREDRAW;
259 wc.lpfnWndProc = (WNDPROC)CDisplayDD::wndProc;
260 wc.cbClsExtra = 0;
261 wc.cbWndExtra = 0;
262 wc.hInstance = hInstance;
263 wc.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(1));
264 wc.hCursor = NULL;
265 wc.hbrBackground = NULL;
266 wc.lpszMenuName = NULL;
267 wc.lpszClassName = L"ElectricsheepWndClass";
268 RegisterClass( &wc );
269
270 if( _bPreview )
271 {
272 RECT rc;
273 //GetWindowRect( _hWnd, &rc );
274 GetClientRect( _hWnd, &rc );
275 int32 cx = rc.right - rc.left;
276 int32 cy = rc.bottom - rc.top;
277
278 g_Log->Info( "rc: %d, %d", cx, cy );
279
280 DWORD dwStyle = WS_VISIBLE | WS_CHILD;
281 AdjustWindowRect( &rc, dwStyle, FALSE );
282 m_ParentWindowHandle = _hWnd;
283 m_WindowHandle = CreateWindow( L"ElectricsheepWndClass", L"Preview", dwStyle, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, _hWnd, NULL, hInstance, this );
284
285 if( m_WindowHandle == NULL )
286 return false;
287
288 m_Width = cx;
289 m_Height = cy;
290
291 g_Log->Info( "Screensaver preview (%dx%d)", cx, cy );
292
293 // In preview mode, "pause" (enter a limited message loop) briefly before proceeding, so the display control panel knows to update itself.
294 m_bWaitForInputIdleDS = true;
295
296 // Post a message to mark the end of the initial group of window messages
297 PostMessage( m_WindowHandle, WM_USER, 0, 0 );
298
299 InvalidateRect( GetParent( _hWnd ), NULL, FALSE ); // Invalidate the hwnd so it gets drawn
300 UpdateWindow( GetParent( _hWnd ) );
301 UpdateWindow( GetParent( _hWnd ) );
302 MSG msg;
303 while( m_bWaitForInputIdleDS )
304 {
305 if( !GetMessage( &msg, m_WindowHandle, 0, 0 ) )
306 {
307 PostQuitMessage(0);
308 break;
309 }
310
311 TranslateMessage( &msg );
312 DispatchMessage( &msg );
313 }
314 InitDD( _hWnd );
315 SetFocus( _hWnd );
316 ShowCursor( true );
317 }
318 else
319 {
320 RECT rc;
321 GetWindowRect( _hWnd, &rc );
322 m_Width = rc.right;
323 m_Height = rc.bottom;
324
325 m_WindowHandle = _hWnd;
326 m_ParentWindowHandle = _hWnd;
327 if( m_WindowHandle == NULL )
328 return false;
329
330 g_Log->Info( "Screensaver (%dx%d)", m_Width, m_Height );
331
332 // Hide cursor.
333 ShowCursor( false );
334
335 InitDD( m_WindowHandle );
336 }
337
338 return true;
339 }
340
341
Initialize(const uint32 _width,const uint32 _height,const bool _bFullscreen)342 HWND CDisplayDD::Initialize( const uint32 _width, const uint32 _height, const bool _bFullscreen )
343 {
344 m_WindowHandle = createwindow( _width, _height, _bFullscreen );
345 m_ParentWindowHandle = m_WindowHandle;
346 if( m_WindowHandle == 0 )
347 return 0;
348
349 // Show or Hide cursor.
350 ShowCursor( !_bFullscreen );
351
352 if (!_bFullscreen)
353 {
354 RECT rcClient, rcWindow;
355 POINT ptDiff;
356 GetClientRect(m_WindowHandle, &rcClient);
357 GetWindowRect(m_WindowHandle, &rcWindow);
358 ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
359 ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
360 MoveWindow(m_WindowHandle, rcWindow.left, rcWindow.top, _width + ptDiff.x, _height + ptDiff.y, TRUE);
361 }
362 // Get window dimensions.
363 RECT rect;
364 GetClientRect( m_WindowHandle, &rect );
365 m_Width = rect.right;
366 m_Height = rect.bottom;
367
368 ShowWindow( m_WindowHandle, SW_SHOW );
369 SetForegroundWindow( m_WindowHandle );
370 SetFocus( m_WindowHandle );
371
372 InitDD(m_WindowHandle);
373
374 if (m_Width == 0 && m_Height == 0)
375 {
376 m_Width = m_dd.GetSize().cx;
377 m_Height = m_dd.GetSize().cy;
378 }
379
380 return m_WindowHandle;
381 }
382
383 //
Title(const std::string & _title)384 void CDisplayDD::Title( const std::string &_title )
385 {
386 SetWindowTextA( m_WindowHandle, _title.c_str() );
387 }
388
389 //
Update()390 void CDisplayDD::Update()
391 {
392 MSG msg;
393
394 //if( m_bPreview )
395 //{
396 // //g_Log->Info( "Invalidating" );
397 // InvalidateRect( m_WindowHandle, NULL, FALSE ); // Invalidate the hwnd so it gets drawn
398 // UpdateWindow( m_WindowHandle );
399 //}
400
401 while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
402 {
403 if( GetMessage( &msg, NULL, 0, 0) <= 0 ) // error or WM_QUIT
404 {
405 m_bClosed = true;
406 return;
407 }
408
409 TranslateMessage( &msg );
410 DispatchMessage( &msg );
411 }
412 }
413
414 };
415
416 #endif
417 #endif