搜索
bottom↓
回复: 5

MFC操作BMP写字的方法

[复制链接]

出0入0汤圆

发表于 2015-5-30 14:54:40 | 显示全部楼层 |阅读模式
     //一下程序来源于网上,拿来分享下
  1 //单击一个Button,保存位图
  2 void CDlgDlg::OnButton1()
  3 {
  4     // TODO: Add your control notification handler code here   
  5     HDC hDC = ::GetDC(GetSafeHwnd());
  6     HDC hMemDC = CreateCompatibleDC(hDC);
  7     //打开位图文件
  8     HBITMAP hBmp = OpenBmpFile(hDC, "Splash.bmp");
  9     SelectObject(hMemDC, hBmp);
10     //在位图上写字
11     RECT rect = {50, 50, 200, 200};
12     SetBkMode(hMemDC, TRANSPARENT);
13     DrawText(hMemDC, "你好", -1, &rect, DT_VCENTER);
14  
15     //保存位图到文件
16     PBITMAPINFO pBmpInfo = CreateBitmapInfoStruct(GetSafeHwnd(), hBmp);
17     CreateBMPFile(GetSafeHwnd(), "Test.bmp", pBmpInfo, hBmp, hDC);
18  
19     DeleteDC(hMemDC);
20     DeleteObject(hBmp);
21 }
22  
23 //打开位图文件,得到位图句柄
24 HBITMAP CDlgDlg::OpenBmpFile(HDC hDC, LPSTR lpszFileName)
25 {
26     HBITMAP hBmp = NULL;
27     //读位图文件,得到位图句柄
28     HANDLE hFile = CreateFile(
29         lpszFileName,
30         GENERIC_READ,
31         FILE_SHARE_READ,
32         NULL,
33         OPEN_EXISTING,
34         FILE_ATTRIBUTE_NORMAL,
35         NULL);
36     if(hFile == INVALID_HANDLE_VALUE)
37         return NULL;
38     //读位图文件头
39     BITMAPFILEHEADER bmpFileHeader;
40     DWORD dwNumberOfBytesRead;
41     if(ReadFile(hFile, (LPVOID)&bmpFileHeader, sizeof(BITMAPFILEHEADER), &dwNumberOfBytesRead, NULL) == 0)
42     {   
43         CloseHandle(hFile);
44         return NULL;
45     }
46     //读位图信息
47     BITMAPINFO *pBmpInfo = new BITMAPINFO;
48     if(ReadFile(hFile, pBmpInfo, sizeof(BITMAPINFOHEADER), &dwNumberOfBytesRead, NULL) == 0)
49     {   
50         CloseHandle(hFile);
51         return NULL;
52     }
53     //读位图数据
54     LPVOID pBmpData;
55     //创建DIB位图句柄
56     hBmp = CreateDIBSection(hDC, pBmpInfo, DIB_PAL_COLORS, &pBmpData, NULL, 0);
57     if(hBmp == NULL)
58     {
59         DWORD dwErr = GetLastError();
60         return NULL;
61     }
62     else  //读位图数据
63         if(ReadFile(hFile, pBmpData, pBmpInfo->bmiHeader.biSizeImage, &dwNumberOfBytesRead, NULL) == 0)
64         {   
65             CloseHandle(hFile);
66             return NULL;
67         }      
68     CloseHandle(hFile);
69     return hBmp;
70 }
71  
72 //下面的代码是把一张位图保存于文件中,参考MSDN
73 PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
74 {
75     BITMAP bmp;
76     PBITMAPINFO pbmi;
77     WORD    cClrBits;
78  
79     // Retrieve the bitmap's color format, width, and height.
80     if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
81         return NULL;
82  
83     // Convert the color format to a count of bits.
84     cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
85     if (cClrBits == 1)
86         cClrBits = 1;
87     else if (cClrBits <= 4)
88         cClrBits = 4;
89     else if (cClrBits <= 8)
90         cClrBits = 8;
91     else if (cClrBits <= 16)
92         cClrBits = 16;
93     else if (cClrBits <= 24)
94         cClrBits = 24;
95     else cClrBits = 32;
96  
97     // Allocate memory for the BITMAPINFO structure. (This structure
98     // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
99     // data structures.)
100  
101      if (cClrBits != 24)
102          pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
103                     sizeof(BITMAPINFOHEADER) +
104                     sizeof(RGBQUAD) * (1<< cClrBits));
105  
106      // There is no RGBQUAD array for the 24-bit-per-pixel format.
107  
108      else
109          pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
110                     sizeof(BITMAPINFOHEADER));
111  
112     // Initialize the fields in the BITMAPINFO structure.
113  
114     pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
115     pbmi->bmiHeader.biWidth = bmp.bmWidth;
116     pbmi->bmiHeader.biHeight = bmp.bmHeight;
117     pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
118     pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
119     if (cClrBits < 24)
120         pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
121  
122     // If the bitmap is not compressed, set the BI_RGB flag.
123     pbmi->bmiHeader.biCompression = BI_RGB;
124  
125     // Compute the number of bytes in the array of color
126     // indices and store the result in biSizeImage.
127     // For Windows NT/2000, the width must be DWORD aligned unless
128     // the bitmap is RLE compressed. This example shows this.
129     // For Windows 95/98, the width must be WORD aligned unless the
130     // bitmap is RLE compressed.
131     pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
132                                   * pbmi->bmiHeader.biHeight;
133     // Set biClrImportant to 0, indicating that all of the
134     // device colors are important.
135      pbmi->bmiHeader.biClrImportant = 0;
136      return pbmi;
137  }
138  
139 void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,
140                   HBITMAP hBMP, HDC hDC)
141  {
142      HANDLE hf;                 // file handle
143     BITMAPFILEHEADER hdr;       // bitmap file-header
144     PBITMAPINFOHEADER pbih;     // bitmap info-header
145     LPBYTE lpBits;              // memory pointer
146     DWORD dwTotal;              // total count of bytes
147     DWORD cb;                   // incremental count of bytes
148     BYTE *hp;                   // byte pointer
149     DWORD dwTmp;
150  
151     pbih = (PBITMAPINFOHEADER) pbi;
152     lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
153  
154     if (!lpBits)
155          return ;
156  
157     // Retrieve the color table (RGBQUAD array) and the bits
158     // (array of palette indices) from the DIB.
159     if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
160         DIB_RGB_COLORS))
161     {
162         return ;
163     }
164  
165     // Create the .BMP file.
166     hf = CreateFile(pszFile,
167                    GENERIC_READ | GENERIC_WRITE,
168                    (DWORD) 0,
169                     NULL,
170                    CREATE_ALWAYS,
171                    FILE_ATTRIBUTE_NORMAL,
172                    (HANDLE) NULL);
173     if (hf == INVALID_HANDLE_VALUE)
174         return ;
175     hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"
176     // Compute the size of the entire file.
177     hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
178                  pbih->biSize + pbih->biClrUsed
179                  * sizeof(RGBQUAD) + pbih->biSizeImage);
180     hdr.bfReserved1 = 0;
181     hdr.bfReserved2 = 0;
182  
183     // Compute the offset to the array of color indices.
184     hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
185                     pbih->biSize + pbih->biClrUsed
186                     * sizeof (RGBQUAD);
187  
188     // Copy the BITMAPFILEHEADER into the .BMP file.
189     if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
190         (LPDWORD) &dwTmp,  NULL))
191     {
192        return ;
193     }
194  
195     // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
196     if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
197                   + pbih->biClrUsed * sizeof (RGBQUAD),
198                   (LPDWORD) &dwTmp, ( NULL)))
199         return ;
200  
201     // Copy the array of color indices into the .BMP file.
202     dwTotal = cb = pbih->biSizeImage;
203     hp = lpBits;
204     if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
205            return ;
206  
207     // Close the .BMP file.
208      if (!CloseHandle(hf))
209            return ;
210  
211     // Free memory.
212     GlobalFree((HGLOBAL)lpBits);
213 }

另一种实现:
1 FILE *fp=fopen("back.bmp", "rb");
2 if(fp == 0)
3     return 1;
4  
5 fseek(fp, sizeof(BITMAPFILEHEADER), 0);
6 BITMAPINFOHEADER head;
7 fread(&head, sizeof(BITMAPINFOHEADER), 1, fp);
8 int bmpHeight = head.biHeight;
9 int bmpWidth = head.biWidth;
10 int biBitCount = head.biBitCount;
11 int lineByte = (bmpWidth*biBitCount/8+3)/4*4;
12 RGBQUAD *pColorTable;
13 if(biBitCount == 8)
14 {
15     pColorTable = new RGBQUAD[256];
16     fread(pColorTable, sizeof(RGBQUAD), 256, fp);
17 }
18 unsigned char *pBmpBuf = new unsigned char[lineByte*bmpHeight];
19 fread(pBmpBuf, 1, lineByte*bmpHeight, fp);
20  
21 CDC *m_pMemDC;
22 m_pMemDC = new CDC();
23 CDC *pDC;
24 pDC = GetDC();
25 m_pMemDC->CreateCompatibleDC(pDC);
26 CBitmap *m_pOldBmp = NULL;
27 CBitmap *m_pMemBmp = new CBitmap();       //根据图片的大小创建一个兼容位图
28 m_pMemBmp->CreateCompatibleBitmap(pDC, bmpWidth, bmpHeight);
29 m_pOldBmp = m_pMemDC->SelectObject(m_pMemBmp);
30  
31 // 把图像的数据绘制到兼容位图上
32  
33 SetDIBits(m_pMemDC->GetSafeHdc(), (HBITMAP)m_pMemBmp->m_hObject,
34     0, bmpHeight, (LPVOID)pBmpBuf, (BITMAPINFO*)&head, DIB_RGB_COLORS);
35 m_pMemDC->SetBkMode(TRANSPARENT);
36 m_pMemDC->SetTextColor(RGB(255, 0, 0));
37
38 //设置字体
39 CFont font;
40 font.CreateFont(10,10,0,0,10,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,OUT_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_SWISS,"宋体");
41 SelectObject(hMemDC, font);
42 // 添加文字到指定位置
43 m_pMemDC->TextOut(17, 10, "hello");
44  
45 unsigned char *pTemp = new unsigned char[lineByte*bmpHeight];
46 GetDIBits(m_pMemDC->GetSafeHdc(), (HBITMAP)m_pMemBmp->m_hObject, 0, bmpHeight,
47     (LPVOID)pTemp, (BITMAPINFO*)&head, DIB_RGB_COLORS);
48 fclose(fp);
49  
50 char bmpwrite[] = "c:\\2.bmp";
51 fp = fopen(bmpwrite,"wb");
52 BITMAPFILEHEADER fileHead;
53 fileHead.bfType = 0x4D42;
54 fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lineByte*bmpHeight;
55 fileHead.bfReserved1 = 0;
56 fileHead.bfReserved2 = 0;
57 fileHead.bfOffBits = 54;
58 fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
59  
60 fwrite(&head, sizeof(BITMAPINFOHEADER), 1, fp);
61 fwrite(pTemp, lineByte*bmpHeight, 1, fp);
62 fclose(fp);
63  
64 delete m_pMemBmp;
65 delete m_pMemDC;
66 delete[] pBmpBuf;
67 delete[] pTemp;

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出870入263汤圆

发表于 2015-6-15 21:18:19 | 显示全部楼层
用MFC还真是麻烦啊!在.net平台上,几句代码轻松就实现了的。

出0入0汤圆

发表于 2015-6-15 22:27:24 来自手机 | 显示全部楼层
C++选啥都行就是别选MFC,后来你就知道了,框架烂的一比,别的我也不知道谁更好,但是他是最烂的~

出0入0汤圆

发表于 2015-6-20 11:37:58 来自手机 | 显示全部楼层
用过qt以后,发誓再也不用mfc!

出0入0汤圆

发表于 2015-6-20 12:02:03 | 显示全部楼层
MFC只是难用,并没有那么烂吧,当年C++还没有那么多特性支持的时候搞出来的框架,只是现在更优秀的东西出现了,看着有点过时而已

出870入263汤圆

发表于 2015-6-20 22:53:50 | 显示全部楼层
关于界面设计,我知道一个比较好用:fltk。它是开源的跨平台界面库,是DirectUI型的,完全面向对象的设计思想。下面是Windows和linux下的示例截图,编译很简单:
Windows下效果:

Linux下效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-25 23:07

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表