WinCE Overlay - 示例:mosquito

在代码中增加了很多对代码的注释。

同时,对在不同平台(Telechips,MStar)的测试效果也做了说明。

虽然代码是 Overlay 示例,但还是增加了一些东东,如注释或者说明,对 Overlay 有兴趣的童鞋可以看看。  

  1 // mosquito.cpp : Defines the entry point for the application.  
  2 //  
  3   
  4 #include "stdafx.h"  
  5 #include <windows.h>  
  6 #include <commctrl.h>  
  7 #include "Resource.h"  
  8 //-----------------------------------------------------------------------------  
  9 // Include files  
 10 //-----------------------------------------------------------------------------  
 11 #include <ddraw.h>  
 12   
 13 //-----------------------------------------------------------------------------  
 14 // Local definitions  
 15 //-----------------------------------------------------------------------------  
 16 #define NAME                TEXT("MosquitoWndClass")  
 17 #define TITLE               TEXT("Mosquito")  
 18   
 19 #define BUG_WIDTH           320  
 20 #define BUG_HEIGHT          200  
 21   
 22 #ifdef UNDER_CE  
 23 #define RAND_INT(x) (Random() % x)  
 24 #else  
 25 #define RAND_INT(x) (rand()*x/RAND_MAX)  
 26 #endif  
 27 #define RANDOM_VELOCITY() (int)(((RAND_INT(5)+3)*2))  
 28   
 29 //-----------------------------------------------------------------------------  
 30 // Default settings  
 31 //-----------------------------------------------------------------------------  
 32 #define TIMER_ID            1  
 33 #define TIMER_RATE          200  
 34   
 35 //-----------------------------------------------------------------------------  
 36 // Global data  
 37 //-----------------------------------------------------------------------------  
 38 LPDIRECTDRAW                g_pDD = NULL;        // DirectDraw object  
 39 LPDIRECTDRAWSURFACE         g_pDDSPrimary = NULL; // Primary Surface.  
 40 LPDIRECTDRAWSURFACE         g_pDDSOverlay = NULL; // The overlay primary.  
 41 BOOL                        g_bActive = FALSE;   // Is application active?  
 42 int                         g_RotationAngles = 0; // Supported rotation angles.  
 43 int                         g_CurrentAngle = 0;   // Current rotation angle.  
 44   
 45 // Overlay position and velocity data.  
 46   
 47 int g_nOverlayXPos, g_nOverlayYPos;  
 48 int g_nOverlayXVel, g_nOverlayYVel;  
 49 int g_nOverlayWidth, g_nOverlayHeight;  
 50 DWORD g_dwOverlayXPositionAlignment;  
 51   
 52 // Our instance handle.  
 53   
 54 HINSTANCE g_hInstance;  
 55   
 56 //-----------------------------------------------------------------------------  
 57 // Local data  
 58 //-----------------------------------------------------------------------------  
 59 static TCHAR                szImg1[] = TEXT("IDB_BUGIMAGE1");//TEXT("IDB_BUGIMAGE1");  
 60 static TCHAR                szImg2[] = TEXT("IDB_BUGIMAGE2");  
 61 static TCHAR                szImg3[] = TEXT("IDB_BUGIMAGE3");  
 62   
 63 // These are the pixel formats this app supports.  Most display adapters  
 64 // with overlay support will recognize one or more of these formats.  
 65 // We start with YUV format, then work down to RGB. (All 16 bpp.)  
 66   
 67 /* 
 68  * Telechips 8902 支持 2 层 overlay 
 69  * 只能创建一层 YUV 的 overlay (可以再创建一层 RGB overlay) 
 70  * RGB 模式可以创建多个,模式与顺序没有不影响创建 
 71 */  
 72 static DDPIXELFORMAT ddpfOverlayFormats[] = {  
 73     //{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','U','Y','V'),0,0,0,0,0},  // YUYV - Leo.Zheng Telechips 8902 可以支持  
 74     //{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0},  // UYVY - Leo.Zheng Telechips 8902:Create No.1 surface return: 0x88760218  
 75     // {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16,  0x7C00, 0x03e0, 0x001F, 0},        // 16-bit RGB 5:5:5  
 76     {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16,  0xF800, 0x07e0, 0x001F, 0},        // 16-bit RGB 5:6:5  
 77 };  
 78   
 79 #define PF_TABLE_SIZE (sizeof(ddpfOverlayFormats) / sizeof(ddpfOverlayFormats[0]))  
 80   
 81 static RECT rs;  
 82 static RECT rd;  
 83   
 84 //-----------------------------------------------------------------------------  
 85 // Prototypes  
 86 //-----------------------------------------------------------------------------  
 87 void ReleaseAllObjects(void);  
 88 HRESULT InitFail(HWND, HRESULT, LPCTSTR, ...);  
 89 HRESULT RestoreAllSurfaces();  
 90 void MoveOverlay();  
 91 long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM);  
 92 BOOL CopyBitmapToYUVSurface(LPDIRECTDRAWSURFACE, HBITMAP);  
 93 BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE, UINT);  
 94 HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);  
 95 HRESULT LoadBugImages();  
 96 HRESULT InitApp(HINSTANCE hInstance, int nCmdShow);  
 97   
 98 //-----------------------------------------------------------------------------  
 99 // Name: ReleaseAllObjects()  
