www.pudn.com > CapIT_src.zip > CapITView.cpp


// CapITView.cpp : implementation of the CCapITView class 
// 
 
#include "stdafx.h" 
#include "CapIT.h" 
 
#include "CapITDoc.h" 
#include "CapITView.h" 
 
#include "MainFrm.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
int FAR PASCAL GetMessageFunc (int nCode, WPARAM wParam, LPARAM lParam ); 
 
 
int hCurMsg = WH_MOUSE; //WH_GETMESSAGE; 
HWND ghWnd; 
HHOOK ghhk; 
 
int gCurrentX = 0; 
int gCurrentY = 0; 
 
BOOL        gbStartUp=TRUE; 
CBitmap*    gcBitmap; 
HDC         gHDC=NULL; 
 
BOOL bColorCoding = TRUE; 
BOOL bCapturingControl = FALSE; 
BOOL bScreenCapture = FALSE; 
BOOL bCapturingWindow = FALSE;  
BOOL bCapturingClient = FALSE; 
 
BOOL        gbTrackCodes = FALSE; 
BOOL        gbTrackPosition = FALSE; 
 
///////////////////////////////////////////////////////////////////////////// 
// CCapITView 
 
IMPLEMENT_DYNCREATE(CCapITView, CScrollView) 
 
BEGIN_MESSAGE_MAP(CCapITView, CScrollView) 
	//{{AFX_MSG_MAP(CCapITView) 
	ON_WM_CAPTURECHANGED() 
	ON_WM_DESTROY() 
	ON_COMMAND(ID_SAVE_FILE, OnSaveFile) 
	ON_UPDATE_COMMAND_UI(ID_SAVE_FILE, OnUpdateSaveFile) 
	ON_COMMAND(ID_COLORCODE, OnColorcode) 
	ON_UPDATE_COMMAND_UI(ID_COLORCODE, OnUpdateColorcode) 
	ON_COMMAND(ID_TRACKPOS, OnTrackpos) 
	ON_UPDATE_COMMAND_UI(ID_TRACKPOS, OnUpdateTrackpos) 
 
	ON_COMMAND(ID_CLEAR, OnClear) 
	ON_UPDATE_COMMAND_UI(ID_CLEAR, OnUpdateClear) 
 
	ON_COMMAND(ID_HIDE , OnHideWindow) 
 
	//}}AFX_MSG_MAP 
	// Standard printing commands 
	ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CCapITView construction/destruction 
 
CCapITView::CCapITView() 
{ 
	// TODO: add construction code here 
	gbDrawImage =  
	gbIsCaptured =  
	gbNewRect =  
	gbIsMarking =  
	gbCaptureMode = FALSE; 
	m_bHookSetup = FALSE; 
//	gMainWnd = NULL; 
} 
 
CCapITView::~CCapITView() 
{ 
} 
 
BOOL CCapITView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	cs.style |= WS_HSCROLL | WS_VSCROLL; 
	return CScrollView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CCapITView drawing 
 
void CCapITView::OnDraw(CDC* pDC) 
{ 
 
 
	if(gbDrawImage) 
	{ 
		// Fill in src/dest rectangle with width and height 
	    // of captured bitmap  
 
		CRect  rect; 
		GetClientRect(&rect); 
        // Paint the captured bitmap in the client area  
//		if(!gbStartUp) 
			PaintBitmap( pDC->m_hDC , &rect, ghBitmap, &rect, NULL);  
//		gbDrawImage = FALSE; 
	} 
 
} 
 
void CCapITView::OnInitialUpdate() 
{ 
	CScrollView::OnInitialUpdate(); 
 
	CSize sizeTotal; 
	sizeTotal.cx = 400; 
	sizeTotal.cy = 200; 
	SetScrollSizes(MM_TEXT, sizeTotal); 
 
	gMainWnd = AfxGetMainWnd(); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CCapITView printing 
 
BOOL CCapITView::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	return DoPreparePrinting(pInfo); 
} 
 
void CCapITView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
 
} 
 
void CCapITView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CCapITView diagnostics 
 
#ifdef _DEBUG 
void CCapITView::AssertValid() const 
{ 
	CScrollView::AssertValid(); 
} 
 
void CCapITView::Dump(CDumpContext& dc) const 
{ 
	CScrollView::Dump(dc); 
} 
 
CCapITDoc* CCapITView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCapITDoc))); 
	return (CCapITDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CCapITView message handlers 
 
 
void CCapITView::OnDestroy()  
{ 
	CScrollView::OnDestroy(); 
	 
	if(ghhk) 
		::UnhookWindowsHookEx(ghhk); 
 
    if (ghBitmap)  
       DeleteObject(ghBitmap);  
    if (ghPal)  
       DeleteObject(ghPal);  
 
} 
 
void CCapITView::OnHideWindow() 
{ 
	CMainFrame* frame = (CMainFrame*)AfxGetMainWnd(); 
	frame->ShowWindow(SW_HIDE); 
} 
 
 
void CCapITView::OnClear() 
{ 
	ClearCapture(); 
} 
 
void CCapITView::OnUpdateClear(CCmdUI* pCmdUI) 
{ 
	pCmdUI->Enable(gbIsCaptured);	 
} 
 
void CCapITView::ClearCapture()  
{ 
 
	if(ghhk) 
		::UnhookWindowsHookEx(ghhk); 
 
	bColorCoding = TRUE; 
 
	gbIsCaptured = FALSE;	 
	ghBitmap = NULL; 
	CRect rect; 
	GetClientRect(&rect); 
	InvalidateRect(rect,TRUE); 
	gbTrackCodes = FALSE; 
	gbTrackPosition = FALSE; 
	UpdateStatusbar(0, gbTrackCodes , gbTrackPosition); 
	UpdateCaptureStatus(FALSE); 
} 
 
void CCapITView::UpdateCaptureStatus(BOOL bCaptured) 
{ 
	CMainFrame* frame = (CMainFrame*)AfxGetMainWnd(); 
	frame->g_mbImageCaptured = bCaptured; 
} 
 
void CCapITView::CaptureClient()  
{ 
	AfxMessageBox("Click on Client Area to be captured"); 
	bCapturingClient = TRUE; 
	gbStartUp = FALSE; 
	SetCapture(); 
} 
 
void CCapITView::CaptureControl()  
{ 
	AfxMessageBox("Click on CONTROL to be captured"); 
	bCapturingControl = TRUE; 
	SetCapture(); 
	gbStartUp=FALSE; 
} 
 
void CCapITView::CaptureDesktop() 
{ 
	WindowCapture(GetDesktopWindow()->m_hWnd); 
	gbIsCaptured = TRUE; 
} 
 
void CCapITView::CaptureWindow()  
{ 
	AfxMessageBox("Click on Window to be captured"); 
	bCapturingWindow = TRUE; 
	SetCapture(); 
	gbStartUp = FALSE; 
} 
 
void CCapITView::WindowCapture(HWND wnd) 
{ 
 
	HBITMAP hBitmap = CopyWindowToBitmap(this , wnd, 1); 
 
    HPALETTE hPal = NULL; 
    if (hBitmap)  
	{ 
//       hPal = GetSystemPalette();  
	   ghBitmap = hBitmap; 
       gbDrawImage = TRUE; 
	   gbIsCaptured = TRUE; 
	   CRect rect; 
	   GetClientRect(&rect); 
	   InvalidateRect(rect); 
	   CCapITDoc* pDoc = GetDocument(); 
	   DoSize(FromHandle(this->m_hWnd) ,hBitmap); 
 
	   UpdateCaptureStatus(TRUE); 
 
    } 
    else  
	{	 
		gbIsCaptured = FALSE; 
		hPal = NULL;  
 
	   AfxMessageBox("Sorry !!!!"); 
	} 
} 
 
void CCapITView::OnCaptureChanged(CWnd *pWnd)  
{ 
 
	if(gbStartUp) 
		return; 
 
	CPoint point; 
    VERIFY(GetCursorPos(&point)); 
	ScreenToClient(&point); 
	ClientToScreen(&point); 
	CWnd* wnd = WindowFromPoint(point);    	 
 
	if(wnd) 
	{ 
		if(IsChild(wnd)) 
		{ 
			WindowCapture(wnd->GetParent()->m_hWnd); 
		} 
		else 
		{ 
			if(!gbIsCaptured) 
			{ 
				if(bCapturingClient) 
				{ 
					CaptureClientArea(wnd); 
					bCapturingClient = FALSE; 
				} 
				if(bCapturingWindow) 
				{ 
					WindowCapture(wnd->GetTopLevelParent()->m_hWnd); 
					bCapturingWindow = FALSE; 
 
				} 
				if(bCapturingControl) 
				{ 
					WindowCapture(wnd->GetTopLevelOwner()->m_hWnd); 
					bCapturingControl = FALSE; 
				} 
				gbIsCaptured = TRUE; 
				UpdateCaptureStatus(TRUE); 
 
			}	 
		} 
	} 
 
	ReleaseCapture(); 
 
	CScrollView::OnCaptureChanged(pWnd); 
} 
 
void CCapITView::CaptureClientArea(CWnd* wnd) 
{ 
	WindowCapture(wnd->m_hWnd); 
	return; 
} 
 
void CCapITView::OnSaveFile()  
{ 
 
   BOOL bOpen = FALSE; 
   char bigBuff[2048] = "";  // maximum common dialog buffer size 
   char szFilter[] = 
      "BMP Files (*.BMP)|*.bmp|*.bmp|All Files (*.*)|*.*|||"; 
   CFileDialog dlg(bOpen, NULL, NULL, 
      OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT, szFilter); 
 
   dlg.m_ofn.lpstrFile = bigBuff; 
   dlg.m_ofn.nMaxFile = sizeof(bigBuff); 
 
   dlg.DoModal(); 
    
   if(dlg.m_ofn.lpstrFile != "") 
   { 
		HPALETTE hPal = NULL; 
        hPal = GetSystemPalette(this->m_hWnd);  
		if(!hPal) 
		{ 
			AfxMessageBox("Error getting System Palette"); 
			return; 
		} 
		DWORD   dwFlags = NULL; 
		DWORD   dCompression = BI_RLE8; // / BI_RLE4 / BI_RGB; 
 
		HANDLE hDIB = ChangeBitmapFormat(ghBitmap,  
			                                   HIWORD(dwFlags),                   
											   dCompression,  
											   hPal ,  
											   this->m_hWnd); 
 
		SaveDIB(hDIB, dlg.m_ofn.lpstrFile); 
		hPal = NULL; 
   }	 
} 
 
void CCapITView::OnUpdateSaveFile(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(gbIsCaptured);	 
} 
 
void CCapITView::OnColorcode()  
{ 
 
	if(!m_bHookSetup)	 
		SetupHookProc(); 
 
	bColorCoding = FALSE; 
	gbTrackCodes = TRUE; 
} 
 
void CCapITView::OnUpdateColorcode(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable((gbIsCaptured) && (bColorCoding)); 
} 
 
int FAR PASCAL GetMessageFunc (int nCode, WPARAM wParam, LPARAM lParam ) 
{ 
 
   LPMOUSEHOOKSTRUCT MouseHookParam; 
 
   if ( nCode >= 0 )  
   { 
 
	  MouseHookParam = (MOUSEHOOKSTRUCT *) lParam; 
	  gCurrentX = MouseHookParam->pt.x; 
	  gCurrentY = MouseHookParam->pt.y; 
 
	  CPoint point; 
	  HWND wnd; 
 
	  GetCursorPos(&point); 
	  wnd = WindowFromPoint(point); 
	  HDC hdc = ::GetDC(wnd);  
	  COLORREF cr = GetPixel(hdc, point.x , point.y); 
      CCapITView::UpdateStatusbar(cr , gbTrackCodes , gbTrackPosition); 
 
   } 
   return CallNextHookEx(ghhk, hCurMsg, wParam , lParam); 
} 
 
void CCapITView::UpdateStatusbar(COLORREF cr , BOOL bShowCodes, BOOL bShowPosition) 
{ 
	CMainFrame* frame = (CMainFrame*)AfxGetMainWnd(); 
 
	frame->m_bShowCodes = bShowCodes; 
	frame->m_iBlueCode = GetBValue(cr); 
	frame->m_iGreenCode = GetGValue(cr); 
	frame->m_iRedCode= GetRValue(cr); 
 
	frame->m_bShowPosition = bShowPosition; 
	frame->m_iPosX = gCurrentX; 
	frame->m_iPosY = gCurrentY; 
 
} 
 
void CCapITView::OnTrackpos()  
{ 
	if(!m_bHookSetup)	 
		SetupHookProc(); 
 
	gbTrackPosition = TRUE;	 
} 
 
void CCapITView::OnUpdateTrackpos(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable((gbIsCaptured) && (!gbTrackPosition));	 
} 
 
void CCapITView::SetupHookProc() 
{ 
	ghWnd = this->m_hWnd; 
    FARPROC lpMsgFilterProc = (FARPROC)MakeProcInstance((FARPROC)GetMessageFunc, hInst); 
    ghhk = SetWindowsHookEx(hCurMsg, (HOOKPROC)lpMsgFilterProc, NULL, 
            GetCurrentThreadId()); 
	m_bHookSetup = TRUE; 
} 
 
 
 
 
/****************************************************************************** 
*       This is a part of the Microsoft Source Code Samples.  
*       Copyright (C) 1993-1997 Microsoft Corporation. 
*       All rights reserved.  
*       This source code is only intended as a supplement to  
*       Microsoft Development Tools and/or WinHelp documentation. 
*       See these sources for detailed information regarding the  
*       Microsoft samples programs. 
******************************************************************************/ 
 
HBITMAP CCapITView::CopyWindowToBitmap(CWnd* wnd , HWND hWnd, WORD fPrintArea) 
{ 
	HBITMAP     hBitmap = NULL;  // handle to device-dependent bitmap       
	// check for a valid window handle       
	if (!hWnd)          
	    return NULL;  
 
    RECT    rectWnd;  
  ::GetWindowRect(hWnd, &rectWnd);   
	 
 
	switch (fPrintArea)      
	{          
		case PW_WINDOW: // copy entire window          
		{              
          // get the window rectangle               
          // get the bitmap of that window by calling              
		  // CopyScreenToBitmap and passing it the window rect                      
//		  GetWindowRect(&rectWnd); 
          hBitmap = CopyScreenToBitmap(&rectWnd);              
		  break;          
		}    
       case PW_CLIENT: // copy client area          
	   {              
	     RECT rectClient;              
	     POINT pt1, pt2;              // get client dimensions               
	     wnd->GetClientRect(&rectClient);              // convert client coords to screen coords               
	     pt1.x = rectClient.left;              
	     pt1.y = rectClient.top;              
	     pt2.x = rectClient.right;              
	     pt2.y = rectClient.bottom;              
	     wnd->ClientToScreen(&pt1);              
	     wnd->ClientToScreen(&pt2);              
	     rectClient.left = pt1.x;              
	     rectClient.top = pt1.y;              
	     rectClient.right = pt2.x;              
	     rectClient.bottom = pt2.y;   
 
         // get the bitmap of the client area by calling              
	     // CopyScreenToBitmap and passing it the client rect                           
	     hBitmap = CopyScreenToBitmap(&rectClient);              
	     break;          
	   }               
	   default:    // invalid print area              
	        return NULL;      
	}      // return handle to the bitmap      
	 
	return hBitmap;  
} 
 
HBITMAP CCapITView::CopyScreenToBitmap(LPRECT lpRect) 
{ 
	HDC         hScrDC, hMemDC;         // screen DC and memory DC      
//	HBITMAP     hBitmap; //,  
//	HBITMAP     hBitmap; 
//	HBITMAP     hOldBitmap;    // handles to deice-dependent bitmaps      
	int         nX, nY, nX2, nY2;       // coordinates of rectangle to grab      
	int         nWidth, nHeight;        // DIB width and height      
	int         xScrn, yScrn;           // screen resolution       
 
	HGDIOBJ     hOldBitmap , hBitmap; 
		 
		// check for an empty rectangle  
    if (IsRectEmpty(lpRect))        
	   return NULL;       
	   // create a DC for the screen and create      
	   // a memory DC compatible to screen DC           
 
   hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);      
   hMemDC = CreateCompatibleDC(hScrDC);      // get points of rectangle to grab   
    
   nX = lpRect->left;      
   nY = lpRect->top;      
   nX2 = lpRect->right;      
   nY2 = lpRect->bottom;      // get screen resolution       
    
   xScrn = GetDeviceCaps(hScrDC, HORZRES);      
   yScrn = GetDeviceCaps(hScrDC, VERTRES);       
    
   //make sure bitmap rectangle is visible       
    
   if (nX < 0)          
	  nX = 0;      
    
   if (nY < 0)          
      nY = 0;      
    
   if (nX2 > xScrn)          
      nX2 = xScrn;      
    
   if (nY2 > yScrn)          
      nY2 = yScrn;       
 
   nWidth = nX2 - nX;      
   nHeight = nY2 - nY;       
    
   // create a bitmap compatible with the screen DC      
    
   hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);       
    
   // select new bitmap into memory DC      
    
   hOldBitmap =   SelectObject (hMemDC, hBitmap);       
    
   // bitblt screen DC to memory DC      
    
   BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);      
    
   // select old bitmap back into memory DC and get handle to      
   // bitmap of the screen           
    
   hBitmap = SelectObject(hMemDC, hOldBitmap);       
    
   // clean up       
    
   DeleteDC(hScrDC);      
   DeleteDC(hMemDC);       
    
   // return handle to the bitmap       
    
   return (HBITMAP)hBitmap;  
 
} 
 
