📄 deviceresolutionaware.h
字号:
// This is a part of the Device Resolution Aware Library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Device Resolution Aware Library and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Device Resolution Aware Library product.
#ifndef __DEVICERESOLUTIONAWARE_H__
#define __DEVICERESOLUTIONAWARE_H__
#pragma once
#ifndef _WIN32_WCE
#error DeviceResolutionAware.h is only supported on Windows CE platforms.
#endif // _WIN32_WCE
#ifndef __cplusplus
#error DRA requires C++ compilation (use a .cpp suffix)
#endif
#include <windows.h>
#include <commctrl.h>
// glc
//
// To get this .h file to compile under eVC4, we must conditionally
// include the altcecrt.h file (which exports _ASSERTE function).
//
// Since altcecrt.h is not available for eVC4, you will find all
// references to _ASSERTE used conditionally as well.
#if (_WIN32_WCE >= 501)
#include <altcecrt.h>
#endif
namespace DRA
{
////////////////////////////////////////////////////////////////////////////////
// HIDPI functions and constants.
////////////////////////////////////////////////////////////////////////////////
#ifndef _DRA_ALTERNATE_DPI
const int HIDPI = 96;
#else
const int HIDPI = _DRA_ALTERNATE_DPI;
#endif
const unsigned int ILC_COLORMASK = 0x000000FE;
//
// The two inlines HIDPISIGN and HIDPIABS are there to ensure correct rounding
// for negative numbers passed into HIDPIMulDiv as x (we want -1.5 to round
// to -1, 2.5 to round to 2, etc). So we use the absolute value of x, and then
// multiply the result by the sign of x. Y and z should never be negative, as
// y is the dpi of the device (presumably 192 or 96), and z is always 96, as
// that is our original dpi we developed on.
//
inline int HIDPISIGN(int x)
{
return (((x)<0)?-1:1);
}
inline int HIDPIABS(int x)
{
return (((x)<0)?-(x):x);
}
inline int HIDPIMulDiv(int x, int y, int z)
{
return ((((HIDPIABS(x)*(y))+((z)>>1))/(z))*HIDPISIGN(x));
}
//
// Cached values of GetDeviceCaps(LOGPIXELSX/Y) for the screen DC.
//
inline int GetScreenCaps(int nIndex)
{
// Get the DC for the entire screen
HDC hDC = ::GetDC(NULL);
if(hDC == NULL)
{
// glc
#if (_WIN32_WCE >= 501)
_ASSERTE(hDC != NULL);
#else
ASSERT(hDC != NULL);
#endif
return -1;
}
int i = ::GetDeviceCaps(hDC, nIndex);
::ReleaseDC(NULL, hDC);
return i;
}
static inline int LogPixelsX()
{
#ifndef _DRA_ADJUSTABLE_RESOLUTION
static int x = GetScreenCaps(LOGPIXELSX);
#else
int x = GetScreenCaps(LOGPIXELSX);
#endif
return x;
}
static inline int LogPixelsY()
{
#ifndef _DRA_ADJUSTABLE_RESOLUTION
static int y = GetScreenCaps(LOGPIXELSY);
#else
int y = GetScreenCaps(LOGPIXELSY);
#endif
return y;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: GetDisplayMode
//
// PURPOSE: used to determined if the display is currently configured as
// portrait, square, or landscape.
//
// ON ENTRY:
// No parameters
//
// ON EXIT:
// Returns the appropraite value from the DisplayMode enum based on the
// current display resolution.
//
enum DisplayMode
{
Landscape = -1,
Square = 0,
Portrait = 1
};
inline DisplayMode GetDisplayMode()
{
int nWidth = ::GetSystemMetrics(SM_CXSCREEN);
int nHeight = ::GetSystemMetrics(SM_CYSCREEN);
if(nHeight > nWidth)
{
return Portrait;
}
if(nHeight < nWidth)
{
return Landscape;
}
return Square;
}
// glc
//
// The following 4 functions offer alternate ways to test the
// current screen orientation and resolution, and to double
// the size of a rectangle.
inline BOOL IsLandscapeMode()
{
return (GetDisplayMode() == Landscape);
}
inline BOOL IsPortraitMode()
{
return (GetDisplayMode() == Portrait);
}
inline BOOL IsSquareMode()
{
return (GetDisplayMode() == Square);
}
inline BOOL IsHiResScreen()
{
return (LogPixelsX() > 96);
}
inline void DoubleRect(LPRECT r) // glc - Caution: assuming hi res screen is exactly 192 DPI!
{
r->bottom *= 2;
r->left *= 2;
r->right *= 2;
r->top *= 2;
return;
}
//
// Scaling inlines.
//
inline int SCALEX(int argX, int nLogPixelsX = LogPixelsX())
{
return HIDPIMulDiv(argX, nLogPixelsX, HIDPI);
}
inline int SCALEY(int argY, int nLogPixelsY = LogPixelsY())
{
return HIDPIMulDiv(argY, nLogPixelsY, HIDPI);
}
inline int UNSCALEX(int argX, int nLogPixelsX = LogPixelsX())
{
return HIDPIMulDiv(argX, HIDPI, nLogPixelsX);
}
inline int UNSCALEY(int argY, int nLogPixelsY = LogPixelsY())
{
return HIDPIMulDiv(argY, HIDPI, nLogPixelsY);
}
inline void SCALERECT(RECT rc)
{
#ifndef _DRA_ADJUSTABLE_RESOLUTION
rc.left = SCALEX(rc.left);
rc.right = SCALEX(rc.right);
rc.top = SCALEY(rc.top);
rc.bottom = SCALEY(rc.bottom);
#else // _DRA_ADJUSTABLE_RESOLUTION
int nLogPixelsX = LogPixelsX();
int nLogPixelsY = LogPixelsY();
rc.left = SCALEX(rc.left, nLogPixelsX);
rc.right = SCALEX(rc.right, nLogPixelsX);
rc.top = SCALEY(rc.top, nLogPixelsY);
rc.bottom = SCALEY(rc.bottom, nLogPixelsY);
#endif // _DRA_ADJUSTABLE_RESOLUTION
}
inline void SCALEPT(POINT pt)
{
pt.x = SCALEX(pt.x);
pt.y = SCALEY(pt.y);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: StretchIcon
//
// PURPOSE: stretches an icon to the specified size on 4.21 devices and later.
// On 4.20 and previous revisions of the OS, this is a no-op.
//
// ON ENTRY:
// HICON hiconIn: the icon to stretch.
// HICON* phiconOut: the stretched icon.
// INT cxIcon: the desired width of the icon.
// INT cyIcon: the desired height of the icon.
//
// ON EXIT:
// Returns TRUE on success, FALSE on failure.
//
inline BOOL StretchIcon(
HICON hiconIn,
HICON* phiconOut,
int cxIcon,
int cyIcon)
{
HBITMAP hBmpTemp;
*phiconOut = NULL;
HDC hdc = ::CreateCompatibleDC(NULL);
if(hdc == NULL)
{
return FALSE;
}
BOOL bRet = FALSE;
HBITMAP hbmMask = ::CreateCompatibleBitmap(hdc, cxIcon, cyIcon);
if(hbmMask != NULL)
{
HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdc, hbmMask));
if(hbmOld != NULL)
{
BOOL bRet2 = ::DrawIconEx(hdc, 0, 0, hiconIn, cxIcon, cyIcon, 0, NULL, DI_MASK);
if(bRet2 != FALSE)
{
HBITMAP hbmImage = ::CreateBitmap(cxIcon, cyIcon, 1, ::GetDeviceCaps(hdc, BITSPIXEL), NULL);
if(hbmImage != NULL)
{
hBmpTemp = static_cast<HBITMAP>(::SelectObject(hdc, hbmImage));
if(hBmpTemp != NULL)
{
bRet2 = ::DrawIconEx(hdc, 0, 0, hiconIn, cxIcon, cyIcon, 0, NULL, DI_IMAGE);
if(bRet2 != FALSE)
{
ICONINFO iconinfo;
::memset(&iconinfo, 0, sizeof(iconinfo));
iconinfo.fIcon = TRUE;
iconinfo.hbmColor = hbmImage;
iconinfo.hbmMask = hbmMask;
*phiconOut = ::CreateIconIndirect(&iconinfo);
if(phiconOut != NULL)
{
bRet = TRUE;
}
}
}
// Free the resources, but don't need to put restore original objects for deleted DCs.
// yes you do, dummy, if you want the delete to work! glc
::SelectObject(hdc, hbmOld);
::DeleteObject(hbmImage);
}
}
}
::SelectObject(hdc, hbmOld);
::DeleteObject(hbmMask);
}
::DeleteDC(hdc);
return bRet;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: GetBitmapLogPixels
//
// PURPOSE: retrieves the DPI fields of the specified bitmap.
//
// ON ENTRY:
// HINSTANCE hinst: the HINSTANCE of the bitmap resource.
// LPCTSTR lpbmp: the ID of the bitmap resource. The MAKEINTRESOURCE
// macro can be used for integer IDs.
// INT* pnLogPixelsX: the returned value for the horizontal DPI field of
// the bitmap. This value is never less than 96.
// INT* pnLogPixelsY: the returned value for the vertical DPI field of
// the bitmap. This value is never less than 96.
//
// ON EXIT:
// Returns TRUE on success, FALSE on failure.
//
inline BOOL GetBitmapLogPixels(
HINSTANCE hinst,
LPCTSTR lpbmp,
int* pnLogPixelsX,
int* pnLogPixelsY)
{
*pnLogPixelsX = 0;
*pnLogPixelsY = 0;
HRSRC hResource = ::FindResource(hinst, lpbmp, RT_BITMAP);
if(!hResource)
{
return FALSE;
}
HGLOBAL hResourceBitmap = ::LoadResource(hinst, hResource);
if(!hResourceBitmap)
{
return FALSE;
}
BITMAPINFO* pBitmapInfo = static_cast<BITMAPINFO*>(::LockResource(hResourceBitmap));
if(!pBitmapInfo)
{
return FALSE;
}
// There are at least three values of PelsPerMeter used for 96 DPI bitmap:
// 0 - the bitmap just simply doesn't set this value
// 2834 - 72 DPI (some editors just always put this in by default)
// 3780 - 96 DPI
// So any value of PelsPerMeter under 3780 should be treated as 96 DPI bitmap.
int nPelsPerMeterX = (pBitmapInfo->bmiHeader.biXPelsPerMeter < 3780) ? 3780 : pBitmapInfo->bmiHeader.biXPelsPerMeter;
int nPelsPerMeterY = (pBitmapInfo->bmiHeader.biYPelsPerMeter < 3780) ? 3780 : pBitmapInfo->bmiHeader.biYPelsPerMeter;
// The formula for converting PelsPerMeter to LogPixels(DPI) is:
// LogPixels = PelsPerMeter / 39.37
// ( PelsPerMeter : Pixels per meter )
// ( LogPixels : Pixels per inch )
// Note: We need to round up, which is why 19.68 is added (half of 39.37).
// All values are multiplied by 100 to avoid converion to float and back to int.
*pnLogPixelsX = static_cast<int>((nPelsPerMeterX * 100 + 1968) / 3937);
*pnLogPixelsY = static_cast<int>((nPelsPerMeterY * 100 + 1968) / 3937);
// There is only one system resource behind hResource, hResourceBitmap,
// and pBitmapInfo, which needs to be freed by calling DeleteObject
::DeleteObject(static_cast<HGDIOBJ>(hResourceBitmap));
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: ImageList_StretchBitmap
//
// PURPOSE: Stretches a bitmap containing a grid of images. There are
// cImagesX images per row and cImagesY rows per bitmap. Each image is
// scaled individually, so that there are no artifacts with non-integral
// scaling factors. If the bitmap contains only one image, set cImagesX
// and cImagesY to 1.
//
// ON ENTRY:
// HBITMAP* phbm: a pointer to the bitmap to be scaled.
// INT cxDstImg: the width of each image after scaling.
// INT cyDstImg: the height of each image after scaling.
// INT cImagesX: the number of images per row. This value should
// evenly divide the width of the bitmap.
// INT cImagesY: the number of rows in the bitmap. This value should
// evenly divide the height of the bitmap.
//
// ON EXIT:
// Returns TRUE on success, FALSE on failure.
//
// If any scaling has occured, the bitmap pointed to by phbm is deleted
// and is replaced by a new bitmap handle.
//
inline BOOL ImageList_StretchBitmap(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -