Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

431 lines
9.8 KiB

  1. // HtmlDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "Html2Bmp.h"
  5. #include "HtmlDlg.h"
  6. #include "IParser.h"
  7. #include <fstream.h>
  8. #include <direct.h>
  9. #define TIMERID 1
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. /////////////////////////////////////////////////////////////////////////////
  16. // CHtmlDlg dialog
  17. CHtmlDlg::CHtmlDlg(CWnd* pParent /*=NULL*/)
  18. : CDialog(CHtmlDlg::IDD, pParent)
  19. {
  20. //{{AFX_DATA_INIT(CHtmlDlg)
  21. // NOTE: the ClassWizard will add member initialization here
  22. //}}AFX_DATA_INIT
  23. m_nTimerID = 0;
  24. }
  25. void CHtmlDlg::DoDataExchange(CDataExchange* pDX)
  26. {
  27. CDialog::DoDataExchange(pDX);
  28. //{{AFX_DATA_MAP(CHtmlDlg)
  29. // NOTE: the ClassWizard will add DDX and DDV calls here
  30. //}}AFX_DATA_MAP
  31. }
  32. BEGIN_MESSAGE_MAP(CHtmlDlg, CDialog)
  33. //{{AFX_MSG_MAP(CHtmlDlg)
  34. ON_WM_TIMER()
  35. //}}AFX_MSG_MAP
  36. END_MESSAGE_MAP()
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CHtmlDlg message handlers
  39. BOOL CHtmlDlg::OnInitDialog()
  40. {
  41. CDialog::OnInitDialog();
  42. if(m_OutputBitmapFile.IsEmpty())
  43. m_OutputBitmapFile = m_HtmlFile + _T(".bmp");
  44. if(m_HtmlFile.Left(2) != _T(":") && m_HtmlFile.Left(3) != _T("\\"))
  45. {
  46. char buffer[_MAX_PATH];
  47. _getcwd(buffer, _MAX_PATH);
  48. CString prefix(buffer);
  49. if(prefix.Right(1) != _T("\\"))
  50. prefix += _T("\\");
  51. m_HtmlFile = prefix + m_HtmlFile;
  52. }
  53. if(m_TemplateBitmapFile.IsEmpty())
  54. {
  55. m_BmpFile = GetTemplateBmp();
  56. if(m_BmpFile.Left(1) != _T(".") || m_BmpFile.Left(1) != _T("\\"))
  57. {
  58. char buffer[_MAX_PATH];
  59. _getcwd(buffer, _MAX_PATH);
  60. CString prefix(buffer);
  61. if(prefix.Right(1) != _T("\\"))
  62. prefix += _T("\\");
  63. m_BmpFile = prefix + m_BmpFile;
  64. }
  65. }
  66. else
  67. m_BmpFile = m_TemplateBitmapFile;
  68. CFile BmpFileTest;
  69. if(!BmpFileTest.Open(m_BmpFile, CFile::modeRead))
  70. {
  71. if(m_TemplateBitmapFile.IsEmpty())
  72. AfxMessageBox(_T("The target bitmap could not be located inside the HTML page:\n") + m_HtmlFile + _T("\nCheck the HTML page."));
  73. else
  74. AfxMessageBox(_T("The target bitmap could not be loaded:\n") + m_TemplateBitmapFile);
  75. EndDialog(1);
  76. return FALSE;
  77. }
  78. BITMAPFILEHEADER BmpFileTestHdr;
  79. DIBSECTION BmpFileTestDibSection;
  80. // file header
  81. BmpFileTest.Read(&BmpFileTestHdr, sizeof(BmpFileTestHdr));
  82. // BitmapInfoHeader
  83. BmpFileTest.Read(&BmpFileTestDibSection.dsBmih , sizeof(BmpFileTestDibSection.dsBmih));
  84. BmpFileTest.Close();
  85. m_biCompression = BmpFileTestDibSection.dsBmih.biCompression;
  86. m_bitw = BmpFileTestDibSection.dsBmih.biWidth;
  87. m_bith = BmpFileTestDibSection.dsBmih.biHeight;
  88. int ScreenX = GetSystemMetrics(SM_CXSCREEN);
  89. int ScreenY = GetSystemMetrics(SM_CYSCREEN);
  90. // SetWindowPos(&CWnd::wndTop, (ScreenX - m_bitw)/2, (ScreenY - m_bith)/2, m_bitw+10, m_bith+10, SWP_SHOWWINDOW);
  91. SetWindowPos(&CWnd::wndTop, 0, 0, ScreenX, ScreenY, SWP_SHOWWINDOW);
  92. VERIFY(m_htmlCtrl.CreateFromStatic(IDC_HTMLVIEW, this));
  93. m_htmlCtrl.MoveWindow(0, 0, ScreenX, ScreenY);
  94. // m_htmlCtrl.MoveWindow((ScreenX - m_bitw)/2, (ScreenY - m_bith)/2, ScreenX, ScreenY);
  95. m_htmlCtrl.Navigate(m_HtmlFile);
  96. m_nTimerID = SetTimer(TIMERID, 100, NULL);
  97. return TRUE; // return TRUE unless you set the focus to a control
  98. // EXCEPTION: OCX Property Pages should return FALSE
  99. }
  100. void CHtmlDlg::OnTimer(UINT nIDEvent)
  101. {
  102. if(nIDEvent == m_nTimerID )
  103. {
  104. // Don't know what gets all loaded into the page,
  105. // so wait until everything is loaded and then start creating the bitmap
  106. if(!m_htmlCtrl.GetBusy())
  107. {
  108. KillTimer(TIMERID);
  109. m_nTimerID = 0;
  110. Capture();
  111. EndDialog(1);
  112. }
  113. }
  114. CDialog::OnTimer(nIDEvent);
  115. }
  116. CString CHtmlDlg::GetTemplateBmp()
  117. {
  118. ifstream* pHtmlFile = new ifstream(m_HtmlFile, ios::nocreate);
  119. if(*pHtmlFile == NULL || pHtmlFile->bad())
  120. {
  121. delete pHtmlFile;
  122. return "";
  123. }
  124. else
  125. {
  126. pHtmlFile->seekg(0, ios::end);
  127. int size = pHtmlFile->tellg();
  128. pHtmlFile->seekg(0, ios::beg);
  129. unsigned char* buf = new unsigned char[size];
  130. pHtmlFile->read(buf, size);
  131. CString HtmlContent(buf);
  132. CIParser IParser(HtmlContent);
  133. delete pHtmlFile;
  134. return IParser.TemplateBitmapName;
  135. }
  136. }
  137. void CHtmlDlg::Capture()
  138. {
  139. CPaintDC dc(this); // device context for painting
  140. CDC memdc;
  141. memdc.CreateCompatibleDC(&dc);
  142. CBitmap Bitmap;
  143. if(!Bitmap.Attach(::LoadImage(NULL, m_BmpFile, IMAGE_BITMAP, 0, 0,
  144. LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE)))
  145. {
  146. AfxMessageBox(_T("The following bitmap could not be loaded:\n") + m_BmpFile);
  147. return;
  148. }
  149. DIBSECTION DibSection;
  150. ::GetObject(
  151. (HBITMAP)Bitmap, // handle to graphics object
  152. sizeof(DIBSECTION), // size of buffer for object information
  153. &DibSection // buffer for object information
  154. );
  155. BITMAP bmp;
  156. Bitmap.GetBitmap(&bmp);
  157. // int bitw = bmp.bmWidth;
  158. // int bith = bmp.bmHeight;
  159. int bmBitsPixel = bmp.bmBitsPixel;
  160. memdc.SelectObject(&Bitmap);
  161. memdc.BitBlt(0, 0, m_bitw, m_bith, &dc, 0, 0, SRCCOPY);
  162. // Convert the color format to a count of bits.
  163. int cClrBits = bmp.bmPlanes * bmp.bmBitsPixel;
  164. if (cClrBits == 1)
  165. cClrBits = 1;
  166. else if (cClrBits <= 4)
  167. cClrBits = 4;
  168. else if (cClrBits <= 8)
  169. cClrBits = 8;
  170. else if (cClrBits <= 16)
  171. cClrBits = 16;
  172. else if (cClrBits <= 24)
  173. cClrBits = 24;
  174. else cClrBits = 32;
  175. // Allocate memory for the BITMAPINFO structure. (This structure
  176. // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
  177. // data structures.)
  178. int nColors = 1 << cClrBits;
  179. RGBQUAD* pColors = new RGBQUAD[nColors];
  180. if(cClrBits != 24)
  181. {
  182. ::GetDIBColorTable(
  183. memdc.m_hDC, // handle to DC
  184. 0, // color table index of first entry
  185. nColors, // number of entries to retrieve
  186. pColors // array of color table entries
  187. );
  188. }
  189. CFile file;
  190. if(!file.Open(m_OutputBitmapFile, CFile::modeWrite | CFile::modeCreate))
  191. {
  192. AfxMessageBox(_T("The target bitmap could not be created:\n") + m_OutputBitmapFile);
  193. return;
  194. }
  195. // For Windows NT/2000, the width must be DWORD aligned unless
  196. // the bitmap is RLE compressed.
  197. // For Windows 95/98, the width must be WORD aligned unless the
  198. // bitmap is RLE compressed.
  199. int PictureSize = DWORD_ALIGNED(m_bitw * bmBitsPixel * 8) * m_bith / 8;
  200. unsigned char* buf;
  201. if(cClrBits == 4 && m_biCompression == BI_RLE4
  202. || cClrBits == 8 && m_biCompression == BI_RLE8)
  203. buf = Compress((DibSection.dsBmih.biCompression = m_biCompression), (unsigned char*)DibSection.dsBm.bmBits, m_bitw, PictureSize);
  204. else
  205. {
  206. buf = (unsigned char*)DibSection.dsBm.bmBits;
  207. DibSection.dsBmih.biCompression = BI_RGB;
  208. }
  209. DibSection.dsBmih.biSizeImage = PictureSize;
  210. /*
  211. biCompression
  212. Specifies the type of compression for a compressed bottom-up bitmap
  213. (top-down DIBs cannot be compressed). This member can be one of the following values.
  214. Value Description
  215. BI_RGB An uncompressed format.
  216. BI_RLE8 A run-length encoded (RLE) format for bitmaps with 8 bpp.
  217. The compression format is a 2-byte format consisting of a count byte followed
  218. by a byte containing a color index. For more information, see Bitmap Compression.
  219. BI_RLE4 An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format
  220. consisting of a count byte followed by two word-length color indexes.
  221. For more information, see Bitmap Compression.
  222. */
  223. // Fill in the fields of the file header
  224. BITMAPFILEHEADER hdr;
  225. hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
  226. hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
  227. DibSection.dsBmih.biSize + DibSection.dsBmih.biClrUsed
  228. * sizeof(RGBQUAD) + DibSection.dsBmih.biSizeImage);
  229. hdr.bfReserved1 = 0;
  230. hdr.bfReserved2 = 0;
  231. hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
  232. DibSection.dsBmih.biSize + DibSection.dsBmih.biClrUsed
  233. * sizeof (RGBQUAD);
  234. // Write the file header
  235. file.Write(&hdr, sizeof(hdr));
  236. // BitmapInfoHeader
  237. file.Write(&DibSection.dsBmih , sizeof(DibSection.dsBmih));
  238. // Color table
  239. if(cClrBits != 24)
  240. file.Write(pColors , DibSection.dsBmih.biClrUsed * sizeof (RGBQUAD));
  241. // Write the bits
  242. file.Write(buf, PictureSize);
  243. }
  244. unsigned char* CHtmlDlg::Compress(int cMode, unsigned char* bmBits, int width, int& PictureSize)
  245. {
  246. if(cMode == BI_RLE4)
  247. {
  248. unsigned char* buf = new unsigned char[2*PictureSize+1];
  249. ZeroMemory(buf, 2*PictureSize+1);
  250. int cIndex = 0;
  251. int cSize = 0;
  252. int LineCount = 0;
  253. unsigned char c;
  254. int i = 0;
  255. while(i < PictureSize)
  256. {
  257. c = bmBits[i++];
  258. cSize = 1;
  259. while(i < PictureSize)
  260. {
  261. LineCount += 2; // 2 pixel pro Byte
  262. if(bmBits[i] == c && cSize < 127 && LineCount < width)
  263. {
  264. cSize++;
  265. }
  266. else
  267. {
  268. buf[cIndex++] = 2*cSize; // 2 pixel pro Byte
  269. buf[cIndex++] = c;
  270. if(LineCount >= width)
  271. {
  272. LineCount = 0;
  273. buf[cIndex++] = 0;
  274. buf[cIndex++] = 0;
  275. }
  276. break;
  277. }
  278. i++;
  279. }
  280. }
  281. // und den Rest noch bearbeiten
  282. if(cSize > 1)
  283. {
  284. buf[cIndex++] = 2*cSize;
  285. buf[cIndex++] = c;
  286. }
  287. PictureSize = cIndex;
  288. return buf;
  289. }
  290. else
  291. if(cMode == BI_RLE8)
  292. {
  293. unsigned char* buf = new unsigned char[2*PictureSize+1];
  294. ZeroMemory(buf, 2*PictureSize+1);
  295. int cIndex = 0;
  296. int cSize = 0;
  297. int LineCount = 0;
  298. unsigned char c;
  299. int i = 0;
  300. while(i < PictureSize)
  301. {
  302. c = bmBits[i++];
  303. cSize = 1;
  304. while(i < PictureSize)
  305. {
  306. LineCount++;
  307. if(bmBits[i] == c && cSize < 127 && LineCount < width)
  308. {
  309. cSize++;
  310. }
  311. else
  312. {
  313. buf[cIndex++] = (unsigned char)cSize;
  314. buf[cIndex++] = c;
  315. if(LineCount >= width)
  316. {
  317. LineCount = 0;
  318. buf[cIndex++] = 0;
  319. buf[cIndex++] = 0;
  320. }
  321. break;
  322. }
  323. i++;
  324. }
  325. }
  326. // und den Rest noch bearbeiten
  327. if(cSize > 1)
  328. {
  329. buf[cIndex++] = (unsigned char)cSize;
  330. buf[cIndex++] = c;
  331. }
  332. PictureSize = cIndex;
  333. return buf;
  334. }
  335. return bmBits;
  336. }