BOOL CCapITView::PaintBitmap(HDC hDC, LPRECT lpDCRect, HBITMAP hDDB, LPRECT lpDDBRect, HPALETTE hPal) 
{ 
    HDC         hMemDC;            // Handle to memory DC  
//    HBITMAP     hOldBitmap;        // Handle to previous bitmap  
    HPALETTE    hOldPal1 = NULL;   // Handle to previous palette  
    HPALETTE    hOldPal2 = NULL;   // Handle to previous palette  
    BOOL        bSuccess = FALSE;  // Success/fail flag  
	HGDIOBJ hOldBitmap; 
    // Create a memory DC  
  
    hMemDC = CreateCompatibleDC (hDC);  
  
    // If this failed, return FALSE  
  
    if (!hMemDC)  
        return FALSE;  
  
    // If we have a palette, select and realize it  
  
    if (hPal)  
    {  
        hOldPal1 = SelectPalette(hMemDC, hPal, TRUE);  
        hOldPal2 = SelectPalette(hDC, hPal, FALSE); //TRUE);  
        RealizePalette(hDC);  
    }  
  
    // Select bitmap into the memory DC  
  
    hOldBitmap = SelectObject (hMemDC, hDDB);  
 
    // Make sure to use the stretching mode best for color pictures  
  
    SetStretchBltMode (hDC, COLORONCOLOR);  
	 
    // Determine whether to call StretchBlt() or BitBlt()  
    if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDDBRect)) &&  
            (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDDBRect)))  
        bSuccess = BitBlt(hDC, lpDCRect->left, lpDCRect->top,  
                lpDCRect->right - lpDCRect->left,  
                lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,  
                lpDDBRect->top, SRCCOPY);  
    else  
        bSuccess = StretchBlt(hDC, lpDCRect->left,  lpDCRect->top,   
                lpDCRect->right - lpDCRect->left,  
                lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,   
                lpDDBRect->top,  lpDDBRect->right - lpDDBRect->left,  
                lpDDBRect->bottom - lpDDBRect->top, SRCCOPY);  
  
    // Clean up  
  
    SelectObject(hMemDC, hOldBitmap);  
  
    if (hOldPal1)  
        SelectPalette (hMemDC, hOldPal1, FALSE);  
  
    if (hOldPal2)  
        SelectPalette (hDC, hOldPal2, FALSE);  
  
    DeleteDC (hMemDC);  
  
    // Return with success/fail flag  
  
    return bSuccess;  
} 
 
 
void CCapITView::DoSize(CWnd* wnd , HBITMAP ghBitmap) 
{ 
    BITMAP      bm;                     // Bitmap info structure  
    int         cxBitmap=0, cyBitmap=0; // Bitmap width and height  
    int         cxScroll, cyScroll;     // Scroll positions  
    RECT        rect;                   // Client rectangle  
  
    // repaint if displaying bitmap  
  
    if (ghBitmap)  
    {  
        // Get info about bitmap  
  
        GetObject(ghBitmap, sizeof(BITMAP), (LPSTR)&bm);  
  
        // Get the width and height of the bitmap  
 
//		CSize sizeTotal; 
		// TODO: calculate the total size of this view 
//		sizeTotal.cx = bm.bmWidth; 
//		sizeTotal.cy = bm.bmHeight; 
//		SetScrollSizes(MM_TEXT, sizeTotal);		 
 
        cxBitmap = bm.bmWidth;  
        cyBitmap = bm.bmHeight;  
  
        // Find out the dimensions of the window, and the current thumb  
        // positions  
  
        wnd->GetClientRect(&rect);  
  
        cxScroll = wnd->GetScrollPos (SB_HORZ);  
        cyScroll = wnd->GetScrollPos (SB_VERT);  
  
        // If current thumb positions would cause blank space  
        // at right or bottom of client area, repaint  
  
        if (cxScroll + rect.right > cxBitmap ||  
                cyScroll + rect.bottom > cyBitmap)  
            wnd->InvalidateRect(NULL, FALSE);  
  
        // Make sure scroll bars are updated  
  
        SetupScrollBars(wnd , (WORD)cxBitmap, (WORD)cyBitmap);  
    }  
    else //if (bStartup)  
        wnd->InvalidateRect(NULL, TRUE);  
} 
 
