// HtmlDlg.cpp : implementation file // #include "stdafx.h" #include "Html2Bmp.h" #include "HtmlDlg.h" #include "IParser.h" #include #include #define TIMERID 1 #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CHtmlDlg dialog CHtmlDlg::CHtmlDlg(CWnd* pParent /*=NULL*/) : CDialog(CHtmlDlg::IDD, pParent) { //{{AFX_DATA_INIT(CHtmlDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_nTimerID = 0; } void CHtmlDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CHtmlDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CHtmlDlg, CDialog) //{{AFX_MSG_MAP(CHtmlDlg) ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CHtmlDlg message handlers BOOL CHtmlDlg::OnInitDialog() { CDialog::OnInitDialog(); if(m_OutputBitmapFile.IsEmpty()) m_OutputBitmapFile = m_HtmlFile + _T(".bmp"); if(m_HtmlFile.Left(2) != _T(":") && m_HtmlFile.Left(3) != _T("\\")) { char buffer[_MAX_PATH]; _getcwd(buffer, _MAX_PATH); CString prefix(buffer); if(prefix.Right(1) != _T("\\")) prefix += _T("\\"); m_HtmlFile = prefix + m_HtmlFile; } if(m_TemplateBitmapFile.IsEmpty()) { m_BmpFile = GetTemplateBmp(); if(m_BmpFile.Left(1) != _T(".") || m_BmpFile.Left(1) != _T("\\")) { char buffer[_MAX_PATH]; _getcwd(buffer, _MAX_PATH); CString prefix(buffer); if(prefix.Right(1) != _T("\\")) prefix += _T("\\"); m_BmpFile = prefix + m_BmpFile; } } else m_BmpFile = m_TemplateBitmapFile; CFile BmpFileTest; if(!BmpFileTest.Open(m_BmpFile, CFile::modeRead)) { if(m_TemplateBitmapFile.IsEmpty()) AfxMessageBox(_T("The target bitmap could not be located inside the HTML page:\n") + m_HtmlFile + _T("\nCheck the HTML page.")); else AfxMessageBox(_T("The target bitmap could not be loaded:\n") + m_TemplateBitmapFile); EndDialog(1); return FALSE; } BITMAPFILEHEADER BmpFileTestHdr; DIBSECTION BmpFileTestDibSection; // file header BmpFileTest.Read(&BmpFileTestHdr, sizeof(BmpFileTestHdr)); // BitmapInfoHeader BmpFileTest.Read(&BmpFileTestDibSection.dsBmih , sizeof(BmpFileTestDibSection.dsBmih)); BmpFileTest.Close(); m_biCompression = BmpFileTestDibSection.dsBmih.biCompression; m_bitw = BmpFileTestDibSection.dsBmih.biWidth; m_bith = BmpFileTestDibSection.dsBmih.biHeight; int ScreenX = GetSystemMetrics(SM_CXSCREEN); int ScreenY = GetSystemMetrics(SM_CYSCREEN); // SetWindowPos(&CWnd::wndTop, (ScreenX - m_bitw)/2, (ScreenY - m_bith)/2, m_bitw+10, m_bith+10, SWP_SHOWWINDOW); SetWindowPos(&CWnd::wndTop, 0, 0, ScreenX, ScreenY, SWP_SHOWWINDOW); VERIFY(m_htmlCtrl.CreateFromStatic(IDC_HTMLVIEW, this)); m_htmlCtrl.MoveWindow(0, 0, ScreenX, ScreenY); // m_htmlCtrl.MoveWindow((ScreenX - m_bitw)/2, (ScreenY - m_bith)/2, ScreenX, ScreenY); m_htmlCtrl.Navigate(m_HtmlFile); m_nTimerID = SetTimer(TIMERID, 100, NULL); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CHtmlDlg::OnTimer(UINT nIDEvent) { if(nIDEvent == m_nTimerID ) { // Don't know what gets all loaded into the page, // so wait until everything is loaded and then start creating the bitmap if(!m_htmlCtrl.GetBusy()) { KillTimer(TIMERID); m_nTimerID = 0; Capture(); EndDialog(1); } } CDialog::OnTimer(nIDEvent); } CString CHtmlDlg::GetTemplateBmp() { ifstream* pHtmlFile = new ifstream(m_HtmlFile, ios::nocreate); if(*pHtmlFile == NULL || pHtmlFile->bad()) { delete pHtmlFile; return ""; } else { pHtmlFile->seekg(0, ios::end); int size = pHtmlFile->tellg(); pHtmlFile->seekg(0, ios::beg); unsigned char* buf = new unsigned char[size]; pHtmlFile->read(buf, size); CString HtmlContent(buf); CIParser IParser(HtmlContent); delete pHtmlFile; return IParser.TemplateBitmapName; } } void CHtmlDlg::Capture() { CPaintDC dc(this); // device context for painting CDC memdc; memdc.CreateCompatibleDC(&dc); CBitmap Bitmap; if(!Bitmap.Attach(::LoadImage(NULL, m_BmpFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE))) { AfxMessageBox(_T("The following bitmap could not be loaded:\n") + m_BmpFile); return; } DIBSECTION DibSection; ::GetObject( (HBITMAP)Bitmap, // handle to graphics object sizeof(DIBSECTION), // size of buffer for object information &DibSection // buffer for object information ); BITMAP bmp; Bitmap.GetBitmap(&bmp); // int bitw = bmp.bmWidth; // int bith = bmp.bmHeight; int bmBitsPixel = bmp.bmBitsPixel; memdc.SelectObject(&Bitmap); memdc.BitBlt(0, 0, m_bitw, m_bith, &dc, 0, 0, SRCCOPY); // Convert the color format to a count of bits. int cClrBits = bmp.bmPlanes * bmp.bmBitsPixel; if (cClrBits == 1) cClrBits = 1; else if (cClrBits <= 4) cClrBits = 4; else if (cClrBits <= 8) cClrBits = 8; else if (cClrBits <= 16) cClrBits = 16; else if (cClrBits <= 24) cClrBits = 24; else cClrBits = 32; // Allocate memory for the BITMAPINFO structure. (This structure // contains a BITMAPINFOHEADER structure and an array of RGBQUAD // data structures.) int nColors = 1 << cClrBits; RGBQUAD* pColors = new RGBQUAD[nColors]; if(cClrBits != 24) { ::GetDIBColorTable( memdc.m_hDC, // handle to DC 0, // color table index of first entry nColors, // number of entries to retrieve pColors // array of color table entries ); } CFile file; if(!file.Open(m_OutputBitmapFile, CFile::modeWrite | CFile::modeCreate)) { AfxMessageBox(_T("The target bitmap could not be created:\n") + m_OutputBitmapFile); return; } // For Windows NT/2000, the width must be DWORD aligned unless // the bitmap is RLE compressed. // For Windows 95/98, the width must be WORD aligned unless the // bitmap is RLE compressed. int PictureSize = DWORD_ALIGNED(m_bitw * bmBitsPixel * 8) * m_bith / 8; unsigned char* buf; if(cClrBits == 4 && m_biCompression == BI_RLE4 || cClrBits == 8 && m_biCompression == BI_RLE8) buf = Compress((DibSection.dsBmih.biCompression = m_biCompression), (unsigned char*)DibSection.dsBm.bmBits, m_bitw, PictureSize); else { buf = (unsigned char*)DibSection.dsBm.bmBits; DibSection.dsBmih.biCompression = BI_RGB; } DibSection.dsBmih.biSizeImage = PictureSize; /* biCompression Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed). This member can be one of the following values. Value Description BI_RGB An uncompressed format. BI_RLE8 A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte format consisting of a count byte followed by a byte containing a color index. For more information, see Bitmap Compression. BI_RLE4 An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting of a count byte followed by two word-length color indexes. For more information, see Bitmap Compression. */ // Fill in the fields of the file header BITMAPFILEHEADER hdr; hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM" hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + DibSection.dsBmih.biSize + DibSection.dsBmih.biClrUsed * sizeof(RGBQUAD) + DibSection.dsBmih.biSizeImage); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + DibSection.dsBmih.biSize + DibSection.dsBmih.biClrUsed * sizeof (RGBQUAD); // Write the file header file.Write(&hdr, sizeof(hdr)); // BitmapInfoHeader file.Write(&DibSection.dsBmih , sizeof(DibSection.dsBmih)); // Color table if(cClrBits != 24) file.Write(pColors , DibSection.dsBmih.biClrUsed * sizeof (RGBQUAD)); // Write the bits file.Write(buf, PictureSize); } unsigned char* CHtmlDlg::Compress(int cMode, unsigned char* bmBits, int width, int& PictureSize) { if(cMode == BI_RLE4) { unsigned char* buf = new unsigned char[2*PictureSize+1]; ZeroMemory(buf, 2*PictureSize+1); int cIndex = 0; int cSize = 0; int LineCount = 0; unsigned char c; int i = 0; while(i < PictureSize) { c = bmBits[i++]; cSize = 1; while(i < PictureSize) { LineCount += 2; // 2 pixel pro Byte if(bmBits[i] == c && cSize < 127 && LineCount < width) { cSize++; } else { buf[cIndex++] = 2*cSize; // 2 pixel pro Byte buf[cIndex++] = c; if(LineCount >= width) { LineCount = 0; buf[cIndex++] = 0; buf[cIndex++] = 0; } break; } i++; } } // und den Rest noch bearbeiten if(cSize > 1) { buf[cIndex++] = 2*cSize; buf[cIndex++] = c; } PictureSize = cIndex; return buf; } else if(cMode == BI_RLE8) { unsigned char* buf = new unsigned char[2*PictureSize+1]; ZeroMemory(buf, 2*PictureSize+1); int cIndex = 0; int cSize = 0; int LineCount = 0; unsigned char c; int i = 0; while(i < PictureSize) { c = bmBits[i++]; cSize = 1; while(i < PictureSize) { LineCount++; if(bmBits[i] == c && cSize < 127 && LineCount < width) { cSize++; } else { buf[cIndex++] = (unsigned char)cSize; buf[cIndex++] = c; if(LineCount >= width) { LineCount = 0; buf[cIndex++] = 0; buf[cIndex++] = 0; } break; } i++; } } // und den Rest noch bearbeiten if(cSize > 1) { buf[cIndex++] = (unsigned char)cSize; buf[cIndex++] = c; } PictureSize = cIndex; return buf; } return bmBits; }