I am editing MFC program which is changed version (not by me) of Microsoft DIBLOOK sample. This program alow to open DIB image, edit it and show result in another window. Open images are showed in windows with scrollbars and edited (result) images are showed in windows without scrollbars. I want windows with edited images (result) to have scrollbars. How to do that windows with edited images have scrollbars? Could you help me? I have pasted code of the most important files below. I added other project files in attachements into DIBLOOK2.zip. I also added sample DIB image in LENA1X2.zip attachement. Microsoft DIBLOOK sample is created for Visual Studio 6 but this version is upgrade (not by me) for Visual Studio 2010. diview.cpp file (void CDibView::OperationOnCopy(pfnCDibDoc op) is method which show edited image, void CDibView::OnGray() cause image operation): Code: #include "stdafx.h" #include "diblook.h" #include "dibdoc.h" #include "dibview.h" #include "OutDoc.h" #include "dibapi.h" #include "mainfrm.h" #include "parametr.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDibView IMPLEMENT_DYNCREATE(CDibView, CScrollView) BEGIN_MESSAGE_MAP(CDibView, CScrollView) //{{AFX_MSG_MAP(CDibView) ON_COMMAND(ID_EDIT_COPY, OnEditCopy) ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy) ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) ON_MESSAGE(WM_DOREALIZE, OnDoRealize) ON_COMMAND(ID_GRAY, OnGray) ON_COMMAND(ID_BLOCK, OnBlock) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDibView construction/destruction CDibView::CDibView() { } CDibView::~CDibView() { } ///////////////////////////////////////////////////////////////////////////// // CDibView drawing void CDibView::OnDraw(CDC* pDC) { CDibDoc* pDoc = GetDocument(); this->EnableScrollBar(SB_BOTH); HDIB hDIB = pDoc->GetHDIB(); if (hDIB != NULL) { LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); int cxDIB = (int) ::DIBWidth(lpDIB); // Size of DIB - x int cyDIB = (int) ::DIBHeight(lpDIB); // Size of DIB - y ::GlobalUnlock((HGLOBAL) hDIB); CRect rcDIB; rcDIB.top = rcDIB.left = 0; rcDIB.right = cxDIB; rcDIB.bottom = cyDIB; CRect rcDest; if (pDC->IsPrinting()) // printer DC { // get size of printer page (in pixels) int cxPage = pDC->GetDeviceCaps(HORZRES); int cyPage = pDC->GetDeviceCaps(VERTRES); // get printer pixels per inch int cxInch = pDC->GetDeviceCaps(LOGPIXELSX); int cyInch = pDC->GetDeviceCaps(LOGPIXELSY); // // Best Fit case -- create a rectangle which preserves // the DIB's aspect ratio, and fills the page horizontally. // // The formula in the "->bottom" field below calculates the Y // position of the printed bitmap, based on the size of the // bitmap, the width of the page, and the relative size of // a printed pixel (cyInch / cxInch). // rcDest.top = rcDest.left = 0; rcDest.bottom = (int)(((double)cyDIB * cxPage * cyInch) / ((double)cxDIB * cxInch)); rcDest.right = cxPage; } else // not printer DC { rcDest = rcDIB; } ::PaintDIB(pDC->m_hDC, &rcDest, pDoc->GetHDIB(), &rcDIB, pDoc->GetDocPalette()); } } ///////////////////////////////////////////////////////////////////////////// // CDibView printing BOOL CDibView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } ///////////////////////////////////////////////////////////////////////////// // CDibView commands LRESULT CDibView::OnDoRealize(WPARAM wParam, LPARAM) { ASSERT(wParam != NULL); CDibDoc* pDoc = GetDocument(); if (pDoc->GetHDIB() == NULL) return 0L; // must be a new document CPalette* pPal = pDoc->GetDocPalette(); if (pPal != NULL) { CMainFrame* pAppFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd; ASSERT_KINDOF(CMainFrame, pAppFrame); CClientDC appDC(pAppFrame); // All views but one should be a background palette. // wParam contains a handle to the active view, so the SelectPalette // bForceBackground flag is FALSE only if wParam == m_hWnd (this view) CPalette* oldPalette = appDC.SelectPalette(pPal, ((HWND)wParam) != m_hWnd); if (oldPalette != NULL) { UINT nColorsChanged = appDC.RealizePalette(); if (nColorsChanged > 0) pDoc->UpdateAllViews(NULL); appDC.SelectPalette(oldPalette, TRUE); } else { TRACE0("\tSelectPalette failed in CDibView::OnPaletteChanged\n"); } } return 0L; } void CDibView::OnInitialUpdate() { CScrollView::OnInitialUpdate(); ASSERT(GetDocument() != NULL); SetScrollSizes(MM_TEXT, GetDocument()->GetDocSize()); } void CDibView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView); if (bActivate) { ASSERT(pActivateView == this); OnDoRealize((WPARAM)m_hWnd, 0); // same as SendMessage(WM_DOREALIZE); } } void CDibView::OnEditCopy() { CDibDoc* pDoc = GetDocument(); // Clean clipboard of contents, and copy the DIB. if (OpenClipboard()) { BeginWaitCursor(); EmptyClipboard(); SetClipboardData (CF_DIB, CopyHandle((HANDLE) pDoc->GetHDIB()) ); CloseClipboard(); EndWaitCursor(); } } void CDibView::OnUpdateEditCopy(CCmdUI* pCmdUI) { pCmdUI->Enable(GetDocument()->GetHDIB() != NULL); } void CDibView::OnEditPaste() { HDIB hNewDIB = NULL; if (OpenClipboard()) { BeginWaitCursor(); hNewDIB = (HDIB) CopyHandle(::GetClipboardData(CF_DIB)); CloseClipboard(); if (hNewDIB != NULL) { CDibDoc* pDoc = GetDocument(); pDoc->ReplaceHDIB(hNewDIB); // and free the old DIB pDoc->InitDIBData(); // set up new size & palette pDoc->SetModifiedFlag(TRUE); SetScrollSizes(MM_TEXT, pDoc->GetDocSize()); OnDoRealize((WPARAM)m_hWnd,0); // realize the new palette pDoc->UpdateAllViews(NULL); } EndWaitCursor(); } } void CDibView::OnUpdateEditPaste(CCmdUI* pCmdUI) { pCmdUI->Enable(::IsClipboardFormatAvailable(CF_DIB)); } void CDibView::OperationOnCopy(pfnCDibDoc op) { BeginWaitCursor(); CDibDoc* pDoc = GetDocument(); CDibDoc* pDst = (CDibDoc*)((CDibLookApp*)AfxGetApp())->m_imageTemplate->OpenDocumentFile(NULL); HDIB hNewDIB = (HDIB) CopyHandle((HANDLE) pDoc->GetHDIB()) ; if (hNewDIB != NULL) { pDst->ReplaceHDIB(hNewDIB); // and free the old DIB this->EnableScrollBar(SB_BOTH); //my attempt at forcing scrollbars (pDst->*op)(this) ; // CPOO tu operacja POSITION pos = pDst->GetFirstViewPosition(); pDst->GetNextView(pos)->EnableScrollBar(SB_BOTH);//my attempt at forcing scrollbars pDst->InitDIBData(); // set up new size & palette pDst->SetModifiedFlag(TRUE); SetScrollSizes(MM_TEXT, pDst->GetDocSize()); //this nothing change OnDoRealize((WPARAM)m_hWnd,0); // realize the new palette pDst->UpdateAllViews(NULL); } EndWaitCursor(); } void CDibView::OnGray() { OperationOnCopy(&CDibDoc::ConvertToGrayImage) ; } dibdoc.cpp (void CDibDoc::ConvertToGrayImage(CView *view) is operation performed on image): Code: #include "stdafx.h" #include "diblook.h" #include <limits.h> #include <string.h> #include "dibdoc.h" #include "dibview.h" #include "outDoc.h" #include "afxext.h" #include <cmath> #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDibDoc IMPLEMENT_DYNCREATE(CDibDoc, CDocument) BEGIN_MESSAGE_MAP(CDibDoc, CDocument) //{{AFX_MSG_MAP(CDibDoc) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDibDoc construction/destruction int CDibDoc::m_size = 8; CDibDoc::CDibDoc() { m_hDIB = NULL; m_palDIB = NULL; m_sizeDoc = CSize(1,1); // dummy value to make CScrollView happy m_outputView = NULL ; } CDibDoc::~CDibDoc() { if (m_hDIB != NULL) { ::GlobalFree((HGLOBAL) m_hDIB); } if (m_palDIB != NULL) { delete m_palDIB; } } BOOL CDibDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; return TRUE; } void CDibDoc::InitDIBData() { if (m_palDIB != NULL) { delete m_palDIB; m_palDIB = NULL; } if (m_hDIB == NULL) { return; } // Set up document size LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); if (::DIBWidth(lpDIB) > INT_MAX ||::DIBHeight(lpDIB) > INT_MAX) { ::GlobalUnlock((HGLOBAL) m_hDIB); ::GlobalFree((HGLOBAL) m_hDIB); m_hDIB = NULL; CString strMsg; strMsg.LoadString(IDS_DIB_TOO_BIG); MessageBox(NULL, strMsg, NULL, MB_ICONINFORMATION | MB_OK); return; } m_sizeDoc = CSize((int) ::DIBWidth(lpDIB), (int) ::DIBHeight(lpDIB)); ::GlobalUnlock((HGLOBAL) m_hDIB); // Create copy of palette m_palDIB = new CPalette; if (m_palDIB == NULL) { // we must be really low on memory ::GlobalFree((HGLOBAL) m_hDIB); m_hDIB = NULL; return; } if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL) { // DIB may not have a palette delete m_palDIB; m_palDIB = NULL; return; } } BOOL CDibDoc::OnOpenDocument(LPCTSTR lpszPathName) { CFile file; CFileException fe; if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite, &fe)) { ReportSaveLoadException(lpszPathName, &fe, FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); return FALSE; } DeleteContents(); BeginWaitCursor(); // replace calls to Serialize with ReadDIBFile function TRY { m_hDIB = ::ReadDIBFile(file); } CATCH (CFileException, eLoad) { file.Abort(); // will not throw an exception EndWaitCursor(); ReportSaveLoadException(lpszPathName, eLoad, FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); m_hDIB = NULL; return FALSE; } END_CATCH InitDIBData(); EndWaitCursor(); if (m_hDIB == NULL) { // may not be DIB format CString strMsg; strMsg.LoadString(IDS_CANNOT_LOAD_DIB); MessageBox(NULL, strMsg, NULL, MB_ICONINFORMATION | MB_OK); return FALSE; } SetPathName(lpszPathName); SetModifiedFlag(FALSE); // start off with unmodified return TRUE; } BOOL CDibDoc::OnSaveDocument(LPCTSTR lpszPathName) { CFile file; CFileException fe; if (!file.Open(lpszPathName, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive, &fe)) { ReportSaveLoadException(lpszPathName, &fe, TRUE, AFX_IDP_INVALID_FILENAME); return FALSE; } // replace calls to Serialize with SaveDIB function BOOL bSuccess = FALSE; TRY { BeginWaitCursor(); bSuccess = ::SaveDIB(m_hDIB, file); file.Close(); } CATCH (CException, eSave) { file.Abort(); // will not throw an exception EndWaitCursor(); ReportSaveLoadException(lpszPathName, eSave, TRUE, AFX_IDP_FAILED_TO_SAVE_DOC); return FALSE; } END_CATCH EndWaitCursor(); SetModifiedFlag(FALSE); // back to unmodified if (!bSuccess) { // may be other-style DIB (load supported but not save) // or other problem in SaveDIB CString strMsg; strMsg.LoadString(IDS_CANNOT_SAVE_DIB); MessageBox(NULL, strMsg, NULL, MB_ICONINFORMATION | MB_OK); } return bSuccess; } void CDibDoc::ReplaceHDIB(HDIB hDIB) { if (m_hDIB != NULL) { ::GlobalFree((HGLOBAL) m_hDIB); } m_hDIB = hDIB; } ///////////////////////////////////////////////////////////////////////////// // CDibDoc diagnostics #ifdef _DEBUG void CDibDoc::AssertValid() const { CDocument::AssertValid(); } void CDibDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CDibDoc commands void CDibDoc::ConvertToGrayImage(CView *view) //Rozpoznaje literę M z loga MODECOM { view->EnableScrollBar(SB_BOTH); //my attempt at forcing scrollbars RGBTRIPLE* rows[50000] ; int width, height ; if (GetDIBRowsRGB(m_hDIB,rows,&width,&height)) { for (int x=0;x<width;x++) { for (int y=0;y<height;y++) { int gray = rows[y][x].rgbtBlue+rows[y][x].rgbtRed+rows[y][x].rgbtGreen; if (gray < 500) { rows[y][x].rgbtBlue = 0; rows[y][x].rgbtRed = 0; rows[y][x].rgbtGreen = 0; } else { rows[y][x].rgbtBlue = 255; rows[y][x].rgbtRed = 255; rows[y][x].rgbtGreen = 255; } } } FreeDIBRows(m_hDIB); } UpdateAllViews(NULL); } diblook.cpp: Code: #include "stdafx.h" #include "diblook.h" #include "mainfrm.h" #include "dibdoc.h" #include "dibview.h" #include "outdoc.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDibLookApp BEGIN_MESSAGE_MAP(CDibLookApp, CWinApp) //{{AFX_MSG_MAP(CDibLookApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) //}}AFX_MSG_MAP // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDibLookApp construction // Place all significant initialization in InitInstance CDibLookApp::CDibLookApp() { } ///////////////////////////////////////////////////////////////////////////// // The one and only CDibLookApp object CDibLookApp NEAR theApp; ///////////////////////////////////////////////////////////////////////////// // CDibLookApp initialization BOOL CDibLookApp::InitInstance() { // Standard initialization // (if you are not using these features and wish to reduce the size // of your final executable, you should remove the following initialization Enable3dControls(); // Use 3d controls in dialogs LoadStdProfileSettings(); // Load standard INI file options (including MRU) // Register document templates which serve as connection between // documents and views. Views are contained in the specified view m_imageTemplate = new CMultiDocTemplate(IDR_DIBTYPE, RUNTIME_CLASS(CDibDoc), RUNTIME_CLASS(CMDIChildWnd), // standard MDI child frame RUNTIME_CLASS(CDibView)) ; AddDocTemplate(m_imageTemplate); m_outputTemplate = new CMultiDocTemplate(IDR_TEXTTYPE, RUNTIME_CLASS(COutputDoc), RUNTIME_CLASS(CMDIChildWnd), RUNTIME_CLASS(CEditView)) ; //AddDocTemplate(m_outputTemplate); // create main MDI Frame window CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); m_pMainWnd = pMainFrame; // enable file manager drag/drop and DDE Execute open m_pMainWnd->DragAcceptFiles(); EnableShellOpen(); RegisterShellFileTypes(TRUE); // Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing ; ParseCommandLine(cmdInfo); // Dispatch commands specified on the command line if (!ProcessShellCommand(cmdInfo)) return FALSE; return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // Implementation protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //{{AFX_MSG(CAboutDlg) // No message handlers //}}AFX_MSG DECLARE_MESSAGE_MAP() }; void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() mainfrm.cpp: Code: #include "stdafx.h" #include "diblook.h" #include "mainfrm.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMainFrame IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_WM_PALETTECHANGED() ON_WM_QUERYNEWPALETTE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // arrays of IDs used to initialize control bars // toolbar buttons - IDs are command buttons static UINT BASED_CODE buttons[] = { // same order as in the bitmap 'toolbar.bmp' ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE, ID_SEPARATOR, ID_EDIT_CUT, ID_EDIT_COPY, ID_EDIT_PASTE, ID_SEPARATOR, ID_FILE_PRINT, ID_APP_ABOUT, }; static UINT BASED_CODE indicators[] = { ID_SEPARATOR, // status line indicator ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, }; ///////////////////////////////////////////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { } CMainFrame::~CMainFrame() { } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.Create(this) || !m_wndToolBar.LoadBitmap(IDR_MAINFRAME) || !m_wndToolBar.SetButtons(buttons, sizeof(buttons)/sizeof(UINT))) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } return 0; } ///////////////////////////////////////////////////////////////////////////// // CMainFrame commands void CMainFrame::OnPaletteChanged(CWnd* pFocusWnd) { CMDIFrameWnd::OnPaletteChanged(pFocusWnd); // always realize the palette for the active view CMDIChildWnd* pMDIChildWnd = MDIGetActive(); if (pMDIChildWnd == NULL) return; // no active MDI child frame CView* pView = pMDIChildWnd->GetActiveView(); ASSERT(pView != NULL); pView->EnableScrollBar(SB_BOTH); // notify all child windows that the palette has changed SendMessageToDescendants(WM_DOREALIZE, (WPARAM)pView->m_hWnd); } BOOL CMainFrame::OnQueryNewPalette() { // always realize the palette for the active view CMDIChildWnd* pMDIChildWnd = MDIGetActive(); if (pMDIChildWnd == NULL) return FALSE; // no active MDI child frame (no new palette) CView* pView = pMDIChildWnd->GetActiveView(); ASSERT(pView != NULL); // just notify the target view pView->SendMessage(WM_DOREALIZE, (WPARAM)pView->m_hWnd); return TRUE; } myfile.cpp: Code: #include "stdafx.h" #include <math.h> #include <io.h> #include <direct.h> #include "dibapi.h" /* * Dib Header Marker - used in writing DIBs to files */ #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') #ifdef _MAC #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x)) #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x))) void ByteSwapHeader(BITMAPFILEHEADER* bmiHeader); void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header); #endif /************************************************************************* * * SaveDIB() * * Saves the specified DIB into the specified CFile. The CFile * is opened and closed by the caller. * * Parameters: * * HDIB hDib - Handle to the dib to save * * CFile& file - open CFile used to save DIB * * Return value: TRUE if successful, else FALSE or CFileException * *************************************************************************/ BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) { BITMAPFILEHEADER bmfHdr; // Header for Bitmap file LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure DWORD dwDIBSize; if (hDib == NULL) return FALSE; /* * Get a pointer to the DIB memory, the first of which contains * a BITMAPINFO structure */ lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); if (lpBI == NULL) return FALSE; if (!IS_WIN30_DIB(lpBI)) { ::GlobalUnlock((HGLOBAL) hDib); return FALSE; // It's an other-style DIB (save not supported) } /* * Fill in the fields of the file header */ /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ bmfHdr.bfType = DIB_HEADER_MARKER; // "BM" // Calculating the size of the DIB is a bit tricky (if we want to // do it right). The easiest way to do this is to call GlobalSize() // on our global handle, but since the size of our global memory may have // been padded a few bytes, we may end up writing out a few too // many bytes to the file (which may cause problems with some apps). // // So, instead let's calculate the size manually (if we can) // // First, find size of header plus size of color table. Since the // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains // the size of the structure, let's use this. dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // Partial Calculation // Now calculate the size of the image if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) { // It's an RLE bitmap, we can't calculate size, so trust the // biSizeImage field dwDIBSize += lpBI->biSizeImage; } else { DWORD dwBmBitsSize; // Size of Bitmap Bits only // It's not RLE, so size is Width (DWORD aligned) * Height dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; dwDIBSize += dwBmBitsSize; // Now, since we have calculated the correct size, why don't we // fill in the biSizeImage field (this will fix any .BMP files which // have this field incorrect). lpBI->biSizeImage = dwBmBitsSize; } // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; /* * Now, calculate the offset the actual bitmap bits will be in * the file -- It's the Bitmap file header plus the DIB header, * plus the size of the color table. */ bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPSTR)lpBI); #ifdef _MAC ByteSwapHeader(&bmfHdr); // First swap the size field *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI)); // Now swap the rest of the structure (we don't save < Win30 files) ByteSwapInfo((LPSTR)lpBI, TRUE); #endif TRY { // Write the file header file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // // Write the DIB header and the bits // file.Write(lpBI, dwDIBSize); } CATCH (CFileException, e) { #ifdef _MAC // Swap everything back *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI)); ByteSwapInfo((LPSTR)lpBI, TRUE); #endif ::GlobalUnlock((HGLOBAL) hDib); THROW_LAST(); } END_CATCH #ifdef _MAC // Swap everything back *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI)); ByteSwapInfo((LPSTR)lpBI, TRUE); #endif ::GlobalUnlock((HGLOBAL) hDib); return TRUE; } /************************************************************************* Function: ReadDIBFile (CFile&) Purpose: Reads in the specified DIB file into a global chunk of memory. Returns: A handle to a dib (hDIB) if successful. NULL if an error occurs. Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything from the end of the BITMAPFILEHEADER structure on is returned in the global memory handle. *************************************************************************/ HDIB WINAPI ReadDIBFile(CFile& file) { BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HDIB hDIB; LPSTR pDIB; /* * get length of DIB in bytes for use when reading */ dwBitsSize = file.GetLength(); /* * Go read the DIB file header and check if it's valid. */ if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) return NULL; #ifdef _MAC ByteSwapHeader(&bmfHeader); #endif if (bmfHeader.bfType != DIB_HEADER_MARKER) return NULL; /* * Allocate memory for DIB */ hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); if (hDIB == 0) { return NULL; } pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); /* * Go read the bits. */ if (file.Read(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) ) { ::GlobalUnlock((HGLOBAL) hDIB); ::GlobalFree((HGLOBAL) hDIB); return NULL; } #ifdef _MAC // First swap the size field *((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB)); // Now swap the rest of the structure ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB)); #endif ::GlobalUnlock((HGLOBAL) hDIB); return hDIB; } #ifdef _MAC void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader) { bmfHeader->bfType = SWAPWORD(bmfHeader->bfType); bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize); bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits); } void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header) { // Note this doesn't swap the bcSize/biSize field. It assumes that the // size field was swapped during read or while setting the fWin30Header // flag. if (fWin30Header) { LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader); //lpBMIH->biSize = SWAPLONG(lpBMIH->biSize); lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth); lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight); lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes); lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount); lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression); lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage); lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter); lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter); lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed); lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant); } else { LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader); lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth); lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight); lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes); lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount); } } #endif BOOL WINAPI FreeDIBRows(HDIB hDib) { ::GlobalUnlock((HGLOBAL) hDib); return TRUE ; } /************************************************************************* * * SaveDIB() * * Saves the specified DIB into the specified CFile. The CFile * is opened and closed by the caller. * * Parameters: * * HDIB hDib - Handle to the dib to save * * CFile& file - open CFile used to save DIB * * Return value: TRUE if successful, else FALSE or CFileException * *************************************************************************/ BOOL WINAPI GetDIBRowsRGB(HDIB hDib, RGBTRIPLE* rows[], int *Width, int *Height) { BITMAPFILEHEADER bmfHdr; // Header for Bitmap file LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure DWORD dwDIBSize; if (hDib == NULL) return FALSE; /* * Get a pointer to the DIB memory, the first of which contains * a BITMAPINFO structure */ lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); if (lpBI == NULL) return FALSE; if (!IS_WIN30_DIB(lpBI)) { ::GlobalUnlock((HGLOBAL) hDib); return FALSE; // It's an other-style DIB (save not supported) } /* * Fill in the fields of the file header */ /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ bmfHdr.bfType = DIB_HEADER_MARKER; // "BM" // Calculating the size of the DIB is a bit tricky (if we want to // do it right). The easiest way to do this is to call GlobalSize() // on our global handle, but since the size of our global memory may have // been padded a few bytes, we may end up writing out a few too // many bytes to the file (which may cause problems with some apps). // // So, instead let's calculate the size manually (if we can) // // First, find size of header plus size of color table. Since the // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains // the size of the structure, let's use this. dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // Partial Calculation LPSTR lpStr ; lpStr = (LPSTR)lpBI ; lpStr = lpStr+dwDIBSize ; // Now calculate the size of the image if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) { // It's an RLE bitmap, we can't calculate size, so trust the // biSizeImage field dwDIBSize += lpBI->biSizeImage; } else { DWORD dwBmBitsSize; // Size of Bitmap Bits only // It's not RLE, so size is Width (DWORD aligned) * Height dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; dwDIBSize += dwBmBitsSize; // Now, since we have calculated the correct size, why don't we // fill in the biSizeImage field (this will fix any .BMP files which // have this field incorrect). lpBI->biSizeImage = dwBmBitsSize; } // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; /* * Now, calculate the offset the actual bitmap bits will be in * the file -- It's the Bitmap file header plus the DIB header, * plus the size of the color table. */ bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPSTR)lpBI); rows[0] = (RGBTRIPLE*)lpStr ; for(int i=1;i<lpBI->biHeight;i++) // >> Poprawka A. Wujek // rows[i] = rows[i-1]+lpBI->biWidth ; << było if(lpBI->biWidth%4==0) rows[i] = rows[i-1]+lpBI->biWidth; else rows[i] = (RGBTRIPLE*)((BYTE*)(rows[i-1]+lpBI->biWidth)+4-(lpBI->biWidth*3)%4) ; // << Poprawka A. Wujek if( Width != NULL ) *Width = lpBI->biWidth ; if( Height != NULL ) *Height = lpBI->biHeight ; return TRUE; } OutputDoc.cpp: Code: #include "stdafx.h" #include "diblook.h" #include "OutDoc.h" #include "afxext.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // COutputDoc IMPLEMENT_DYNCREATE(COutputDoc, CDocument) COutputDoc::COutputDoc() { } BOOL COutputDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; return TRUE; } COutputDoc::~COutputDoc() { } BEGIN_MESSAGE_MAP(COutputDoc, CDocument) //{{AFX_MSG_MAP(COutputDoc) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // COutputDoc diagnostics #ifdef _DEBUG void COutputDoc::AssertValid() const { CDocument::AssertValid(); } void COutputDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // COutputDoc serialization void COutputDoc::Serialize(CArchive& ar) { ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar); if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // COutputDoc commands