void CCapITView::SetupScrollBars(CWnd* wnd , WORD cxBitmap, WORD cyBitmap) 
{ 
    RECT        rect;                       // Client Rectangle  
    BOOL        bNeedScrollBars=FALSE;      // Need Scroll bars?  
    unsigned    cxWindow, cyWindow;         // Width and height of client area  
    int         cxRange=0, cyRange=0;       // Range needed for horz and vert  
  
    // Do some initialization  
  
    ReallyGetClientRect(wnd , &rect);  
  
    cxWindow = rect.right - rect.left;  
    cyWindow = rect.bottom - rect.top;  
  
    // Now determine if we need the scroll bars  
  
    if ((cxWindow < (unsigned)cxBitmap) || (cyWindow < (unsigned)cyBitmap))  
        bNeedScrollBars = TRUE;  
  
  
    // Setup the scroll bar ranges.  We want to be able to  
    // scroll the window so that all the bitmap can appear  
    // within the client area.  Take into account that  
    // if the opposite scroll bar is activated, it eats  
    // up some client area.  
  
    if (bNeedScrollBars)  
    {  
        cyRange = (unsigned)cyBitmap - cyWindow - 1 +  
                GetSystemMetrics (SM_CYHSCROLL);  
        cxRange = (unsigned)cxBitmap - cxWindow - 1 +  
                GetSystemMetrics (SM_CXVSCROLL);  
    }  
  
    // Set the ranges we've calculated (0 to 0 means invisible scrollbar)  
  
    wnd->SetScrollRange(SB_VERT, 0, cyRange, TRUE);  
    wnd->SetScrollRange(SB_HORZ, 0, cxRange, TRUE);  
} 
 
 
void CCapITView::ReallyGetClientRect(CWnd* wnd , LPRECT lpRect) 
{ 
    DWORD   dwWinStyle;  
  
    dwWinStyle = GetWindowLong (wnd->m_hWnd, GWL_STYLE);  
  
    wnd->GetClientRect (lpRect);  
  
    if (dwWinStyle & WS_HSCROLL)  
        lpRect->bottom += (GetSystemMetrics (SM_CYHSCROLL) - 1);  
  
    if (dwWinStyle & WS_VSCROLL)  
        lpRect->right  += (GetSystemMetrics (SM_CXVSCROLL) - 1);  
  
} 
 