100 // Desc: Finished with all objects we use; release them  
101 //-----------------------------------------------------------------------------  
102 static void ReleaseAllObjects(void)  
103 {  
104     if(g_pDDSOverlay != NULL)  
105     {  
106                 // 如果不再需要一个覆盖表面或只想不让覆盖可见, 就可以设定适当的标志调用 UpdateOverlay 方法来隐藏该覆盖表面  
107         // Use UpdateOverlay() with the DDOVER_HIDE flag to remove an overlay from the display.  
108             // g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL);  
109         g_pDDSOverlay->Release();  
110         g_pDDSOverlay = NULL;  
111     }  
112   
113     if(g_pDDSPrimary != NULL)  
114     {  
115         g_pDDSPrimary->Release();  
116         g_pDDSPrimary = NULL;  
117     }  
118   
119     if(g_pDD != NULL)  
120     {  
121         g_pDD->Release();  
122         g_pDD = NULL;  
123     }  
124 }  
125   
126 //-----------------------------------------------------------------------------  
127 // Name: InitFail()  
128 // Desc: This function is called if an initialization function fails  
129 //-----------------------------------------------------------------------------  
130 #define PREFIX      TEXT("MOSQUITO: ")  
131 #define PREFIX_LEN  10  
132   
133 static HRESULT InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)  
134 {  
135     TCHAR szBuff[128] = PREFIX;  
136     va_list vl;  
137   
138     va_start(vl, szError);  
139     StringCchVPrintf(szBuff + PREFIX_LEN, (128-PREFIX_LEN), szError, vl);      
140     size_t len = wcslen(szBuff);  
141     StringCchPrintf(szBuff + len, 128 - len, TEXT("\r\n"));  
142     ReleaseAllObjects();  
143     OutputDebugString(szBuff);  
144     DestroyWindow(hWnd);  
145     va_end(vl);  
146     return hRet;  
147 }  
148   
149 #undef PREFIX_LEN  
150 #undef PREFIX  
151   
152 //-----------------------------------------------------------------------------  
153 // Name: RestoreAllSurfaces  
154 // Desc: Called in case we lose our surface's vram.  
155 //-----------------------------------------------------------------------------  
156 static HRESULT RestoreAllSurfaces()  
157 {  
158     HRESULT hRet = 0;  
159   
160     // Try Restoring the primary surface.  
161     hRet = g_pDDSPrimary->Restore();  
162     if(hRet != DD_OK)  
163             return hRet;  
164   
165     // Try Restoring the overlay surface.  
166     hRet = g_pDDSOverlay->Restore();  
167     if(hRet != DD_OK)  
168             return hRet;  
169   
170     // Reload the images.  
171     hRet = LoadBugImages();  
172     if(hRet != DD_OK)  
173         return hRet;  
174   
175     // Show the overlay.  
176     hRet = g_pDDSOverlay->UpdateOverlay(&rs, g_pDDSPrimary, &rd, DDOVER_SHOW, NULL);  
177   
178     return hRet;  
179 }  
180   
181 //-----------------------------------------------------------------------------  
182 // Name: MoveOverlay()  
183 // Desc: Called on the timer, this function moves the overlay around the  
184 //       screen, periodically calling flip to animate the mosquito.  
185 //-----------------------------------------------------------------------------  
186 static void MoveOverlay()  
187 {  
188     HRESULT hRet = 0;  
189     DWORD dwXAligned = 0;  
190   
191     // Add the current velocity vectors to the position.  
192     g_nOverlayXPos += g_nOverlayXVel;  
193     g_nOverlayYPos += g_nOverlayYVel;  
194   
195     // Check to see if this new position puts the overlay off the edge of the screen.  
196     // SetOverlayPosition() won't like that.  
197     // Have we gone off the left edge?  
198     if(g_nOverlayXPos < 0)  
199         {  
200            g_nOverlayXPos = 0;  
201            g_nOverlayXVel = RANDOM_VELOCITY();  
202     }  
203   
204     // Have we gone off the right edge?  
205   
206     if((g_nOverlayXPos + g_nOverlayWidth) > GetSystemMetrics(SM_CXSCREEN))  
207         {  
208            g_nOverlayXPos = GetSystemMetrics(SM_CXSCREEN) - g_nOverlayWidth;  
209            g_nOverlayXVel = -RANDOM_VELOCITY();  
210     }  
211   
212     // Have we gone off the top edge?  
213     if(g_nOverlayYPos < 0)  
214         {  
215            g_nOverlayYPos = 0;  
216            g_nOverlayYVel = RANDOM_VELOCITY();  
217     }  
218   
219     // Have we gone off the bottom edge?  
220     if((g_nOverlayYPos + g_nOverlayHeight) > GetSystemMetrics(SM_CYSCREEN))  
221         {  
222            g_nOverlayYPos = GetSystemMetrics(SM_CYSCREEN) - g_nOverlayHeight;  
223            g_nOverlayYVel = -RANDOM_VELOCITY();  
224     }  
225   
226     // We need to check for any alignment restrictions on the X position.  
227     if(g_dwOverlayXPositionAlignment)  
228            dwXAligned = g_nOverlayXPos - g_nOverlayXPos % g_dwOverlayXPositionAlignment;  
229     else  
230            dwXAligned = g_nOverlayXPos;  
231   
232     // Set the overlay to it's new position. 重新放置覆盖  
233     hRet = g_pDDSOverlay->SetOverlayPosition(dwXAligned, g_nOverlayYPos);  
234     if(hRet == DDERR_SURFACELOST)  
235     {  
236             if(FAILED(RestoreAllSurfaces()))   
237                 return;  
238     }  
239   
240         // 注意, 不要使用太靠近目标表面的右/下边界的坐标. 因为 SetOverlayPosition 方法并不执行剪切功能,  
241         // 所以使用那些可能导致覆盖超出目标表面边界的坐标会引起调用的失败, 并返回 DDERR_INVALIDPOSITION.  
242   
243     // Flip.  
244     while(TRUE)  
245     {  
246         hRet = g_pDDSOverlay->Flip(NULL, 0);  
247         if(hRet == DD_OK)  
248             break;  
249         if(hRet == DDERR_SURFACELOST)           // 正常情况下,不执行此 if 语句  
250         {  
251             hRet = RestoreAllSurfaces();  
252             if(hRet != DD_OK)  
253                 break;  
254         }  
255         if(hRet != DDERR_WASSTILLDRAWING)  
256             break;  
257     }  
258 }  
259   
260   
261 //-----------------------------------------------------------------------------  
262 // Name: WindowProc()  
263 // Desc: The Main Window Procedure  
264 //-----------------------------------------------------------------------------  
265 long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
266 {  
267     int                         NewAngle;  
268     DEVMODE                     DevMode;  
269   
270     switch (message)  
271     {  
272 #ifdef UNDER_CE  
273         case WM_ACTIVATE:  
274 #else  
275         case WM_ACTIVATEAPP:  
276 #endif  
277             // Pause if minimized or not the top window  
278             g_bActive = (wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE);  
279             return 0L;  
280   
281         case WM_KILLFOCUS:  
282             // We do not allow anyone else to have the keyboard focus until  
283             // we are done.  
284             SetFocus(hWnd);  
285             return 0L;  
286   
287         case WM_DESTROY:  
288             // Clean up and close the app  
289                         RETAILMSG(1,(L"[mosquito]overlay test - release overlay objects.\r\n"));  
290             ReleaseAllObjects();  
291             PostQuitMessage(0);  
292                         return 0L;  
293   
294                 case WM_LBUTTONDOWN:            // Leo.Zheng 没有窗体,无法响应 MOUSE 消息  
295                         PostMessage(hWnd, WM_CLOSE, 0, 0);  
296                         break;  
297   
298         case WM_KEYDOWN:  
299             // Handle any non-accelerated key commands  
300             switch (wParam)  
301             {  
302                 case VK_ESCAPE:  
303                 case VK_F12:  
304                     PostMessage(hWnd, WM_CLOSE, 0, 0);  
305                     return 0L;  
306   
307                 case VK_SPACE:  
308                     // Rotate to the "next" angle.  
309                     if (g_CurrentAngle >= 0 && g_RotationAngles >= 0)  
310                                         {  
311                         NewAngle = g_CurrentAngle;  
312                         do  
313                         {  
314                             NewAngle <<= 1;  
315                             if (NewAngle == DMDO_0)  
316                             {  
317                                 NewAngle = DMDO_90;  
318                             }  
319                             if (NewAngle > DMDO_270)  
320                             {  
321                                 NewAngle = DMDO_0;  
322                             }  
323                         }while (!(NewAngle & g_RotationAngles) && (NewAngle != DMDO_0));  
324   
325                         memset(&DevMode, 0, sizeof (DevMode));  
326                         DevMode.dmSize = sizeof (DevMode);  
327                         DevMode.dmFields = DM_DISPLAYORIENTATION;  
328                         DevMode.dmDisplayOrientation = NewAngle;  
329   
330                         if (DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_RESET, NULL))  
331                                                 {  
332                             g_CurrentAngle = NewAngle;  
333                                                         RestoreAllSurfaces();  
334                         }  
335                     }  
336                     return 0L;  
337             }  
338             break;  
339   
340         case WM_TIMER:  
341             // Update and flip surfaces  
342             if (g_bActive && TIMER_ID == wParam)  
343             {  
344                 MoveOverlay();  
345                                 Sleep(100);  
346                                 LoadBugImages();  
347             }  
348             break;  
349     }  
350     return DefWindowProc(hWnd, message, wParam, lParam);  
351 }  
352   
353 //-----------------------------------------------------------------------------  
354 //  Function: CopyBitmapToYUVSurface  
355 //  Description:   
356 //      Copies an RGB GDI bitmap to a YUV surface. Both bitmap and surface  
357 //      must be a multiple of 2 pixels in width for the supported YUV formats.    
358 //      The following formats are supported:  
359 //              YUYV  
360 //              UYVY  
361 //        
362 //      The "YUYV" YUV pixel format looks like this:  
363 //          As a series of BYTES:    [Y0][U][Y1][V] (reverse it for a DWORD)  
364 //   
365 //      The "UYVY" YUV pixel format looks like this:  
366 //          As a series of BYTES:    [U][Y0][V][Y1] (reverse it for a DWORD)  
367 //   
368 //      As you can see, both formats pack two pixels into a single DWORD. The   
369 //      pixels share U and V components and have separate Y components.  
370 //        
371 //  Returns: TRUE if successful, otherwise FALSE.  
372 //-----------------------------------------------------------------------------  
373 static BOOL CopyBitmapToYUVSurface(LPDIRECTDRAWSURFACE lpDDSurf, HBITMAP hbm)  
374 {  
375     HDC                 hdcImage;  
376     HRESULT             ddrval;  
377     DDSURFACEDESC       ddsd;  
378     DWORD               x, y, dwWidth, dwHeight;  
379     DWORD               dwPitch;  
380     LPBYTE              pSurf;  
381     DWORD               dwBytesInRow;  
382     COLORREF            color;  
383     BYTE                R,G,B, Y0,Y1,U,V;  
384     BOOL                bRet = FALSE;  
385   
386     if (hbm == NULL || lpDDSurf == NULL)  
387         return FALSE;  
388   
389     //  
390     //  select bitmap into a memoryDC so we can use it.  
391     //  
392     hdcImage = CreateCompatibleDC(NULL);  
393     SelectObject(hdcImage, hbm);  
394   
395     memset(&ddsd, 0, sizeof(ddsd));  
396     ddsd.dwSize = sizeof(ddsd);  
397     // Lock down the surface so we can modify it's contents.  
398     ddrval=lpDDSurf->Lock( NULL, &ddsd, DDLOCK_WAITNOTBUSY, NULL);  
399     if (FAILED(ddrval))  
400             goto CleanUp;  
401   
402     dwWidth=ddsd.dwWidth;  
403     dwHeight=ddsd.dwHeight;  
404     dwPitch=ddsd.lPitch;  
405     pSurf=(LPBYTE)ddsd.lpSurface;  
406         dwBytesInRow=ddsd.dwWidth*2;  
407   
408     // Go through the image 2 pixels at a time and convert to YUV  
409     for(y=0; y<dwHeight; y++)  
410     {  
411                 for(x=0; x<dwWidth; x+=2)  
412                 {  
413                         // The equations for color conversion used here, probably aren't   
414                         // exact, but they seem to do an OK job.  
415                         color=GetPixel(hdcImage, x,y);  
416                         R=GetRValue(color);  
417                         G=GetGValue(color);  
418                         B=GetBValue(color);  
419                     Y0= (BYTE)(0.29*R + 0.59*G + 0.14*B);  
420                         U= (BYTE)(128.0 - 0.14*R - 0.29*G + 0.43*B);  
421   
422                         color=GetPixel(hdcImage, x+1,y);  
423                         R=GetRValue(color);  
424                         G=GetGValue(color);  
425                         B=GetBValue(color);  
426                         Y1= (BYTE)(0.29*R + 0.57*G + 0.14*B);  
427                         V= (BYTE)(128.0 + 0.36*R - 0.29*G - 0.07*B);  
428   
429                         switch (ddsd.ddpfPixelFormat.dwFourCC)  
430                         {  
431                                 case MAKEFOURCC('Y','U','Y','V'):   
432                                         *(pSurf++) = Y0;  
433                                         *(pSurf++) = U;  
434                                         *(pSurf++) = Y1;  
435                                         *(pSurf++) = V;  
436                                         break;  
437                                 case MAKEFOURCC('U','Y','V','Y'):   
438                                         *(pSurf++) = U;  
439                                         *(pSurf++) = Y0;  
440                                         *(pSurf++) = V;  
441                                         *(pSurf++) = Y1;  
442                                         break;  
443                         }                         
444                 }  
445                 pSurf+=(dwPitch-dwBytesInRow);  
446     }  
447   
448     lpDDSurf->Unlock(NULL);       
449   
450 CleanUp:  
451     if(hdcImage)  
452         DeleteDC(hdcImage);  
453   
454         return TRUE;  
455 }  
456   
457 //-----------------------------------------------------------------------------  
458 //  Function: LoadImageOnToSurface  
459 //  Description:  
460 //      Loads a resource based bitmap image onto a DirectDraw surface.  Can  
461 //      covert the bitmap to all RGB formats, plus a couple YUV formats.  
462 //-----------------------------------------------------------------------------  
463 static BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE lpdds, UINT lpstrResID)  
464 {  
465     HBITMAP hbm = NULL;  
466     HDC     hdcImage = NULL;  
467     HDC     hdcSurf = NULL;  
468     BOOL bRetVal = FALSE;  
469     HRESULT ddrval;  
470     DDSURFACEDESC ddsd;  
471   
472     if(!lpdds)  
473                 return FALSE;  
474   
475     // get surface size and format.  
476     memset(&ddsd, 0, sizeof(ddsd));  
477     ddsd.dwSize = sizeof(ddsd);  
478     ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;  
479     ddrval = lpdds->GetSurfaceDesc(&ddsd);  
480     if(FAILED(ddrval))  
481             goto Exit;  
482   
483         // Load the bitmap resource.  We'll use LoadImage() since it'll scale the   
484     // image to fit our surface, and maintain the color information in the bitmap.  
485     hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(lpstrResID), IMAGE_BITMAP, 0, 0, 0);  
486         if(hbm == NULL)  
487             goto Exit;  
488   
489     // If our surface is a FOURCC YUV format, we need to do a little work to convert  
490     // our RGB resource bitmap into the appropriate YUV format.  
491     if(ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC)  
492     {  
493                 if(!CopyBitmapToYUVSurface(lpdds, hbm))  
494                         goto Exit;  
495     }  
496     else  //Looks like we're just using a standard RGB surface format, let GDI do the work.  
497     {  
498             // Create a DC and associate the bitmap with it.  
499             hdcImage = CreateCompatibleDC(NULL);  
500             SelectObject(hdcImage, hbm);  
501      
502             ddrval = lpdds->GetDC(&hdcSurf);  
503             if(FAILED(ddrval))  
504                 goto Exit;  
505       
506             if(BitBlt(hdcSurf, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, 0, 0, SRCCOPY) == FALSE)  
507                 goto Exit;  
508   
509                 ::SetBkMode(hdcSurf,TRANSPARENT);  
510                 ::SetTextColor(hdcSurf,RGB(255,0,0));  
511                 RECT Rect={0,0,100,50};  
512                 ::DrawText(hdcSurf,_T("ABCD"),4,&Rect,DT_SINGLELINE|DT_LEFT);  
513     }  
514   
515     bRetVal = TRUE;  
516       
517 Exit:  
518     if(hdcSurf)  
519             lpdds->ReleaseDC(hdcSurf);  
520     if(hdcImage)  
521             DeleteDC(hdcImage);  
522     if(hbm)  
523             DeleteObject(hbm);  
524   
525     return bRetVal;  
526 }  
527   
528 //-----------------------------------------------------------------------------  
529 // Name: EnumSurfacesCallback()  
530 // Desc: Used by LoadBugImages to aid it loading all three bug images.  
531 //-----------------------------------------------------------------------------  
532 static HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE lpDDSurface,    
533                      LPDDSURFACEDESC lpDDSurfaceDesc,    
534                      LPVOID lpContext)  
535 {  
536     int *CallCount = (int *)lpContext;  
537     HRESULT hr = (HRESULT)DDENUMRET_OK;  
538     UINT ResName;  
539   
540     // Load the Bug Image appropriate...  
541     if(*CallCount == 0)  
542         {  
543         ResName = IDB_BUGIMAGE2;  
544     }  
545     else if(*CallCount == 1)  
546         {  
547         ResName = IDB_BUGIMAGE3;  
548     }  
549     else  
550         {  
551         hr = (HRESULT)DDENUMRET_CANCEL;  
552         goto exit;  
553     }  
554   
555     if(!LoadImageOntoSurface(lpDDSurface, ResName))  
556         {  
557         hr = (HRESULT)DDENUMRET_CANCEL;  
558         goto exit;  
559     }  
560   
561     // Bump the count.  
562     (*CallCount)++;  
563         if(*CallCount >= 2)  
564         {  
565                 *CallCount = 0;  
566         }  
567   
568 exit:  
569     lpDDSurface->Release();  
570     return hr;  
571 }  
572   
573 //-----------------------------------------------------------------------------  
574 // Name: LoadBugImages()  
575 // Desc: Load the bug resource images into our various flipping surfaces.  
576 //-----------------------------------------------------------------------------  
577 static HRESULT LoadBugImages()  
578 {  
579     HRESULT hRet;  
580     static int CallCount = 0;  
581   
582     // Put the first bug image onto the first buffer of our complex surface.  
583         if(0 == CallCount)  
584         {  
585                 if(!LoadImageOntoSurface(g_pDDSOverlay, IDB_BUGIMAGE1))  
586                         return (E_FAIL);  
587         }  
588   
589     // Use the enumeration attachment function to load the other images.  
590     hRet = g_pDDSOverlay->EnumAttachedSurfaces((LPVOID)&CallCount,EnumSurfacesCallback);  
591   
592     return (hRet);  
593 }  
594   
595 //-----------------------------------------------------------------------------  
596 // Name: InitApp()  
597 // Desc: Do work required for every instance of the application:  
598 //          Create the window, initialize data  
599 //-----------------------------------------------------------------------------  
600 static HRESULT InitApp(HINSTANCE hInstance, int nCmdShow)  
601 {  
602     HWND          hWnd;  
603     WNDCLASS      wc;  
604     DDSURFACEDESC ddsd;  
605     DDCAPS        ddcaps;  
606     HRESULT       hRet;  
607     DWORD         dwUpdateFlags = 0;  
608     DDOVERLAYFX   ovfx;  
609     DEVMODE       DevMode;  
610   
611     // Check for rotation support by getting the rotation angles supported.  
612     memset(&DevMode, 0, sizeof(DevMode));  
613     DevMode.dmSize = sizeof(DevMode);  
614     DevMode.dmFields = DM_DISPLAYQUERYORIENTATION;  
615     if(DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL))  
616         {  
617         g_RotationAngles = DevMode.dmDisplayOrientation;  
618     }  
619     else  
620         {  
621         OutputDebugString(L"MOSQUITO: Device does not support any rotation modes. Rotation disabled.");  
622         g_RotationAngles = -1;  
623     }  
624   
625     // Get the current rotation angle.  
626     memset(&DevMode, 0, sizeof (DevMode));  
627     DevMode.dmSize = sizeof (DevMode);  
628     DevMode.dmFields = DM_DISPLAYORIENTATION;  
629     if(DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL))  
630         {  
631         g_CurrentAngle = DevMode.dmDisplayOrientation;  
632     }  
633     else  
634         {  
635         OutputDebugString(L"MOSQUITO: Unable to read current rotation. Rotation disabled.");  
636         g_CurrentAngle = -1;  
637     }  
638   
639     // Set up and register window class.  
640     wc.style = CS_HREDRAW | CS_VREDRAW;  
641     wc.lpfnWndProc = WindowProc;  
642     wc.cbClsExtra = 0;  
643     wc.cbWndExtra = 0;  
644     wc.hInstance = hInstance;  
645     wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MOSQUITO));  
646     wc.hCursor = LoadCursor(NULL, IDC_ARROW);  
647     wc.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH);  
648     wc.lpszMenuName = NULL;  
649     wc.lpszClassName = NAME;  
650     RegisterClass(&wc);  
651   
652     // Create a window.  
653     hWnd = CreateWindowEx(WS_EX_TOPMOST,  
654       NAME,  
655       TITLE,  
656       WS_POPUP,  
657       0,  
658       0,  
659       GetSystemMetrics(SM_CXSCREEN),  
660       GetSystemMetrics(SM_CYSCREEN),  
661       NULL,  
662       NULL,  
663       hInstance,  
664       NULL);  
665     if(!hWnd)  
666         return FALSE;  
667     // We never show the window, only set focus to it.  
668     SetFocus(hWnd);  
669   
670     // Create the main DirectDraw object  
671     hRet = DirectDrawCreate(NULL, &g_pDD, NULL);  
672     if(hRet != DD_OK)  
673         return InitFail(hWnd, hRet, TEXT("DirectDrawCreate FAILED"));  
674   
675     // Get normal mode.  
676     hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);  
677     if(hRet != DD_OK)  
678         return InitFail(hWnd, hRet, TEXT("SetCooperativeLevel FAILED"));  
679   
680     // Get a primary surface interface pointer (only needed for init.)  
681         // 要使用覆盖表面, 必须先要初始化一个主表面, 覆盖表面将显示在该主表面上  
682     memset(&ddsd, 0, sizeof(ddsd));  
683     ddsd.dwSize = sizeof(ddsd);  
684     ddsd.dwFlags = DDSD_CAPS;  
685     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;  
686     hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);  
687     if(hRet != DD_OK)  
688         return InitFail(hWnd, hRet, TEXT("CreateSurface FAILED"));  
689   
690     // See if we can support overlays.  
691         // 初始化 DirectDraw 后, 需要检测设备是否支持覆盖表面  
692         // 因为 DirectDraw 不能仿真覆盖, 所以如果硬件不支持覆盖, 就不能继续下面的工作  
693     memset(&ddcaps, 0, sizeof(ddcaps));  
694     ddcaps.dwSize = sizeof(ddcaps);  
695     hRet = g_pDD->GetCaps(&ddcaps, NULL);  
696     if(hRet != DD_OK)  
697         return InitFail(hWnd, hRet, TEXT("GetCaps FAILED"));  
698   
699     if(ddcaps.dwOverlayCaps == 0)  
700         return InitFail(hWnd, hRet, TEXT("Overlays are not supported in hardware!"));  
701         /* // Leo.Zheng Add 
702         if(!(capsDrv.dwCaps & DDCAPS_OVERLAY)) 
703                 return FALSE; 
704         */  
705   
706     // Get alignment info to compute our overlay surface size.  
707     rs.left = 0;  
708     rs.top = 0;  
709     rs.right = BUG_WIDTH;  
710     rs.bottom = BUG_HEIGHT;  
711     if(ddcaps.dwAlignSizeSrc != 0)  
712             rs.right += rs.right % ddcaps.dwAlignSizeSrc;  
713       
714     // Create the overlay flipping surface. We will attempt the pixel formats  
715         // in our table one at a time until we find one that jives.  
716         // 如果知道显示设备支持覆盖表面, 就可以创建一个. 因为没有指明设备怎样支持覆盖表面的标准, 所以不能够期望创建任意大小的像素格式的表面.  
717         // 另外, 也不要期望第一次创建覆盖表面就会成功. 因此, 必须作好准备进行多次创建的尝试, 直到有一个能够工作为止.  
718         int i = 0;  
719     memset(&ddsd, 0, sizeof(ddsd));  
720     ddsd.dwSize = sizeof(ddsd);  
721     ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP;  
722     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT;  
723         ddsd.dwWidth = rs.right;  
724         ddsd.dwHeight = rs.bottom;  
725     ddsd.dwBackBufferCount = 1;  
726     do  
727         {       // Leo.Zheng MStar 2521 只创建 16-bit RGB 5:6:5 成功; 创建 16-bit RGB 5:5:5 失败.  
728             ddsd.ddpfPixelFormat = ddpfOverlayFormats[i];  
729             hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL);                   // Leo.Zheng 此处调用后引起使用 IOCtrl 显示在 LCD 上的消失  
730                 RETAILMSG(1,(L"[mosquito]Create No.%d surface return: 0x%X\r\n",i + 1,hRet));  
731     }while(hRet != DD_OK && (++i < PF_TABLE_SIZE));  
732     if(hRet != DD_OK)  
733         return InitFail(hWnd, hRet, TEXT("Unable to create overlay surface!"));  
734   
735     // Load the images.  
736     if(LoadBugImages() != DD_OK)  
737         return InitFail(hWnd, hRet, TEXT("Unable to load images to overlay surface!"));  
738   
739     // Finish setting up the overlay.  
740     int StretchFactor1000 = ddcaps.dwMinOverlayStretch > 1000 ? ddcaps.dwMinOverlayStretch : 1000;  
741   
742     rd.left=0;   
743     rd.top=0;  
744     // Adding 999 takes care of integer truncation problems.  
745     rd.right  = (rs.right * StretchFactor1000 + 999) / 1000;  
746     rd.bottom = rs.bottom * StretchFactor1000 / 1000;  
747     if (ddcaps.dwAlignSizeDest != 0)  
748             rd.right = (int)((rd.right + ddcaps.dwAlignSizeDest - 1)/ ddcaps.dwAlignSizeDest) * ddcaps.dwAlignSizeDest;  
749   
750         // 显示覆盖表面: 在设置了源矩形和目的矩形后, 就可以显示覆盖了.  
751         // 程序开始在临时变量 dwUpdateFlags 中设定了 DDOVER_SHOW 和 DDOVER_DDFX 标志, 指明该覆盖是第一次显示,   
752         // 硬件应该使用包含在 DDOVERLAYFX 结构中的效果信息完成这一工作.  
753         // UpdateOverlay 用于重新定位一个覆盖页面, 或修改其视觉属性.  
754     // Set the flags we'll send to UpdateOverlay  
755     dwUpdateFlags = DDOVER_SHOW;  
756         // dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX;                   // Leo.Zheng DDOVER_DDFX WinCE 不支持  
757   
758         // 检查 DDCAPS 结构确定覆盖是否支持源 Color Key  
759     // Does the overlay hardware support source color keying?  
760     // If so, we can hide the black background around the image.  
761     // This probably won't work with YUV formats  
762     memset(&ovfx, 0, sizeof(ovfx));  
763     ovfx.dwSize = sizeof(ovfx);  
764     if(ddcaps.dwOverlayCaps & DDOVERLAYCAPS_CKEYSRC)                    // MStar2521 不支持 color key  
765     {  
766         dwUpdateFlags |= DDOVER_KEYSRCOVERRIDE;  
767   
768         // Create an overlay FX structure so we can specify a source color key.  
769         // This information is ignored if the DDOVER_SRCKEYOVERRIDE flag   
770         // isn't set.  
771         ovfx.dckSrcColorkey.dwColorSpaceLowValue=0; // black as the color key  
772         ovfx.dckSrcColorkey.dwColorSpaceHighValue=0;  
773     }  
774         else  
775         {  
776                 RETAILMSG(1,(L"[mosquito]cannot support color key: 0x%X(0x%x)\r\n",ddcaps.dwOverlayCaps,DDOVERLAYCAPS_CKEYSRC));  
777         }  
778   
779     // Update the overlay parameters.  
780         // 调用 IDirectDrawSurface::UpdateOverlay 方法来显示覆盖  
781     hRet = g_pDDSOverlay->UpdateOverlay(&rs, g_pDDSPrimary, &rd, dwUpdateFlags, &ovfx);  
782     if(hRet != DD_OK)  
783         {  
784                 // 在 MStar 2521 设备上运行第二个此程序实例时出错。  
785                 // 在 TeleChips 8902 设备上运行第三个此程序实例时出错。  
786                 return InitFail(hWnd, hRet, TEXT("Unable to show overlay surface: 0x%x!"),hRet);  
787         }  
788   
789     // Set a bunch of position and velocity module vars.  
790     g_nOverlayXPos = 0;  
791     g_nOverlayYPos = 0;  
792     g_nOverlayXVel = RANDOM_VELOCITY();  
793     g_nOverlayYVel = RANDOM_VELOCITY();  
794     g_nOverlayWidth = rd.right - rd.left;  
795     g_nOverlayHeight = rd.bottom - rd.top;  
796       
797     // Set the "destination position alignment" global so we won't have to  
798     // keep calling GetCaps() everytime we move the overlay surface.  
799     g_dwOverlayXPositionAlignment = ddcaps.dwAlignBoundaryDest;  
800   
801     // Create a timer to flip the pages.  
802     if(TIMER_ID != SetTimer(hWnd, TIMER_ID, TIMER_RATE, NULL))  
803         return InitFail(hWnd, hRet, TEXT("SetTimer FAILED"));  
804   
805     return DD_OK;  
806 }  
807   
808 //-----------------------------------------------------------------------------  
809 // Name: WinMain()  
810 // Desc: Initialization, message loop  
811 //-----------------------------------------------------------------------------  
812 int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,  
813 #ifdef UNDER_CE  
814         LPWSTR lpCmdLine,  
815 #else  
816         LPSTR lpCmdLine,  
817 #endif  
818         int nCmdShow)  
819 {  
820     MSG msg;  
821   
822     g_hInstance = hInstance;  
823     if(InitApp(hInstance, nCmdShow) != DD_OK)  
824         return FALSE;  
825   
826     while(GetMessage(&msg, NULL, 0, 0))  
827     {  
828         TranslateMessage(&msg);  
829         DispatchMessage(&msg);  
830     }  
831   
832     return msg.wParam;  
833 }  

 

你可能感兴趣的:(WinCE Overlay - 示例:mosquito)