index
Generated: On Fri Jan 4 20:14:55 2008, From: c:\GTools\tools\testap3\testMagnify.cxx, dated Fri Jan 4 18:15:34 2008, with size 14579 bytes.
// testMagnify.cxx // // Some experiments 'magnifying' the bitmap under the cursor // 2008/01/03 - geoff mclane - http://geoffair.net/ms/magnify.htm // Open Source - praise me, if need be, but do not blame me! // #include "testap3.h" BOOL bAddRedOutline = TRUE; typedef struct tagMAGNIF { POINT pt; // mouse POINT HBITMAP hbm; // saved BITMAP (handle) - for RESTORE SIZE szin, szout; // INNER and OUTER sizes COLORREF trans; // transparent color HBITMAP hBitmap2; // for REPAINT }MAGNIF, * PMAGNIF; MAGNIF sMagnif = {0}; // some coding ideas from // http://www.codeguru.com/cpp/g-m/bitmap/article.php/c1753__1 // but (a) this is in MS MFC code, and (b) could NOT get is working! // later found something that worked - // http://www.codeproject.com/KB/GDI/magnify.aspx // You have to be a MEMBER of 'codeproject' (it is FREE) to download // the source files. Again it is in MS MFC, so here I 'converted' // that to standard C/C++. // It uses one seemingly UNDOCUMENTED BitBlt() operation, 0x220326, // but works like a charm ;=)) void test_DrawTransparent(HDC hdcDst, HBITMAP hBmp, int x, int y, COLORREF clrTransparency) { BITMAP bm; //GetBitmap (&bm); GetObject( hBmp, sizeof(BITMAP), (LPSTR)&bm ); //CPoint size (bm.bmWidth, bm.bmHeight); //pDC->DPtoLP (&size); //CPoint org (0, 0); //pDC->DPtoLP (&org); POINT size; size.x = bm.bmWidth; size.y = bm.bmHeight; DPtoLP( hdcDst, &size, 1 ); POINT org; org.x = 0; org.y = 0; DPtoLP( hdcDst, &org, 1 ); // Create a memory DC (dcImage) and select the bitmap into it. //CDC dcImage; //dcImage.CreateCompatibleDC (pDC); HDC dcImage = CreateCompatibleDC(hdcDst); // CBitmap* pOldBitmapImage = dcImage.SelectObject (this); HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(dcImage, hBmp); // dcImage.SetMapMode (pDC->GetMapMode ()); SetMapMode( dcImage, GetMapMode(hdcDst) ); // Create a second memory DC (dcAnd) and in it create an AND mask. // CDC dcAnd; // dcAnd.CreateCompatibleDC (pDC); // dcAnd.SetMapMode (pDC->GetMapMode ()); HDC dcAnd = CreateCompatibleDC (hdcDst); SetMapMode (dcAnd, GetMapMode (hdcDst)); // CBitmap bitmapAnd; // bitmapAnd.CreateBitmap (bm.bmWidth, bm.bmHeight, 1, 1, NULL); // CBitmap* pOldBitmapAnd = dcAnd.SelectObject (&bitmapAnd); HBITMAP bitmapAnd = CreateBitmap (bm.bmWidth, bm.bmHeight, 1, 1, NULL); HBITMAP pOldBitmapAnd = (HBITMAP)SelectObject (dcAnd, bitmapAnd); // dcImage.SetBkColor (clrTransparency); // dcAnd.BitBlt (org.x, org.y, size.x, size.y, &dcImage, org.x, org.y, // SRCCOPY); SetBkColor(dcImage, clrTransparency); BitBlt (dcAnd, org.x, org.y, size.x, size.y, dcImage, org.x, org.y, SRCCOPY); // Create a third memory DC (dcXor) and in it create an XOR mask. // CDC dcXor; // dcXor.CreateCompatibleDC (pDC); // dcXor.SetMapMode (pDC->GetMapMode ()); HDC dcXor = CreateCompatibleDC (hdcDst); SetMapMode ( dcXor, GetMapMode (hdcDst) ); // CBitmap bitmapXor; // bitmapXor.CreateCompatibleBitmap (&dcImage, bm.bmWidth, bm.bmHeight); // CBitmap* pOldBitmapXor = dcXor.SelectObject (&bitmapXor); HBITMAP bitmapXor = CreateCompatibleBitmap (dcImage, bm.bmWidth, bm.bmHeight); HBITMAP pOldBitmapXor = (HBITMAP)SelectObject (dcXor, bitmapXor); //dcXor.BitBlt (org.x, org.y, size.x, size.y, &dcImage, org.x, org.y, // SRCCOPY); BitBlt (dcXor, org.x, org.y, size.x, size.y, dcImage, org.x, org.y, SRCCOPY); //dcXor.BitBlt (org.x, org.y, size.x, size.y, &dcAnd, org.x, org.y, // 0x220326); BitBlt (dcXor, org.x, org.y, size.x, size.y, dcAnd, org.x, org.y, 0x220326); // Copy the pixels in the destination rectangle to a temporary // memory DC (dcTemp). // CDC dcTemp; // dcTemp.CreateCompatibleDC (pDC); // dcTemp.SetMapMode (pDC->GetMapMode ()); HDC dcTemp = CreateCompatibleDC (hdcDst); SetMapMode ( dcTemp, GetMapMode (hdcDst) ); // CBitmap bitmapTemp; // bitmapTemp.CreateCompatibleBitmap (&dcImage, bm.bmWidth, bm.bmHeight); // CBitmap* pOldBitmapTemp = dcTemp.SelectObject (&bitmapTemp); HBITMAP bitmapTemp = CreateCompatibleBitmap (dcImage, bm.bmWidth, bm.bmHeight); HBITMAP pOldBitmapTemp = (HBITMAP)SelectObject (dcTemp, bitmapTemp); // dcTemp.BitBlt (org.x, org.y, size.x, size.y, pDC, x, y, SRCCOPY); BitBlt (dcTemp, org.x, org.y, size.x, size.y, hdcDst, x, y, SRCCOPY); // Generate the final image by applying the AND and XOR masks to // the image in the temporary memory DC. // dcTemp.BitBlt (org.x, org.y, size.x, size.y, &dcAnd, org.x, org.y, // SRCAND); // dcTemp.BitBlt (org.x, org.y, size.x, size.y, &dcXor, org.x, org.y, // SRCINVERT); BitBlt ( dcTemp, org.x, org.y, size.x, size.y, dcAnd, org.x, org.y, SRCAND); BitBlt ( dcTemp, org.x, org.y, size.x, size.y, dcXor, org.x, org.y, SRCINVERT); // Blit the resulting image to the screen. // pDC->BitBlt (x, y, size.x, size.y, &dcTemp, org.x, org.y, SRCCOPY); BitBlt ( hdcDst, x, y, size.x, size.y, dcTemp, org.x, org.y, SRCCOPY); //pDC->StretchBlt(x, y, cx, cy, &dcTemp, 0, 0, w, h, SRCCOPY); // Restore the default bitmaps. SelectObject ( dcTemp, pOldBitmapTemp); SelectObject ( dcXor, pOldBitmapXor); SelectObject ( dcAnd, pOldBitmapAnd); SelectObject ( dcImage, pOldBitmapImage); // delete objects DeleteDC(dcImage); DeleteDC(dcAnd); DeleteObject(bitmapAnd); DeleteDC(dcXor); DeleteObject(bitmapXor); DeleteDC(dcTemp); DeleteObject(bitmapTemp); } HBITMAP test_MagnifyPoint( HWND hWnd, PMAGNIF pm ) { TmStamp tm; HBITMAP bitmap3 = NULL; HRGN rgn1, rgn2, rgn3; HDC hdc = GetDC(hWnd); HBITMAP bitmap = NULL; HBITMAP bitmap2 = NULL; HDC hdcBmp = NULL; HBITMAP hold, hold2, hold3; HBRUSH hbr = NULL; HDC hdcMem = NULL; HDC hdcKeep = NULL; COLORREF rgbTransparent = pm->trans; // gMagTC; // RGB(255, 0, 254); //SIZE szIN, szOUT; PSIZE pszin = &pm->szin; PSIZE pszout = &pm->szout; POINT point = pm->pt; INT xi2, yi2; INT xo2, yo2; // INNER AND OUTER SIZES //pszin->cx = gMagICX; // 40; //pszin->cy = gMagICY; // 40; //pszout->cx = gMagOCX; // 120 //pszout->cy = gMagOCY; // 120 // half INNER and OUTER sizes xi2 = pszin->cx / 2; yi2 = pszin->cy / 2; xo2 = pszout->cx / 2; yo2 = pszout->cy / 2; // create regions rgn1 = CreateEllipticRgn(0,0,pszout->cx,pszout->cy); rgn2 = CreateRectRgn(0,0,pszout->cx,pszout->cy); rgn3 = CreateRectRgn(0,0,pszout->cx,pszout->cy); if( !rgn1 || !rgn2 || !rgn3 ) goto Cleanup; // ============================================================== CombineRgn(rgn3,rgn2,rgn1, RGN_DIFF); // subtract center ellipse, // from outer rectangle - gets a complex region // Try outputRgn() for diagnostics only // OutputRgn( hdc, rgn1 ); // OutputRgn( hdc, rgn3 ); // this PAINTS all the RECT to the HDC // ============================================================== if( !hdc ) goto Cleanup; hbr = CreateSolidBrush( rgbTransparent ); hdcBmp = CreateCompatibleDC(hdc); if( !hdcBmp ) goto Cleanup; hdcMem = CreateCompatibleDC(hdc); if( !hdcMem ) goto Cleanup; hdcKeep = CreateCompatibleDC(hdc); if( !hdcKeep ) goto Cleanup; bitmap = CreateCompatibleBitmap( hdc, pszin->cx, pszin->cy ); if( !bitmap ) goto Cleanup; bitmap2 = CreateCompatibleBitmap( hdc, pszout->cx, pszout->cy ); if( !bitmap2 ) goto Cleanup; bitmap3 = CreateCompatibleBitmap( hdc, pszout->cx, pszout->cy ); if( !bitmap3 ) goto Cleanup; hold = (HBITMAP)SelectObject(hdcBmp,bitmap); hold2 = (HBITMAP)SelectObject(hdcMem,bitmap2); // get the OUTTER rectangle, for replacement // ========================================= hold3 = (HBITMAP)SelectObject(hdcKeep,bitmap3); BitBlt( hdcKeep, 0, 0, pszout->cx, pszout->cy, hdc, point.x - xo2, point.y - yo2, SRCCOPY ); bitmap3 = (HBITMAP)SelectObject(hdcKeep,hold3); DeleteDC(hdcKeep); // ========================================== // get the INNER rectangle BitBlt( hdcBmp, 0, 0, pszin->cx, pszin->cx, hdc, point.x - xi2, point.y - yi2, SRCCOPY ); // expand this inner rectangle to fill the outer rectangle //StretchBlt(hdc, point.x, point.y, 120, 120, hdcBmp, 0, 0, 40, 40, SRCCOPY); StretchBlt(hdcMem, 0, 0, pszout->cx, pszout->cy, hdcBmp, 0, 0, pszin->cx, pszin->cy, SRCCOPY); // fill the outside the circle with the transparent color FillRgn( hdcMem, rgn3, hbr ); // HAD VARIOUS TRIES AT COPYING THE EXPANDED RECTANGLE TO THE SCREEN, // excluding the surrounding transparent region ... until SUCCESS bitmap2 = (HBITMAP)SelectObject(hdcMem,hold2); test_DrawTransparent( hdc, bitmap2, point.x-xo2, point.y-yo2, rgbTransparent ); // MAYBE OUTLINE THE CIRCLE! // dc.SelectObject(&CPen(PS_SOLID, 1, RGB(0, 0, 0))); // dc.SelectObject(&CBrush(NULL, RGB(0, 0, 0))); // dc.Ellipse(point.x-(60*1)-1, point.y-(60*1)-1, point.x+(60*1), point.y+(60*1)); if( bAddRedOutline ) { RECT rc; rc.left = point.x-xo2; rc.top = point.y-yo2; rc.right = rc.left + pszout->cx; rc.bottom = rc.top + pszout->cy; DrawColoredEllipse( hdc, &rc, RGB(255,0,0) ); } SelectObject(hdcBmp,hold); pm->hBitmap2 = bitmap2; bitmap2 = NULL; Cleanup: if(hdc) ReleaseDC(hWnd, hdc); if(bitmap) DeleteObject(bitmap); if(bitmap2) DeleteObject(bitmap2); if(hdcBmp) DeleteDC(hdcBmp); if(hdcMem) DeleteDC(hdcMem); if(hbr) DeleteObject(hbr); if(rgn1) DeleteObject(rgn1); if(rgn2) DeleteObject(rgn2); if(rgn3) DeleteObject(rgn3); { long elap = tm.elapsed(); sprtf( "test_MagnifyPoint: Elapsed = %ld usecs (%0.5f secs)\n", elap, tm.get_secs_d(elap) ); } return bitmap3; } void testReplaceMagnify( HWND hWnd, PMAGNIF pm ) { HDC hdcMem = NULL; HBITMAP hold; POINT point = pm->pt; int xo2 = pm->szout.cx / 2; int yo2 = pm->szout.cy / 2; HDC hdc = GetDC(hWnd); if(!hdc) // nothing to do!!! goto Cleanup; if( !pm->hbm ) goto Cleanup; // create compatible device context hdcMem = CreateCompatibleDC(hdc); if(!hdcMem) goto Cleanup; // select bitmap into context hold = (HBITMAP)SelectObject(hdcMem, pm->hbm); // bli it to the destination BitBlt( hdc, point.x - xo2, point.y - yo2, pm->szout.cx, pm->szout.cy, hdcMem, 0, 0, SRCCOPY ); // select out the bitmap SelectObject(hdcMem, hold); Cleanup: if( hdc ) ReleaseDC(hWnd,hdc); if( hdcMem ) DeleteDC(hdcMem); if( pm->hbm ) DeleteObject( pm->hbm ); pm->hbm = NULL; } void Setup_Magnify( void ) { PMAGNIF pm = &sMagnif; // INNER AND OUTER SIZES pm->szin.cx = gMagICX; // 40; pm->szin.cy = gMagICY; // 40; pm->szout.cx = gMagOCX; // 120 pm->szout.cy = gMagOCY; // 120 // and transparent color to use - can be any (I think) pm->trans = gMagTC; } void Toggle_Magnify( HWND hWnd, POINT pt ) { PMAGNIF pm = &sMagnif; if( pm->hbm ) { testReplaceMagnify( hWnd, pm ); pm->hbm = NULL; } else { Setup_Magnify(); // do it around THIS POINT pm->pt.x = pt.x; pm->pt.y = pt.y; pm->hbm = test_MagnifyPoint( hWnd, pm ); } } // void Previous_Magnify_Off( HWND hWnd ) void Magnify2Off( HWND hWnd ) { PMAGNIF pm = &sMagnif; if( pm->hbm ) { testReplaceMagnify( hWnd, pm ); pm->hbm = NULL; } if( pm->hBitmap2 ) { DeleteObject(pm->hBitmap2); pm->hBitmap2 = NULL; } } void Do_IDM_TEST_OK( HWND hWnd ) { POINT pt; pt.x = 217; pt.y = 218; Toggle_Magnify( hWnd, pt ); //Do_Bubble_Test( hWnd, pt ); } void MouseMagnify( HWND hWnd, LPARAM lParam ) { MSG msg; RECT rcClient; POINT point; PMAGNIF pm = &sMagnif; if( pm->hbm ) Magnify2Off( hWnd ); // replace any OLD Setup_Magnify(); // set any NEW parameters point.x = LOWORD (lParam); point.y = HIWORD (lParam); SetCapture( hWnd ); GetWindowRect( hWnd, &rcClient ); Toggle_Magnify( hWnd, point ); // paint FIRST for( ; ; ) { WaitMessage(); // suspended, until message available // PeekMessage Return Values // If a message is available, the return value is nonzero. if( PeekMessage( &msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ) ) { if( pm->hbm ) Magnify2Off( hWnd ); // remove OLD point.x = LOWORD (msg.lParam); point.y = HIWORD (msg.lParam); pm->pt.x = point.x; pm->pt.y = point.y; pm->hbm = test_MagnifyPoint( hWnd, pm ); if( msg.message == WM_LBUTTONUP ) { break; // we have completed tracking } } } ReleaseCapture(); } BOOL IsMagnifyOn( void ) { PMAGNIF pm = &sMagnif; if( pm->hbm && pm->hBitmap2 ) { return TRUE; } return FALSE; } void RePaintMagnify( HDC hdc ) { PMAGNIF pm = &sMagnif; if( IsMagnifyOn() ) { HBITMAP bitmap2 = pm->hBitmap2; COLORREF rgbTransparent = pm->trans; PSIZE pszin = &pm->szin; PSIZE pszout = &pm->szout; POINT point = pm->pt; INT xo2 = pszout->cx / 2; INT yo2 = pszout->cy / 2; test_DrawTransparent( hdc, bitmap2, point.x-xo2, point.y-yo2, rgbTransparent ); // MAYBE OUTLINE THE CIRCLE! // dc.SelectObject(&CPen(PS_SOLID, 1, RGB(0, 0, 0))); // dc.SelectObject(&CBrush(NULL, RGB(0, 0, 0))); // dc.Ellipse(point.x-(60*1)-1, point.y-(60*1)-1, point.x+(60*1), point.y+(60*1)); if( bAddRedOutline ) { RECT rc; rc.left = point.x-xo2; rc.top = point.y-yo2; rc.right = rc.left + pszout->cx; rc.bottom = rc.top + pszout->cy; DrawColoredEllipse( hdc, &rc, RGB(255,0,0) ); } } } // eof - testMagnify.cxx