WORD CCapITView::SaveDIB(HDIB hDib, LPSTR lpFileName) 
{ 
	BITMAPFILEHEADER    bmfHdr;     // Header for Bitmap file      
	LPBITMAPINFOHEADER  lpBI;       // Pointer to DIB info structure      
	HANDLE              fh;         // file handle for opened file      
	DWORD               dwDIBSize;      
	DWORD               dwWritten;       
	if (!hDib)          
		return ERR_INVALIDHANDLE;   
	 
   fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);       
    
   if (fh == INVALID_HANDLE_VALUE)          
		return ERR_OPEN;       
   // Get a pointer to the DIB memory, the first of which contains      
   // a BITMAPINFO structure       
   lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);      
   if (!lpBI)      
   {          
		CloseHandle(fh);          
		return ERR_LOCK;      
	}      
	// Check to see if we're dealing with an OS/2 DIB.  If so, don't      
	// save it because our functions aren't written to deal with these      
	// DIBs.   
   if (lpBI->biSize != sizeof(BITMAPINFOHEADER))      
   {          
		GlobalUnlock(hDib);          
		CloseHandle(fh);          
		return ERR_NOT_DIB;      
	}       
	// 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"  
 
 dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);         
 // Now calculate the size of the image       
 // It's an RLE bitmap, we can't calculate size, so trust the biSizeImage      
 // field       
  
 if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))          
  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);       
  
 // Write the file header       
  
 WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);       
  
 // Write the DIB header and the bits -- use local version of      
  // MyWrite, so we can write more than 32767 bytes of data           
  
 WriteFile(fh, (LPSTR)lpBI, dwDIBSize, &dwWritten, NULL);       
 GlobalUnlock(hDib);      
 CloseHandle(fh);       
  
 if (dwWritten == 0)          
  return ERR_OPEN;  
  
 // oops, something happened in the write      
  else          
  return 0; // Success code  
  
} 
 
