📄 deviceresolutionaware.h
字号:
HBITMAP hbmIn,
HBITMAP* phbmOut,
int cxDstImg,
int cyDstImg,
int cImagesX,
int cImagesY)
{
if( phbmOut == NULL ||
(cxDstImg == 0 && cyDstImg == 0) ||
(cImagesX == 0 || cImagesY == 0))
{
return FALSE;
}
if (!hbmIn)
return FALSE;
BITMAP bm;
int nSize = ::GetObject(hbmIn, sizeof(bm), &bm);
if(nSize != sizeof(bm))
{
TCHAR szMsg[255];
wsprintf(szMsg, TEXT("nSize = %d, sizeof(bm) = %d."), nSize, sizeof(bm));
MessageBox(0, szMsg, TEXT("Status"), MB_TOPMOST);
return FALSE;
}
// If you hit this ASSERT, that mean your passed in image count in row and
// the column number of images is not correct.
// glc
#if (_WIN32_WCE >= 501)
_ASSERTE(((bm.bmWidth % cImagesX) == 0) && ((bm.bmHeight % cImagesY) == 0));
#else
ASSERT(((bm.bmWidth % cImagesX) == 0) && ((bm.bmHeight % cImagesY) == 0));
#endif
int cxSrcImg = bm.bmWidth / cImagesX;
int cySrcImg = bm.bmHeight / cImagesY;
if(cxSrcImg == cxDstImg && cySrcImg == cyDstImg)
{
return TRUE;
}
if(cxDstImg == 0)
{
cxDstImg = HIDPIMulDiv(cyDstImg, cxSrcImg, cySrcImg);
}
else if(cyDstImg == 0)
{
cyDstImg = HIDPIMulDiv(cxDstImg, cySrcImg, cxSrcImg);
}
BOOL bRet = FALSE;
HBITMAP hbmNew;
HDC hdcSrc = ::CreateCompatibleDC(NULL);
if(hdcSrc != NULL)
{
HDC hdcDst = ::CreateCompatibleDC(NULL);
if(hdcDst != NULL)
{
HDC hdcScreen = ::GetDC(NULL);
if(hdcScreen != NULL)
{
HBITMAP hbmOldSrc = static_cast<HBITMAP>(::SelectObject(hdcSrc, hbmIn));
if(hbmOldSrc != NULL)
{
hbmNew = ::CreateCompatibleBitmap(hdcScreen, cxDstImg * cImagesX, cyDstImg * cImagesY);
if(hbmNew != NULL)
{
HBITMAP hbmOldDst = static_cast<HBITMAP>(::SelectObject(hdcDst, hbmNew));
if(hbmOldDst != NULL)
{
bRet = TRUE; // fix added by glc
for(int j = 0, yDest = 0, yBmp = 0;
(j < cImagesY) && (bRet != FALSE);
++j, yDest += cyDstImg, yBmp += cySrcImg)
{
for(int i = 0, xDest = 0, xBmp = 0;
(i < cImagesX) && (bRet != FALSE);
++i, xDest += cxDstImg, xBmp += cxSrcImg)
{
bRet = ::StretchBlt(
hdcDst,
xDest,
yDest,
cxDstImg,
cyDstImg,
hdcSrc,
xBmp,
yBmp,
cxSrcImg,
cySrcImg,
SRCCOPY);
}
}
}
}
}
// Free the resources, but don't need to put restore original objects for deleted DCs.
::ReleaseDC(NULL, hdcScreen);
}
::DeleteDC(hdcDst);
}
::DeleteDC(hdcSrc);
}
if(bRet != FALSE)
{
*phbmOut = hbmNew;
}
return bRet;
}
// glc
//
// A generic bitmap stretching call that replaces the HBITMAP that is passed in as the first arg.
//
// This was missing from the original code.
inline BOOL StretchBitmap(
HBITMAP* phbm,
int cxDstImg,
int cyDstImg,
int cImagesX,
int cImagesY
)
{
HBITMAP hNewBitmap;
BOOL bReturn;
bReturn = ImageList_StretchBitmap(*phbm, &hNewBitmap, cxDstImg, cyDstImg, cImagesX, cImagesY);
if (bReturn)
{
DeleteObject(*phbm);
*phbm = hNewBitmap;
}
return bReturn;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: ImageList_LoadImage
//
// PURPOSE: This function operates identically to ImageList_LoadImage, except
// that it first checks the DPI fields of the bitmap (using
// GetBitmapLogPixels); compares it to the DPI of the screen
// (using LogPixelsX() and LogPixelsY()), and performs scaling
// (using ImageList_StretchBitmap) if the values are different.
//
// ON ENTRY:
// See the MSDN documentation for ImageList_LoadImage.
//
// ON EXIT:
// See the MSDN documentation for ImageList_LoadImage.
//
inline HIMAGELIST ImageList_LoadImage(
HINSTANCE hinst,
LPCTSTR lpbmp,
int cx,
int cGrow,
COLORREF crMask,
UINT uType,
UINT uFlags)
{
UINT flags = 0;
int cy = 0;
int cImages = 0;
int cxImage = 0;
int nSize = 0;
if( uType != IMAGE_BITMAP || // Image type is not IMAGE_BITMAP
cx == 0) // Caller doesn't care about the dimensions of the image - assumes the ones in the file
{
return ::ImageList_LoadImage(hinst, lpbmp, cx, cGrow, crMask, uType, uFlags);
}
int BmpLogPixelsX;
int BmpLogPixelsY;
if(!GetBitmapLogPixels(hinst, lpbmp, &BmpLogPixelsX, &BmpLogPixelsY))
{
return NULL;
}
HIMAGELIST piml = NULL;
HBITMAP hbmImage = static_cast<HBITMAP>(::LoadImage(hinst, lpbmp, uType, 0, 0, uFlags));
if(hbmImage == NULL)
{
goto cleanup;
}
BITMAP bm;
nSize = ::GetObject(hbmImage, sizeof(bm), &bm);
if(nSize != sizeof(bm))
{
goto cleanup;
}
if(BmpLogPixelsX == LogPixelsX())
{
// do not need to scale the bitmap
piml = ::ImageList_LoadImage(hinst, lpbmp, cx, cGrow, crMask, uType, uFlags);
goto cleanup;
}
cxImage = HIDPIMulDiv(cx, BmpLogPixelsX, LogPixelsX());
// Bitmap width should be multiple integral of image width.
// If not, that means either your bitmap is wrong or passed in cx is wrong.
// glc
#if (_WIN32_WCE >= 501)
_ASSERTE((bm.bmWidth % cxImage) == 0);
#else
ASSERT((bm.bmWidth % cxImage) == 0);
#endif
cImages = bm.bmWidth / cxImage;
cy = HIDPIMulDiv(bm.bmHeight, LogPixelsY(), BmpLogPixelsY);
HBITMAP hbmStretched;
BOOL bRet;
if((LogPixelsX() % BmpLogPixelsX) == 0)
{
bRet = ImageList_StretchBitmap(hbmImage, &hbmStretched, cx * cImages, cy, 1, 1);
}
else
{
// Here means the DPI is not integral multiple of standard DPI (96DPI).
// So if we stretch entire bitmap together, we are not sure each indivisual
// image will be stretch to right place. It is controled by StretchBlt().
// (for example, a 16 pixel icon, the first one might be stretch to 22 pixels
// and next one might be stretched to 20 pixels)
// What we have to do here is stretching indivisual image separately to make sure
// every one is stretched properly.
bRet = ImageList_StretchBitmap(hbmImage, &hbmStretched, cx, cy, cImages, 1);
}
if(bRet == FALSE)
{
goto cleanup;
}
//UINT flags = 0;
// ILC_MASK is important for supporting CLR_DEFAULT
if(crMask != CLR_NONE)
{
flags |= ILC_MASK;
}
// ILC_COLORMASK bits are important if we ever want to Merge ImageLists
if(bm.bmBits)
{
flags |= (bm.bmBitsPixel & ILC_COLORMASK);
}
// bitmap MUST be de-selected from the DC
// create the image list of the size asked for.
piml = ::ImageList_Create(cx, cy, flags, cImages, cGrow);
if(piml)
{
int added;
// fixed by glc
#if 0
if(crMask == CLR_NONE)
{
added = ::ImageList_Add(piml, hbmImage, NULL);
}
else
{
added = ::ImageList_AddMasked(piml, hbmImage, crMask);
}
#else
if(crMask == CLR_NONE)
{
added = ::ImageList_Add(piml, hbmStretched, NULL);
}
else
{
added = ::ImageList_AddMasked(piml, hbmStretched, crMask);
}
#endif
if(added < 0)
{
::ImageList_Destroy(piml);
piml = NULL;
}
}
::DeleteObject(hbmStretched);
cleanup:
::DeleteObject(hbmImage);
return piml;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: ImageList_ReplaceIcon
//
// PURPOSE: Replaces an icon in an ImageList, scaling it from its original size
// to the size of the images in the ImageList.
//
// ON ENTRY:
// See the MSDN documentation for ImageList_ReplaceIcon.
//
// ON EXIT:
// See the MSDN documentation for ImageList_ReplaceIcon.
//
inline int ImageList_ReplaceIcon(HIMAGELIST himl, int i, HICON hicon)
{
int cxIcon, cyIcon;
BOOL bRet = ::ImageList_GetIconSize(himl, &cxIcon, &cyIcon);
if(bRet == FALSE)
{
return -1; // per MSDN documentation for ImageList_ReplaceIcon.
}
HICON hiconStretched;
StretchIcon(hicon, &hiconStretched, cxIcon, cyIcon);
int iRet;
if(hiconStretched != NULL)
{
iRet = ::ImageList_ReplaceIcon(himl, i, hiconStretched);
::DestroyIcon(hiconStretched);
}
else
{
iRet = ::ImageList_ReplaceIcon(himl, i, hicon);
}
return iRet;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: ImageList_AddIcon
//
// PURPOSE: Adds an icon to an ImageList, scaling it from its original size
// to the size of the images in the ImageList.
//
// ON ENTRY:
// See the MSDN documentation for ImageList_AddIcon.
//
// ON EXIT:
// See the MSDN documentation for ImageList_AddIcon.
//
// ImageList_AddIcon is defined as a macro in commctrl.h
#ifdef ImageList_AddIcon
#undef ImageList_AddIcon
#endif
inline int ImageList_AddIcon(HIMAGELIST himl, HICON hicon)
{
return DRA::ImageList_ReplaceIcon(himl, -1, hicon);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: Rectangle
//
// PURPOSE: Draws a rectangle using the currently selected pen. Drawing occurs
// completely within the drawing rectangle (the rectangle has an "inside
// frame" drawing style).
//
// ON ENTRY:
// HDC hdc: the display context of the drawing surface.
// INT nLeft: left bound of rectangle
// INT nTop: top bound of rectangle
// INT nRight: right bound of rectangle plus one.
// INT nBottom: bottom bound of rectangle plus one.
//
// ON EXIT:
// Returns TRUE on success, FALSE on failure.
//
inline BOOL Rectangle(HDC hdc, int nLeft, int nTop, int nRight, int nBottom)
{
// Obtain current pen thickness
HPEN hpenSel = static_cast<HPEN>(::GetCurrentObject(hdc, OBJ_PEN));
if(hpenSel == NULL)
{
return FALSE;
}
LOGPEN lpenSel;
int iRet = ::GetObject(hpenSel, sizeof(lpenSel), &lpenSel);
if(iRet == 0)
{
return FALSE;
}
int nOff = lpenSel.lopnWidth.x/2;
nLeft += nOff;
nTop += nOff;
nRight -= nOff;
nBottom -= nOff;
return ::Rectangle(hdc, nLeft, nTop, nRight, nBottom);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: Polyline
//
// PURPOSE: Draws a polyline using the currently selected pen. In addition,
// this function provides control over how the line will be drawn.
//
// ON ENTRY:
// HDC hdc: the display context of the drawing surface.
// const POINT* lppt: array of POINTS that specify line to draw.
// INT cPoints: number of points in array.
// INT nStyle: the style the pen should be drawn in. This may be an
// existing pen style, such as PS_SOLID, or one of the following styles:
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -