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