WORD CCapITView::PaletteSize (VOID FAR * pv)  
{      
	LPBITMAPINFOHEADER lpbi;      
	WORD NumColors;       
	lpbi      = (LPBITMAPINFOHEADER)pv;      
	NumColors = DibNumColors(lpbi);       
	if (lpbi->biSize == sizeof(BITMAPCOREHEADER))          
		return NumColors * sizeof(RGBTRIPLE);      
	else          
		return NumColors * sizeof(RGBQUAD);  
}  
 
WORD CCapITView::DibNumColors (VOID FAR * pv) 
{      
	int bits;      
	LPBITMAPINFOHEADER lpbi;      
	LPBITMAPCOREHEADER lpbc;       
	lpbi = ((LPBITMAPINFOHEADER)pv);      
	lpbc = ((LPBITMAPCOREHEADER)pv);       
	 
	/*  With the BITMAPINFO format headers, the size of the palette       
	*  is in biClrUsed, whereas in the BITMAPCORE - style headers, it       
	*  is dependent on the bits per pixel ( = 2 raised to the power of       
	*  bits/pixel).       
	*/      
	 
	if (lpbi->biSize != sizeof(BITMAPCOREHEADER))      
	{          
		if (lpbi->biClrUsed != 0)              
			return (WORD)lpbi->biClrUsed;          
	 
		bits = lpbi->biBitCount;      
	}      
	else          
		bits = lpbc->bcBitCount;       
	 
	switch (bits)      
	{      
		case 1:          
			return 2;      
		case 4:          
 
			return 16;      
		case 8:          
			return 256;      
		default:          
			//  A 24 bitcount DIB has no color table           
			return 0;      
 
	}  
 
	 
}  
 
