WinCE5.0下直接写屏操作与函数 CreateDIBSection() 的使用

时间:2021-10-10 08:41:36

这段时间在研究直接写屏的方法.

此问题的起因是: 在 iMX31(WinCE 5.0)上, 屏的分辨为: 800*480. 调用 BitBlt() API 函数画一整屏的动作, 竟然需要 120ms 左右; 同样的程序, 在 Prima 上只需要 20ms 以内的时间. 

直接写屏, 需要用到以下两个主要的函数: CreateDC(TEXT("DISPLAY"),......) 和 CreateDIBSection().

1) CreateDC(TEXT("DISPLAY"),......) 的用法比较简单, 参考 MSDN 就可以很容易的搞定.

2) CreateDIBSection() API 函数的使用, 花了我一些时间. 因为以前没有用过它, 所以将其使用的方法记录如下:

 1 {
 2     HBITMAP hDIBitmap;
 3     LPBYTE lpBitmapBits;
 4     BITMAPINFO DriectBmp; 
 5  
 6     ZeroMemory(&DriectBmp,sizeof(BITMAPINFO));
 7     DriectBmp.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
 8     DriectBmp.bmiHeader.biWidth = 800;
 9     DriectBmp.bmiHeader.biHeight = 480;
10     DriectBmp.bmiHeader.biPlanes = 1;
11     DriectBmp.bmiHeader.biBitCount = 16;
12     HDC dcDirect = CreateCompatibleDC(dcBuf);
13  
14     // 建立 hDIBitmap, dcDirect, 和 lpBitmapBits 之间的关系.
15     // 通过 DC 操作向 dcDirect 中写入图形数据, 从 lpBitmapBits 中取得内存数据, 进行内存 Copy 操作, 直接写向显存.
16     hDIBitmap = CreateDIBSection(dcDirect, (BITMAPINFO *)&DriectBmp, 
17       DIB_RGB_COLORS, (void **)&lpBitmapBits, NULL, 0);
18     if(NULL != hDIBitmap)
19     {
20       HGDIOBJ OldBitmap = SelectObject(dcDirect, hDIBitmap);
21  
22       BitBlt(dcDirect,0,0,800,480,dcBuf,0,0,SRCCOPY);
23  
24       CopyMemory(gpbFrameAddress,lpBitmapBits,800 * 480 * 2);
25  
26       SelectObject(dcDirect,OldBitmap);
27     }
28  
29     DeleteObject(hDIBitmap);
30     DeleteDC(dcDirect);
31   }

在研究此问题的过程中, 在 CSDN 上找到一个很好的资源, 也记录在自己这里:

http://topic.csdn.net/u/20090629/09/00b25d0d-d461-47dc-88ad-0e2131a5abc7.html

