1 // VideoDrawer.h: interface for the CVideoDrawer class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #if !defined(AFX_VIDEODRAWER_H__A06B8DA9_C12E_49B6_B585_2152167D2E29__INCLUDED_)
6 #define AFX_VIDEODRAWER_H__A06B8DA9_C12E_49B6_B585_2152167D2E29__INCLUDED_
7
8 #if _MSC_VER > 1000
9 #pragma once
10 #endif // _MSC_VER > 1000
11
12
13 #include <windows.h>
14 #include <tchar.h>
15 #include <ddraw.h>
16
17 class CVideoDrawer
18 {
19 public:
20 CVideoDrawer();
21 virtual ~CVideoDrawer();
22
23 HRESULT Init(HWND hWnd,RECT rect);
24
25
26 HRESULT DrawFrame(BYTE *lpDataBuffer,DWORD dwSize,DWORD dwWidth,DWORD dwHeight,int bFlip);
27
28
29 HRESULT DrawText(TCHAR* strText, size_t align,COLORREF fgcolor);
30
31 HRESULT Flush();
32
33 private:
34 enum ALIGNSTYLE{
35 TOP = 0x01,
36 BOTTOM = 0x02,
37 LEFT = 0x04,
38 RIGHT = 0x08
39 };
40 LPDIRECTDRAW7 m_pDD;
41 LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer;
42 LPDIRECTDRAWSURFACE7 m_pddsBackBuffer;
43
44 HWND m_hWnd;
45 RECT m_rcWindow;
46
47 int m_dwWidth;
48 int m_dwHeight;
49 void DestroyObjects();
50 void UpdateBounds();
51
52 HRESULT CheckBackBuffer(DWORD dwWidth,DWORD dwHeight);
53 };
54
55 #endif // !defined(AFX_VIDEODRAWER_H__A06B8DA9_C12E_49B6_B585_2152167D2E29__INCLUDED_)
56
1 // VideoDrawer.cpp: implementation of the CVideoDrawer class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #include "stdafx.h"
6 #include "VideoDrawer.h"
7
8 //////////////////////////////////////////////////////////////////////
9 // Construction/Destruction
10 //////////////////////////////////////////////////////////////////////
11
12 CVideoDrawer::CVideoDrawer()
13 {
14 m_pDD = NULL;
15 m_pddsFrontBuffer = NULL;
16 m_pddsBackBuffer = NULL;
17
18 m_dwWidth = 0;
19 m_dwHeight = 0;
20 }
21
22 CVideoDrawer::~CVideoDrawer()
23 {
24 DestroyObjects();
25 }
26
27 HRESULT CVideoDrawer::Init(HWND hWnd,RECT rect)
28 {
29 HRESULT hr;
30
31 // Cleanup anything from a previous call
32 DestroyObjects();
33
34 // DDraw stuff begins here
35 if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD,
36 IID_IDirectDraw7, NULL ) ) )
37 return E_FAIL;
38
39 // Set cooperative level
40 hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL );
41 if( FAILED(hr) )
42 return E_FAIL;
43
44 DWORD dwWidth,dwHeight;
45 dwWidth = rect.right-rect.left;
46 dwHeight = rect.bottom - rect.top;
47
48 /* RECT rcWork;
49 RECT rc;
50 DWORD dwStyle;
51
52 // If we are still a WS_POPUP window we should convert to a normal app
53 // window so we look like a windows app.
54 dwStyle = GetWindowStyle( hWnd );
55 dwStyle &= ~WS_POPUP;
56 dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
57 SetWindowLong( hWnd, GWL_STYLE, dwStyle );
58
59 // Aet window size
60 SetRect( &rc, 0, 0, dwWidth, dwHeight );
61
62 AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL,
63 GetWindowExStyle(hWnd) );
64
65 SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
66 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
67
68 SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
69 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
70
71 // Make sure our window does not hang outside of the work area
72 SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
73 GetWindowRect( hWnd, &rc );
74 if( rc.left < rcWork.left ) rc.left = rcWork.left;
75 if( rc.top < rcWork.top ) rc.top = rcWork.top;
76 SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0,
77 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
78 */
79 GetWindowRect( hWnd, &m_rcWindow );
80
81 LPDIRECTDRAWCLIPPER pcClipper;
82
83 // Create the primary surface
84 DDSURFACEDESC2 ddsd;
85 ZeroMemory( &ddsd, sizeof( ddsd ) );
86 ddsd.dwSize = sizeof( ddsd );
87 ddsd.dwFlags = DDSD_CAPS;
88 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
89
90 if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
91 return E_FAIL;
92
93 if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
94 return E_FAIL;
95
96 if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ){
97 pcClipper->Release();
98 return E_FAIL;
99 }
100
101 if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) {
102 pcClipper->Release();
103 return E_FAIL;
104 }
105
106 // Done with clipper
107 pcClipper->Release();
108
109 m_hWnd = hWnd;
110 return S_OK;
111 }
112
113
114 HRESULT CVideoDrawer::DrawFrame(BYTE *lpDataBuffer,DWORD dwSize,DWORD dwWidth,DWORD dwHeight,int bFlip)
115 {
116 HDC hDC;
117 DDSURFACEDESC2 ddsd;
118 HRESULT hr;
119
120 UpdateBounds();
121
122 if(FAILED(hr = CheckBackBuffer(dwWidth,dwHeight)))
123 return hr;
124 if(NULL == m_pddsBackBuffer )
125 return E_INVALIDARG;
126
127 // Make sure this surface is restored.
128 if( FAILED( hr = m_pddsBackBuffer->Restore() ) )
129 return hr;
130
131 // Get the surface.description
132 ddsd.dwSize = sizeof(ddsd);
133 m_pddsBackBuffer->GetSurfaceDesc( &ddsd );
134
135 if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC )
136 return E_NOTIMPL;
137
138 // Stretch the bitmap to cover this surface
139 if( FAILED( hr = m_pddsBackBuffer->GetDC( &hDC ) ) )
140 return hr;
141 BITMAPINFOHEADER bminh;
142
143 bminh.biSize = sizeof(BITMAPINFOHEADER);
144 bminh.biWidth = dwWidth;
145 bminh.biHeight = dwHeight;
146 bminh.biPlanes = 1;
147
148 bminh.biBitCount = 24;
149 bminh.biCompression = BI_RGB;
150 bminh.biSizeImage = 0;
151 bminh.biXPelsPerMeter = 0;
152 bminh.biYPelsPerMeter = 0;
153 bminh.biClrUsed = 0;
154 bminh.biClrImportant = 0;
155
156
157 int iRet =GDI_ERROR;
158 if(bFlip==0)
159 {
160 iRet = StretchDIBits(hDC,
161 // destination rectangle
162 0,0,
163 dwWidth,dwHeight,
164 //0,dwHeight,
165 0,0,
166 dwWidth,
167 //-dwHeight,
168 dwHeight,
169 lpDataBuffer,
170 (LPBITMAPINFO)&bminh,
171 DIB_RGB_COLORS,
172 SRCCOPY);
173 }
174 else
175 { iRet = StretchDIBits(hDC,
176 // destination rectangle
177 0,0,
178 dwWidth,dwHeight,
179 0,dwHeight+1,
180 dwWidth,
181 -dwHeight,
182 lpDataBuffer,
183 (LPBITMAPINFO)&bminh,
184 DIB_RGB_COLORS,
185 SRCCOPY);
186 }
187
188 if (iRet == GDI_ERROR)
189 return E_FAIL;
190
191
192 if( FAILED( hr = m_pddsBackBuffer->ReleaseDC( hDC ) ) )
193 return hr;
194
195 return S_OK;
196 }
197
198
199 HRESULT CVideoDrawer::DrawText(TCHAR* strText, size_t align,COLORREF fgcolor)
200 {
201 HDC hDC = NULL;
202 HRESULT hr;
203 int x=0,y=0;
204
205 if( m_pddsBackBuffer == NULL || strText == NULL )
206 return E_INVALIDARG;
207
208 // Make sure this surface is restored.
209 if( FAILED( hr = m_pddsBackBuffer->Restore() ) )
210 return hr;
211
212 if( FAILED( hr = m_pddsBackBuffer->GetDC( &hDC ) ) )
213 return hr;
214 TEXTMETRIC tm;
215 GetTextMetrics(hDC,&tm);
216
217 int len = _tcslen(strText);
218
219 if(align & LEFT){
220 x = 0;
221 }
222 else if(align & RIGHT){
223 x = m_dwWidth-(tm.tmAveCharWidth)*(len+2);
224 }
225 if(align & TOP){
226 y = 0;
227 }
228 else if(align & BOTTOM){
229 y = m_dwHeight- tm.tmHeight;
230 }
231
232
233 // Set the background and foreground color
234 SetBkMode(hDC,TRANSPARENT);
235 SetTextColor( hDC, fgcolor );
236
237 // Use GDI to draw the text on the surface
238 TextOut( hDC, x , y, strText, len );
239
240 if( FAILED( hr = m_pddsBackBuffer->ReleaseDC( hDC ) ) )
241 return hr;
242
243 return S_OK;
244 }
245
246 HRESULT CVideoDrawer::Flush()
247 {
248 HRESULT hr;
249
250 if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer )
251 return E_POINTER;
252
253 while( 1 ) {
254 hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer,
255 NULL, DDBLT_WAIT, NULL );
256
257 if( hr == DDERR_SURFACELOST ){
258 m_pddsFrontBuffer->Restore();
259 m_pddsBackBuffer->Restore();
260 }
261
262 if( hr != DDERR_WASSTILLDRAWING )
263 return hr;
264 }
265 }
266
267 void CVideoDrawer::DestroyObjects()
268 {
269 SAFE_RELEASE( m_pddsBackBuffer );
270 SAFE_RELEASE( m_pddsFrontBuffer );
271
272 if( m_pDD )
273 m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
274
275 SAFE_RELEASE( m_pDD );
276 }
277
278 void CVideoDrawer::UpdateBounds()
279 {
280 GetClientRect( m_hWnd, &m_rcWindow );
281 ClientToScreen( m_hWnd, (POINT*)&m_rcWindow );
282 ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 );
283 }
284
285
286 HRESULT CVideoDrawer::CheckBackBuffer(DWORD dwWidth,DWORD dwHeight)
287 {
288 HRESULT hr;
289 if(m_dwWidth != dwWidth || m_dwHeight != dwHeight || NULL == m_pddsBackBuffer){
290 if(m_pddsBackBuffer){
291 SAFE_RELEASE( m_pddsBackBuffer );
292 }
293 DDSURFACEDESC2 ddsd;
294 ZeroMemory( &ddsd, sizeof( ddsd ) );
295 ddsd.dwSize = sizeof( ddsd );
296
297 // Create the backbuffer surface
298 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
299 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
300 ddsd.dwWidth = dwWidth;
301 ddsd.dwHeight = dwHeight;
302
303 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
304 return E_FAIL;
305
306 m_dwWidth = dwWidth;
307 m_dwHeight = dwHeight;
308 }
309 return S_OK;
310 }