HDIB CCapITView::ChangeBitmapFormat(HBITMAP hBitmap,  
								   WORD wBitCount,  
								   DWORD dwCompression,  
                                   HPALETTE hPal, 
								   HWND hwnd)  
{  
    HDC                hDC;          // Screen DC  
    HDIB               hNewDIB=NULL; // Handle to new DIB  
    BITMAP             Bitmap;       // BITMAP data structure  
    BITMAPINFOHEADER   bi;           // Bitmap info. header  
    LPBITMAPINFOHEADER lpbi;         // Pointer to bitmap header  
    HPALETTE           hOldPal=NULL; // Handle to palette  
    WORD               NewBPP;       // New bits per pixel  
    DWORD              NewComp;      // New compression format  
  
    // Check for a valid bitmap handle  
  
    if (!hBitmap)  
        return NULL;  
  
    // Validate wBitCount and dwCompression  
    // They must match correctly (i.e., BI_RLE4 and 4 BPP or  
    // BI_RLE8 and 8BPP, etc.) or we return failure  
      
    if (wBitCount == 0)  
    {  
        NewComp = dwCompression;  
        if (NewComp == BI_RLE4)  
            NewBPP = 4;  
        else if (NewComp == BI_RLE8)  
            NewBPP = 8;  
        else // Not enough info */  
            return NULL;  
    }  
    else if (wBitCount == 1 && dwCompression == BI_RGB)  
    {  
        NewBPP = wBitCount;  
        NewComp = BI_RGB;  
    }  
    else if (wBitCount == 4)  
    {  
        NewBPP = wBitCount;  
        if (dwCompression == BI_RGB || dwCompression == BI_RLE4)  
            NewComp = dwCompression;  
        else  
            return NULL;  
    }  
    else if (wBitCount == 8)  
    {  
        NewBPP = wBitCount;  
        if (dwCompression == BI_RGB || dwCompression == BI_RLE8)  
            NewComp = dwCompression;  
        else  
            return NULL;  
    }  
    else if (wBitCount == 24 && dwCompression == BI_RGB)  
    {  
        NewBPP = wBitCount;  
        NewComp = BI_RGB;  
    }  
    else  
        return NULL;  
  
    // Get info about the bitmap  
  
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);  
  
    // Fill in the BITMAPINFOHEADER appropriately  
  
    bi.biSize               = sizeof(BITMAPINFOHEADER);  
    bi.biWidth              = Bitmap.bmWidth;  
    bi.biHeight             = Bitmap.bmHeight;  
    bi.biPlanes             = 1;  
    bi.biBitCount           = NewBPP;  
    bi.biCompression        = NewComp;  
    bi.biSizeImage          = 0;  
    bi.biXPelsPerMeter      = 0;  
    bi.biYPelsPerMeter      = 0;  
    bi.biClrUsed            = 0;  
    bi.biClrImportant       = 0;  
  
    // Go allocate room for the new DIB  
  
    hNewDIB = AllocRoomForDIB(bi, hBitmap , hwnd);  
    if (!hNewDIB)  
        return NULL;  
  
    // Get a pointer to the new DIB  
  
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);  
  
    // If we have a palette, get a DC and select/realize it  
  
    if (hPal)  
    {  
 		hDC = CreateDC ( TEXT("DISPLAY"), NULL, NULL, NULL ); 
        hOldPal = SelectPalette(hDC, hPal, FALSE);  
        RealizePalette(hDC);  
    }  
  
    // Call GetDIBits and get the new DIB bits  
  
    if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight, (LPSTR)lpbi +  
            (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,  
            DIB_RGB_COLORS))  
    {  
        GlobalUnlock(hNewDIB);  
        GlobalFree(hNewDIB);  
        hNewDIB = NULL;  
    }  
  
    // Clean up and return  
  
    if (hOldPal)  
    {  
        SelectPalette(hDC, hOldPal, TRUE);  
        RealizePalette(hDC);  
		::ReleaseDC(hwnd, hDC); 
     }  
  
    // Unlock the new DIB's memory block  
  
    if (hNewDIB)  
        GlobalUnlock(hNewDIB);  
  
    return hNewDIB;  
} 
  