并转载其中关键的代码如下:

  1 #include "stdafx.h"
  2 #include "CopyScreen.h"
  3 #include <windows.h>
  4 #include <commctrl.h>
  5 #include"Jpeg.h"
  6 #define MAX_LOADSTRING 100
  7  
  8 // 全局变量:
  9 HINSTANCE            g_hInst;            // 当前实例
 10 HWND                g_hWndMenuBar;        // 菜单栏句柄
 11  
 12 // 此代码模块中包含的函数的前向声明:
 13 ATOM            MyRegisterClass(HINSTANCE, LPTSTR);
 14 BOOL            InitInstance(HINSTANCE, int);
 15 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 16 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 17  
 18 int WINAPI WinMain(HINSTANCE hInstance,
 19                    HINSTANCE hPrevInstance,
 20                    LPTSTR    lpCmdLine,
 21                    int       nCmdShow)
 22 {
 23     MSG msg;
 24  
 25     // 执行应用程序初始化:
 26     if (!InitInstance(hInstance, nCmdShow)) 
 27     {
 28         return FALSE;
 29     }
 30  
 31     HACCEL hAccelTable;
 32     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_COPYSCREEN));
 33  
 34     // 主消息循环:
 35     while (GetMessage(&msg, NULL, 0, 0)) 
 36     {
 37         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
 38         {
 39             TranslateMessage(&msg);
 40             DispatchMessage(&msg);
 41         }
 42     }
 43  
 44     return (int) msg.wParam;
 45 }
 46  
 47 //
 48 //  函数: MyRegisterClass()
 49 //
 50 //  目的: 注册窗口类。
 51 //
 52 //  注释:
 53 //
 54 ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
 55 {
 56     WNDCLASS wc;
 57  
 58     wc.style         = CS_HREDRAW | CS_VREDRAW;
 59     wc.lpfnWndProc   = WndProc;
 60     wc.cbClsExtra    = 0;
 61     wc.cbWndExtra    = 0;
 62     wc.hInstance     = hInstance;
 63     wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_COPYSCREEN));
 64     wc.hCursor       = 0;
 65     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
 66     wc.lpszMenuName  = 0;
 67     wc.lpszClassName = szWindowClass;
 68  
 69     return RegisterClass(&wc);
 70 }
 71  
 72 //
 73 //   函数: InitInstance(HINSTANCE, int)
 74 //
 75 //   目的: 保存实例句柄并创建主窗口
 76 //
 77 //   注释:
 78 //
 79 //        在此函数中,我们在全局变量中保存实例句柄并
 80 //        创建和显示主程序窗口。
 81 //
 82 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
 83 {
 84     HWND hWnd;
 85     TCHAR szTitle[MAX_LOADSTRING];        // 标题栏文本
 86     TCHAR szWindowClass[MAX_LOADSTRING];    // 主窗口类名
 87  
 88     g_hInst = hInstance; // 将实例句柄存储在全局变量中
 89  
 90     // 在应用程序初始化期间,应调用一次 SHInitExtraControls 以初始化
 91     // 所有设备特定控件,例如,CAPEDIT 和 SIPPREF。
 92     SHInitExtraControls();
 93  
 94     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
 95     LoadString(hInstance, IDC_COPYSCREEN, szWindowClass, MAX_LOADSTRING);
 96  
 97     //如果它已经在运行,则将焦点置于窗口上,然后退出
 98     hWnd = FindWindow(szWindowClass, szTitle);    
 99     if (hWnd) 
100     {
101         // 将焦点置于最前面的子窗口
102         // “| 0x00000001”用于将所有附属窗口置于前台并
103         // 激活这些窗口。
104         SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
105         return 0;
106     } 
107  
108     if (!MyRegisterClass(hInstance, szWindowClass))
109     {
110         return FALSE;
111     }
112  
113     hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
114         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
115  
116     if (!hWnd)
117     {
118         return FALSE;
119     }
120  
121     // 使用 CW_USEDEFAULT 创建主窗口时,将不会考虑菜单栏的高度(如果创建了一个
122     // 菜单栏)。因此,我们要在创建窗口后调整其大小
123     // 如果菜单栏存在
124     if (g_hWndMenuBar)
125     {
126         RECT rc;
127         RECT rcMenuBar;
128  
129         GetWindowRect(hWnd, &rc);
130         GetWindowRect(g_hWndMenuBar, &rcMenuBar);
131         rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
132  
133         MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE);
134     }
135  
136     ShowWindow(hWnd, nCmdShow);
137     UpdateWindow(hWnd);
138  
139  
140     return TRUE;
141 }
142  
143 HBITMAP CopyScreenToBitmap(int &nWidth,int &nHeight)
144 {
145     // 屏幕和内存设备描述表
146     HDC  hScrDC, hMemDC;      
147     // 位图句柄
148     HBITMAP  hBitmap, hOldBitmap;    
149     // 屏幕分辨率
150     int  xScrn, yScrn;         
151  
152     //为屏幕创建设备描述表
153     hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
154     //为屏幕设备描述表创建兼容的内存设备描述表
155     hMemDC = CreateCompatibleDC(hScrDC);
156     // 获得屏幕分辨率
157     xScrn = GetDeviceCaps(hScrDC, HORZRES);
158     yScrn = GetDeviceCaps(hScrDC, VERTRES);
159  
160     //存储屏幕的长宽
161     nWidth = xScrn;
162     nHeight = yScrn;
163  
164     // 创建一个与屏幕设备描述表兼容的位图
165     hBitmap = CreateCompatibleBitmap(hScrDC, xScrn, yScrn);
166     // 把新位图选到内存设备描述表中
167     hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
168     // 把屏幕设备描述表拷贝到内存设备描述表中
169     BitBlt(hMemDC, 0, 0, xScrn,yScrn,hScrDC, 0, 0, SRCCOPY);
170     //得到屏幕位图的句柄
171     hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
172     //清除 
173     DeleteDC(hScrDC);
174     DeleteDC(hMemDC);
175     // 返回位图句柄
176     return hBitmap;
177 }
178  
179 int Save16BitmapToFile(HBITMAP hBitmap,LPCTSTR lpFileName)//将截屏所得保存为16位的图片
180 {
181     HDC hDC=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
182     HDC hOffDC=CreateCompatibleDC(hDC);
183     SelectObject(hOffDC,hBitmap);
184  
185     BITMAP Bitmap;
186     GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
187  
188     HANDLE fh=CreateFile(lpFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
189         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
190     if(fh == INVALID_HANDLE_VALUE )
191         return FALSE;
192  
193     BITMAPFILEHEADER bfh;
194     memset(&bfh,0,sizeof(bfh));
195     bfh.bfType=0x4D42/*((WORD) ('M' << 8) | 'B')*/;
196     bfh.bfSize= sizeof(bfh)+2*Bitmap.bmWidth*Bitmap.bmHeight+sizeof(BITMAPFILEHEADER);
197     bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
198     DWORD dwWritten=0;
199     WriteFile(fh,&bfh,sizeof(bfh),&dwWritten,NULL);
200     BITMAPINFOHEADER bih;
201     memset(&bih,0,sizeof(bih));
202     bih.biSize=sizeof(bih);
203     bih.biWidth=Bitmap.bmWidth;
204     bih.biHeight=Bitmap.bmHeight;
205     bih.biPlanes=1;
206     bih.biBitCount=16;
207  
208     if( !WriteFile(fh,&bih,sizeof(bih),&dwWritten,NULL) )
209     {
210         return FALSE;
211     }
212  
213     BITMAPINFO bitmapInfo;
214     memset((void *)&bitmapInfo,0,sizeof(BITMAPINFO) );
215     bitmapInfo.bmiHeader=bih;
216  
217     HDC hMemDC=CreateCompatibleDC(hDC);    
218     BYTE *m_lpBitBmp=new BYTE[bfh.bfSize-sizeof(BITMAPFILEHEADER)];
219     HBITMAP hDibBitmap=CreateDIBSection(hMemDC,&bitmapInfo,DIB_RGB_COLORS,(void **)&m_lpBitBmp,
220         NULL,0);
221     if(hDibBitmap != 0)
222     {
223         ::SelectObject(hMemDC,hDibBitmap);
224         BitBlt(hMemDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,hOffDC,0,0,SRCCOPY);
225         WriteFile(fh,m_lpBitBmp,bfh.bfSize-sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
226     }
227  
228     DeleteObject(hDibBitmap);
229     DeleteDC(hDC);
230     DeleteDC(hMemDC);
231  
232     CloseHandle(fh);
233  
234     return 1;
235  
236 }
237  
238 int Save24BitmapToFile(HBITMAP hBitmap,LPCTSTR lpFileName)//将截屏所得保存为24位的图片
239 {
240     HDC hDC=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
241     HDC hOffDC=CreateCompatibleDC(hDC);
242     SelectObject(hOffDC,hBitmap);
243  
244     BITMAP Bitmap;
245     GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
246  
247     HANDLE fh=CreateFile(lpFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
248         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
249     if(fh == INVALID_HANDLE_VALUE )
250         return FALSE;
251  
252     BITMAPFILEHEADER bfh;
253     memset(&bfh,0,sizeof(bfh));
254     bfh.bfType=0x4D42/*((WORD) ('M' << 8) | 'B')*/;
255     bfh.bfSize= sizeof(bfh)+3*Bitmap.bmWidth*Bitmap.bmHeight+sizeof(BITMAPFILEHEADER);
256     bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
257     DWORD dwWritten=0;
258     WriteFile(fh,&bfh,sizeof(bfh),&dwWritten,NULL);
259     BITMAPINFOHEADER bih;
260     memset(&bih,0,sizeof(bih));
261     bih.biSize=sizeof(bih);
262     bih.biWidth=Bitmap.bmWidth;
263     bih.biHeight=Bitmap.bmHeight;
264     bih.biPlanes=1;
265     bih.biBitCount=24;
266  
267     if( !WriteFile(fh,&bih,sizeof(bih),&dwWritten,NULL) )
268     {
269         return FALSE;
270     }
271  
272     BITMAPINFO bitmapInfo;
273     memset((void *)&bitmapInfo,0,sizeof(BITMAPINFO) );
274     bitmapInfo.bmiHeader=bih;
275  
276     HDC hMemDC=CreateCompatibleDC(hDC);    
277     BYTE *m_lpBitBmp=new BYTE[3*Bitmap.bmWidth*Bitmap.bmHeight];
278     HBITMAP hDibBitmap=CreateDIBSection(hMemDC,&bitmapInfo,DIB_RGB_COLORS,(void **)&m_lpBitBmp,
279         NULL,0);
280     if(hDibBitmap != 0)
281     {
282         ::SelectObject(hMemDC,hDibBitmap);
283         BitBlt(hMemDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,hOffDC,0,0,SRCCOPY);
284         WriteFile(fh,m_lpBitBmp,3*Bitmap.bmWidth*Bitmap.bmHeight,&dwWritten,NULL);
285     }
286  
287     DeleteObject(hDibBitmap);
288     DeleteDC(hDC);
289     DeleteDC(hMemDC);
290  
291     CloseHandle(fh);
292  
293     return 1;
294  
295 }
  1 /*索引颜色/颜色表 
  2  
  3 位图常用的一种压缩方法。从位图图片中选择最有代表性的若干种颜色(通常不超过256种)编制成颜色表,
  4 然后将图片中原有颜色用颜色表的索引来表示。
  5 这样原图片可以被大幅度有损压缩。适合于压缩网页图形等颜色数较少的图形,
  6 不适合压缩照片等色彩丰富的图形。 */
  7  
  8 int Save32BitmapToFile(HBITMAP hBitmap,LPCTSTR lpFileName)//将截屏所得保存为32位带颜色表的图片
  9 {
 10     /*若不使用颜色表,则去掉bih.biCompression=BI_BITFIELDS;这句,然后
 11     不设置bitmapInfo.bmiColors[0].rgbRed=255;
 12     bitmapInfo.bmiColors[0].rgbGreen=255;
 13     bitmapInfo.bmiColors[0].rgbBlue=255;*/
 14  
 15     HDC hDC=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
 16     HDC hOffDC=CreateCompatibleDC(hDC);
 17     SelectObject(hOffDC,hBitmap);
 18  
 19     BITMAP Bitmap;
 20     GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
 21  
 22     HANDLE fh=CreateFile(lpFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
 23         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
 24     if(fh == INVALID_HANDLE_VALUE )
 25         return FALSE;
 26  
 27     BITMAPFILEHEADER bfh;
 28     memset(&bfh,0,sizeof(bfh));
 29     bfh.bfType=0x4D42/*((WORD) ('M' << 8) | 'B')*/;
 30     bfh.bfSize= sizeof(bfh)+4*Bitmap.bmWidth*Bitmap.bmHeight+sizeof(BITMAPFILEHEADER);
 31     bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
 32  
 33     DWORD dwWritten=0;
 34     WriteFile(fh,&bfh,sizeof(bfh),&dwWritten,NULL);
 35     BITMAPINFOHEADER bih;
 36     memset(&bih,0,sizeof(bih));
 37     bih.biSize=sizeof(bih);
 38     bih.biWidth=Bitmap.bmWidth;
 39     bih.biHeight=Bitmap.bmHeight;
 40     bih.biPlanes=1;
 41     bih.biBitCount=32;
 42     bih.biCompression=BI_BITFIELDS;
 43  
 44  
 45     if( !WriteFile(fh,&bih,sizeof(bih),&dwWritten,NULL) )
 46     {
 47         return FALSE;
 48     }
 49  
 50     BITMAPINFO bitmapInfo;
 51     memset((void *)&bitmapInfo,0,sizeof(BITMAPINFO) );
 52     bitmapInfo.bmiHeader=bih;
 53     bitmapInfo.bmiColors[0].rgbRed=255;
 54     bitmapInfo.bmiColors[0].rgbGreen=255;
 55     bitmapInfo.bmiColors[0].rgbBlue=255;
 56  
 57  
 58     HDC hMemDC=CreateCompatibleDC(hDC);    
 59     BYTE *m_lpBitBmp=new BYTE[4*Bitmap.bmWidth*Bitmap.bmHeight];
 60     HBITMAP hDibBitmap=CreateDIBSection(hMemDC,&bitmapInfo,DIB_RGB_COLORS,(void **)&m_lpBitBmp,
 61         NULL,0);
 62     if(hDibBitmap != 0)
 63     {
 64         ::SelectObject(hMemDC,hDibBitmap);
 65         BitBlt(hMemDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,hOffDC,0,0,SRCCOPY);
 66         WriteFile(fh,m_lpBitBmp,4*Bitmap.bmWidth*Bitmap.bmHeight,&dwWritten,NULL);
 67     }
 68  
 69     DeleteObject(hDibBitmap);
 70     DeleteDC(hDC);
 71     DeleteDC(hMemDC);
 72  
 73     CloseHandle(fh);
 74  
 75     return 1;
 76  
 77 }
 78  
 79 int SaveJPEGToFile(HBITMAP hBitmap,LPCSTR lpFileName)//将截屏所得保存为jpeg图片
 80 {
 81  
 82  
 83     HDC hDC=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
 84     HDC hOffDC=CreateCompatibleDC(hDC);
 85     SelectObject(hOffDC,hBitmap);
 86  
 87     BITMAP Bitmap;
 88     GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
 89  
 90     HANDLE fh=CreateFile((LPCWSTR)lpFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
 91         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
 92     if(fh == INVALID_HANDLE_VALUE )
 93         return FALSE;
 94  
 95     BITMAPFILEHEADER bfh;
 96     memset(&bfh,0,sizeof(bfh));
 97     bfh.bfType=0x4D42/*((WORD) ('M' << 8) | 'B')*/;
 98     bfh.bfSize= sizeof(bfh)+3*Bitmap.bmWidth*Bitmap.bmHeight+sizeof(BITMAPFILEHEADER);
 99     bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
100     DWORD dwWritten=0;
101 //    WriteFile(fh,&bfh,sizeof(bfh),&dwWritten,NULL);
102     BITMAPINFOHEADER bih;
103     memset(&bih,0,sizeof(bih));
104     bih.biSize=sizeof(bih);
105     bih.biWidth=Bitmap.bmWidth;
106     bih.biHeight=Bitmap.bmHeight;
107     bih.biPlanes=1;
108     bih.biBitCount=24;
109  
110     /*if( !WriteFile(fh,&bih,sizeof(bih),&dwWritten,NULL) )
111     {
112         return FALSE;
113     }*/
114  
115     BITMAPINFO bitmapInfo;
116     memset((void *)&bitmapInfo,0,sizeof(BITMAPINFO) );
117     bitmapInfo.bmiHeader=bih;
118  
119     HDC hMemDC=CreateCompatibleDC(hDC);    
120     BYTE *m_lpBitBmp=new BYTE[bfh.bfSize-sizeof(BITMAPFILEHEADER)];
121     HBITMAP hDibBitmap=CreateDIBSection(hMemDC,&bitmapInfo,DIB_RGB_COLORS,(void **)&m_lpBitBmp,
122         NULL,0);
123     if(hDibBitmap != 0)
124     {
125         ::SelectObject(hMemDC,hDibBitmap);
126         BitBlt(hMemDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,hOffDC,0,0,SRCCOPY);
127         //WriteFile(fh,m_lpBitBmp,bfh.bfSize-sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
128          WriteJPEGFile(lpFileName, m_lpBitBmp,Bitmap.bmWidth,Bitmap.bmHeight,TRUE, 60);
129  
130     }
131  
132     DeleteObject(hDibBitmap);
133     DeleteDC(hDC);
134     DeleteDC(hMemDC);
135  
136     CloseHandle(fh);
137  
138     return 1;
139  
140 }
141  
142  
143 //
144 //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
145 //
146 //  目的: 处理主窗口的消息。
147 //
148 //  WM_COMMAND    - 处理应用程序菜单
149 //  WM_PAINT    - 绘制主窗口
150 //  WM_DESTROY    - 发送退出消息并返回
151 //
152 //
153 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
154 {
155     int wmId, wmEvent;
156     PAINTSTRUCT ps;
157     HDC hdc;
158  
159     static SHACTIVATEINFO s_sai;
160     int iWidth,iHeight;
161     HBITMAP hBitmap;
162  
163     static int s_cxBegin;
164     static int s_cyBegin;
165     static int s_cxEnd;
166     static int s_cyEnd;
167     switch (message) 
168     {
169         case WM_COMMAND:
170             wmId    = LOWORD(wParam); 
171             wmEvent = HIWORD(wParam); 
172             // 分析菜单选择:
173             switch (wmId)
174             {
175                 case IDM_HELP_ABOUT:
176                     DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
177                     break;
178                 case IDM_OK:
179                     SendMessage (hWnd, WM_CLOSE, 0, 0);                
180                     break;
181  
182                 case ID_RGB16:
183  
184                     hBitmap=CopyScreenToBitmap(iWidth,iHeight);
185                     Save16BitmapToFile(hBitmap,TEXT("//a.bmp"));
186                     break;
187  
188                 case ID_RGB24:
189  
190                     hBitmap=CopyScreenToBitmap(iWidth,iHeight);
191                     Save24BitmapToFile(hBitmap,TEXT("//b.bmp"));
192                     break;
193  
194                 case ID_RGB32:
195                     hBitmap=CopyScreenToBitmap(iWidth,iHeight);
196                     Save32BitmapToFile(hBitmap,TEXT("//c.bmp"));
197                     break;
198  
199                 case ID_JPEG:
200                     hBitmap=CopyScreenToBitmap(iWidth,iHeight);
201                     SaveJPEGToFile(hBitmap,"d.jpg");
202                     break;
203  
204                 default:
205                     return DefWindowProc(hWnd, message, wParam, lParam);
206             }
207             break;
208         case WM_CREATE:
209             SHMENUBARINFO mbi;
210  
211             memset(&mbi, 0, sizeof(SHMENUBARINFO));
212             mbi.cbSize     = sizeof(SHMENUBARINFO);
213             mbi.hwndParent = hWnd;
214             mbi.nToolBarId = IDR_MENU;
215             mbi.hInstRes   = g_hInst;
216  
217             if (!SHCreateMenuBar(&mbi)) 
218             {
219                 g_hWndMenuBar = NULL;
220             }
221             else
222             {
223                 g_hWndMenuBar = mbi.hwndMB;
224             }
225  
226             // 初始化外壳程序激活信息结构
227             memset(&s_sai, 0, sizeof (s_sai));
228             s_sai.cbSize = sizeof (s_sai);
229             break;
230  
231         case WM_LBUTTONDOWN:
232             HCURSOR  hCursor;
233             hCursor=SetCursor( LoadCursor(NULL,MAKEINTRESOURCE(IDC_WAIT) ) );
234  
235             s_cxBegin=LOWORD(lParam);
236             s_cyBegin=HIWORD(lParam);
237  
238             break;
239  
240  
241  
242         case WM_LBUTTONUP:
243  
244             s_cxEnd=LOWORD(lParam);
245             s_cyEnd=HIWORD(lParam);
246             SetCursor( LoadCursor( GetModuleHandle(NULL),MAKEINTRESOURCE(IDC_ARROW) ) );
247  
248             break;
249         case WM_PAINT:
250             hdc = BeginPaint(hWnd, &ps);
251  
252             // TODO: 在此添加任意绘图代码...
253  
254             EndPaint(hWnd, &ps);
255             break;
256         case WM_DESTROY:
257             CommandBar_Destroy(g_hWndMenuBar);
258             PostQuitMessage(0);
259             break;
260  
261         case WM_ACTIVATE:
262             // 向外壳程序通知我们的激活消息
263             SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
264             break;
265         case WM_SETTINGCHANGE:
266             SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
267             break;
268  
269         default:
270             return DefWindowProc(hWnd, message, wParam, lParam);
271     }
272     return 0;
273 }