HANDLE CCapITView::AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap , HWND hwnd)  
{  
    DWORD               dwLen;  
    HANDLE              hDIB;  
    HDC                 hDC;  
    LPBITMAPINFOHEADER  lpbi;  
    HANDLE              hTemp;  
  
    // Figure out the size needed to hold the BITMAPINFO structure  
    // (which includes the BITMAPINFOHEADER and the color table).  
  
    dwLen = bi.biSize + PaletteSize((LPSTR) &bi);  
    hDIB  = GlobalAlloc(GHND,dwLen);  
  
    // Check that DIB handle is valid  
  
    if (!hDIB)  
        return NULL;  
  
    // Set up the BITMAPINFOHEADER in the newly allocated global memory,  
    // then call GetDIBits() with lpBits = NULL to have it fill in the  
    // biSizeImage field for us.  
  
    lpbi  = (LPBITMAPINFOHEADER)GlobalLock(hDIB);  
    *lpbi = bi;  
  
    hDC = CreateDC ( TEXT("DISPLAY"), NULL, NULL, NULL ); 
  
    GetDIBits(hDC, hBitmap, 0, (UINT) bi.biHeight, NULL, (LPBITMAPINFO)lpbi,  
            DIB_RGB_COLORS);  
 	::ReleaseDC(hwnd, hDC); 
  
  
    // If the driver did not fill in the biSizeImage field,  
    // fill it in -- NOTE: this is a bug in the driver!  
      
    if (lpbi->biSizeImage == 0)  
        lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth *  
                lpbi->biBitCount) * lpbi->biHeight;  
  
    // Get the size of the memory block we need  
  
    dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;  
  
    // Unlock the memory block  
  
    GlobalUnlock(hDIB);  
  
    // ReAlloc the buffer big enough to hold all the bits   
  
    if (hTemp = GlobalReAlloc(hDIB,dwLen,0))  
        return hTemp;  
    else  
    {  
        // Else free memory block and return failure  
  
        GlobalFree(hDIB);  
        return NULL;  
    }  
}  
  
HPALETTE CCapITView::GetSystemPalette(HWND hwnd)  
{  
    HDC hDC;                // handle to a DC  
    static HPALETTE hPal = NULL;   // handle to a palette  
    HANDLE hLogPal;         // handle to a logical palette  
    LPLOGPALETTE lpLogPal;  // pointer to a logical palette  
    int nColors;            // number of colors  
  
    // Find out how many palette entries we want.  
 
    hDC = CreateDC ( TEXT("DISPLAY"), NULL, NULL, NULL ); 
  
    if (!hDC)  
        return NULL;  
	  
    nColors = 256; //PalEntriesOnDevice(hDC);   // Number of palette entries  
  
    // Allocate room for the palette and lock it.  
  
    hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *  
            sizeof(PALETTEENTRY));  
  
    // if we didn't get a logical palette, return NULL  
  
    if (!hLogPal)  
        return NULL;  
  
    // get a pointer to the logical palette  
  
    lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);  
  
    // set some important fields  
  
    lpLogPal->palVersion = 0x300; //PALVERSION;  
    lpLogPal->palNumEntries = nColors;  
  
    // Copy the current system palette into our logical palette  
  
    GetSystemPaletteEntries(hDC, 0, nColors,  
            (LPPALETTEENTRY)(lpLogPal->palPalEntry));  
  
    // Go ahead and create the palette.  Once it's created,  
    // we no longer need the LOGPALETTE, so free it.      
  
    hPal = CreatePalette(lpLogPal);  
  
    // clean up  
  
    GlobalUnlock(hLogPal);  
    GlobalFree(hLogPal);  
	::ReleaseDC(hwnd, hDC); 
  
    return hPal;  
}  
 
int CCapITView::PalEntriesOnDevice(HDC hDC)  
{      
	int nColors;  // number of colors       
	// Find out the number of colors on this device.           
	nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES))); 
	ASSERT(nColors);      
	return nColors;  
}