DM界面库DPI改造之路(和图片拉伸防锯齿)

DM界面库简介:
DM是Dui Magic的简称,是一套基于商业化标准的开源directui界面框架,不仅能提供完善的项目管理方案、详细的文档框架,也可轻松协助完成可视化界面设计,其核心库的稳定性已在内部多个大型商化项目中通过验证。界面库开始编写于2014年,2015年年中基本完成主框架代码的编写,之后不断完善和维护,代码主程笔者的前同事hgy413,他曾经是YY游戏运营中心的windows C++桌面客户端的资深架构师,笔者曾经也是该库的深度开发及维护者,我们曾努力致力把DM打造成全网最好的windows界面库。
原博客地址:REDM-开源的商业化DirectUI库_花熊的博客-CSDN博客

引言:

在高分辨率的屏幕上(比如当下主流的笔记本),我们通常会设置windows的显示缩放进行比例拉伸,这样可以避免程序的显示过小而看不清,不方便操作:
                                    

但是程序界面经过系统拉伸之后,无论是界面上的图片和文字因为经过系统拉伸,而显得模糊,而对于那些对界面显示分辨率有较高要求(比如分辨率的游戏)的用户,是不想程序被系统进行拉伸的,这种情况下,我们只需要通过调用系统API:SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);来设置dpi,这种情况下,表明程序拒绝被系统进行拉伸,我们看看这两种情况下的效果对比:

  • 上面左边的图是被系统进行2.5倍拉伸的效果,界面显示被放大,用户方便操作,但是缺点是界面的图片和字体比较模糊。
  • 上面右边的图是拒绝被系统进行拉伸的效果,界面显示没有经过放大,但是界面的字体和图片没有经过拉伸,显示是清晰的,但是缺点就是界面显示比较小,非常不方便用户进行操作。

 引入主题:

界面的DPI改造就是把上面的右图窗口大小进行2.5倍拉伸,达到左图的效果,这样窗口的显示既满足了界面显示清晰,又达到了方便用户操作的目的。

怎么实现呢(可能会遇到的挑战):

  1. 把窗口大小进行等比例拉伸,即窗口在创建的时候进行倍率拉伸:

  2. 上图右图,界面经过倍率拉伸之后以及控件坐标和字体大小进行简单的转换之后,窗口大小跟左边一致了,但是依然有很多的问题需要解决,比如:

    一.

    上面右图是经过DPI改造后,但是里面的tablayout布局对子控件还没进行布局处理,控件位置和大小没有做倍率拉伸处理,所以显示上跟原布局会有问题。布局分了好几种布局,比如描点布局、水平布局、垂直布局、spliter布局等,这些都要找到合适的地方进行对坐标和控件大小进行处理。
    二.

    上面右图是经过DPI改造后,里面的listctrl控件跟左边的item高度跟原高度不相同,这些控件布局以及控件宽高都需要做调整。DM里面的控件很多,这些控件可能都需要做相应的转换和处理。
  3. ...
     

 如何调整(部分调整的代码展示):

  1. 处理窗口创建时候的宽高:

    如上图,在加载xml的时候,就对创建窗口的初始宽高进行DPI等比例拉伸处理
  2. 控件坐标转换:

  3. 字体大小的调整:

  4. 子窗口控件宽高转换:

  5. ......

     

 DPI改造之后效果对比:

好了,经过改造,从图1到图2再到图3,我们几乎以及改造的几乎一样了,基本完成了DPI的改造工作。图3比图1字体上看清晰很多。

 但经过对比,发现,DPI改造之后的图像经过拉伸之后,出现了明显的锯齿状。这也是需要解决的另一个问题,就是图片拉伸防锯齿功能。

 

图片拉伸防锯齿功能:

这里引入了一种图片拉伸填充算法,原理就是在图片拉伸的时候通过图像算法,填充图片因为拉伸而缺失的像素,达到“羽化”的效果。

打开图片拉伸防锯齿功能:

图片拉伸防锯齿功能不是默认带的,需要手动开启,开启方法就是在CMake之前勾选USE_XGRAPHIC32选项,然后重新生成工程,重新编译工程即可。

重新生成工程之后,工程会自动加入xGraphic32图像算法代码以及SmoothBmp注册替换画布插件代码:

 打开图片拉伸防锯齿功能之后(可能是截图工具限制,截图可能看起来效果不明显):

 经过改造,图片拉伸的锯齿得到了明显的改善。

好了,到了这里,就基本完成了DPI功能的改造了,如果开启DPI功能,建议也开启图片拉伸防锯齿功能,图片拉伸防锯齿算法比较消耗CPU,但笔者已经对此做了缓存上的优化,不影响效率,可放心使用。

附录:

1.因为DPI功能改造刚改造不久,后续才会将代码合入主线,目前可以在我的代码仓库上进行下载:
DM: REDM是一套基于商业化标准的开源directui界面框架,不仅能提供完善的项目管理方案、详细的文档框架,也可轻松协助完成可视化界面设计,其核心库的稳定性已在内部多个大型商化项目中通过验证。

2.这里截取一段自己写的代码作为参考:
 

//-------------------------------------------------------
// Copyright (c) DuiMagic
// All rights reserved.
// 
// File Name: DMDPIHelper.h 
// File Des: DPI转换工具类
/* Use  Des:
	DMApp theApp(hInstance);
	DMDPIHelper::EnableHIDPI(true); // 程序高清支持 SetProcessDpiAwareness
	DMDPIHelper::getSingleton().SetDPIAdaptFlag(true); // 设置dpi标志
	DPISCALE_X(10);  // 传右值 结果返回经过乘积
	DPISCALE_X(i);   // 传变量 不会改变i的值 等价:DPISCALE_X_T<int>(i);
	DPISCALE_X_T<int&>(i); // 传引用 会改变i的值
	DPISCALE_X(&i);  // 传指针 会改变i的值 等价:DPISCALE_X_T<int*>(&i);
	DPIUNSCALE_X(10);
	DPISCALE_X_T<int>(20);

	CSize size(10, 20);
	CRect rect(10, 20, 30, 40);
	CSize rtSize = DPISCALE_OBJ(size);  // 传CSize对象 不会改变size的值
	CRect rtRect = DPISCALE_OBJ(rect);  // 传CRect对象 不会改变rect的值
	CSize rtSize2 = DPISCALE_OBJ_T<CSize&>(size); // 传CSize引用 会改变size的值
	CSize rtSize3 = DPISCALE_OBJ_T<CSize*>(&size); // 传CSize指针 会改变size的值
	DPIUNSCALE_OBJ(size); // 传CSize对象 不会改变size的值 等价:DPIUNSCALE_OBJ_T<CSize>(rect);
	DPIUNSCALE_OBJ(rect); // 传CRect对象 不会改变rect的值 等价:DPIUNSCALE_OBJ_T<CRect>(rect);
	DPIUNSCALE_OBJ_T<CRect&>(rect);  // 传CSize引用 会改变size的值
	DPIUNSCALE_OBJ_T<CRect*>(&rect); // 传CSize指针 会改变size的值
*/
// File Summary: 
// Cur Version: 1.0
// Author:
// Create Data:
// History:
// 		<Author>	<Time>		<Version>	  <Des>
//      zeron		2022-5-7	1.0			
//-------------------------------------------------------
#pragma once

#define DPISCALE_X(val)		DMDPIHelper::getSingleton().DpiScaleX<decltype(val)>(val)
#define DPISCALE_X_T		DMDPIHelper::getSingleton().DpiScaleX
#define DPIUNSCALE_X(val)	DMDPIHelper::getSingleton().DpiUnScaleX<decltype(val)>(val)
#define DPIUNSCALE_X_T		DMDPIHelper::getSingleton().DpiUnScaleX

#define DPISCALE_Y(val)		DMDPIHelper::getSingleton().DpiScaleY<decltype(val)>(val)
#define DPISCALE_Y_T		DMDPIHelper::getSingleton().DpiScaleY
#define DPIUNSCALE_Y(val)	DMDPIHelper::getSingleton().DpiUnScaleY<decltype(val)>(val)
#define DPIUNSCALE_Y_T		DMDPIHelper::getSingleton().DpiUnScaleY

#define DPISCALE_OBJ(val)	DMDPIHelper::getSingleton().DpiScaleObj<decltype(val)>(val)
#define DPISCALE_OBJ_T		DMDPIHelper::getSingleton().DpiScaleObj
#define DPIUNSCALE_OBJ(val) DMDPIHelper::getSingleton().DpiUnScaleObj<decltype(val)>(val)
#define DPIUNSCALE_OBJ_T	DMDPIHelper::getSingleton().DpiUnScaleObj

#define ISDPISCALED  DMDPIHelper::getSingleton().IsNeededScale()
#define DPIEXTENDX(X) (ISDPISCALED ? X : 0)
#define DPISCALEXVAL DMDPIHelper::getSingleton().GetDPIScaleX()
#define DPISCALEYVAL DMDPIHelper::getSingleton().GetDPIScaleY()
#define CHECK_DPIXY(val) if (DMDPIHelper::getSingleton().GetDPIX() == 96 && DMDPIHelper::getSingleton().GetDPIY() == 96) { return val; }
#define CHECK_DPIX(val) if (DMDPIHelper::getSingleton().GetDPIX() == 96) { return val; }
#define CHECK_DPIY(val) if (DMDPIHelper::getSingleton().GetDPIY() == 96) { return val; }

namespace DM
{
	/// <summary>
	///		DPI转换工具类
	/// </summary>
	class DM_EXPORT DMDPIHelper:public DMSingletonT<DMDPIHelper>
	{
	public:
		DMDPIHelper();
		static void EnableHIDPI(bool enable = true);

		void SetDPIAdaptFlag(bool bDPIAdaptFlag, bool bEnableHIDPI = true);
		bool GetDPIAdaptFlag();

		// Get screen DPI.
		int GetDPIX();
		int GetDPIY();

		// Get windows real screen DPI.
		int GetRealDPIX();
		int GetRealDPIY();

		// Get DPI Scale.
		float GetDPIScaleX();
		float GetDPIScaleY();

		//---------------------------------------------------
		// Function Des: 参数类型类别说明
		//---------------------------------------------------
		template <typename T>
		struct TupleTraits
		{
			typedef T ValueType;
			typedef T& RefType;
			typedef const T& ParamType;
		};

		template <typename T>
		struct TupleTraits<T&>
		{
			typedef T ValueType;
			typedef T& RefType;
			typedef T& ParamType;
		};

		template <typename T>
		struct TupleTraits<T*>
		{
			typedef T ValueType;
			typedef T*& RefType;
			typedef T* ParamType;
		};

		//---------------------------------------------------
		// Function Des: DPI乘积方法
		//---------------------------------------------------
		template<class T>
		struct MultiplyTraits
		{
			typedef const T Param;
			typedef typename TupleTraits<Param>::ValueType ReturnType;
			typedef typename TupleTraits<Param>::ParamType ParamType;

			///-------------- ScaleMultiplyT
			static inline ReturnType ScaleMultiplyT(ParamType tValue, float fScale)
			{
				CHECK_DPIXY(tValue);
				return static_cast<ReturnType>(tValue * fScale);
			}

			///-------------- UnScaleDivideT
			static inline ReturnType UnScaleDivideT(ParamType tValue, float fScale)
			{
				CHECK_DPIXY(tValue);
				return static_cast<ReturnType>(tValue / fScale);
			}

			//---------------------------------------------------
			// Function Des:  ScaleMultiplyObj声明
			//---------------------------------------------------
			template<class E>
			static inline typename TupleTraits<E>::ValueType ScaleMultiplyObj(typename TupleTraits<E>::ParamType tValue);

			/// --------------------  特化 好像不是特化 是重载     RECT CRect
			static inline typename TupleTraits<RECT>::ValueType ScaleMultiplyObj(typename TupleTraits<RECT>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				RECT rtRect;
				rtRect.left = (tValue.left == -1) ? tValue.left : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.left, DPISCALEXVAL);
				rtRect.top = (tValue.top == -1) ? tValue.top : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.top, DPISCALEYVAL);
				rtRect.right = (tValue.right == -1) ? tValue.right : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.right, DPISCALEXVAL);
				rtRect.bottom = (tValue.bottom == -1) ? tValue.bottom : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.bottom, DPISCALEYVAL);
				return rtRect;
			}

			static inline typename TupleTraits<DM::CRect>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CRect>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				DM::CRect rtRect;
				rtRect.left = (tValue.left == -1) ? tValue.left : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.left, DPISCALEXVAL);
				rtRect.top = (tValue.top == -1) ? tValue.top : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.top, DPISCALEYVAL);
				rtRect.right = (tValue.right == -1) ? tValue.right : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.right, DPISCALEXVAL);
				rtRect.bottom = (tValue.bottom == -1) ? tValue.bottom : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.bottom, DPISCALEYVAL);
				return rtRect;
			}

			///------------------------------------------------------- SIZE CSize
			static inline typename TupleTraits<SIZE>::ValueType ScaleMultiplyObj(typename TupleTraits<SIZE>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				SIZE sz;
				sz.cx = (tValue.cx == -1) ? tValue.cx : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.cx, DPISCALEXVAL);
				sz.cy = (tValue.cy == -1) ? tValue.cy : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.cy, DPISCALEYVAL);
				return sz;
			}

			static inline typename TupleTraits<DM::CSize>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CSize>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				DM::CSize sz;
				sz.cx = (tValue.cx == -1) ? tValue.cx : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.cx, DPISCALEXVAL);
				sz.cy = (tValue.cy == -1) ? tValue.cy : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.cy, DPISCALEYVAL);
				return sz;
			}

			///------------------------------------------------------- POINT CPoint
			static inline typename TupleTraits<POINT>::ValueType ScaleMultiplyObj(typename TupleTraits<POINT>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				POINT pt;
				pt.x = (tValue.x == -1) ? tValue.x : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.x, DPISCALEXVAL);
				pt.y = (tValue.y == -1) ? tValue.y : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.y, DPISCALEYVAL);
				return pt;
			}

			static inline typename TupleTraits<DM::CPoint>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CPoint>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				DM::CPoint pt;
				pt.x = (tValue.x == -1) ? tValue.x : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.x, DPISCALEXVAL);
				pt.y = (tValue.y == -1) ? tValue.y : MultiplyTraits<LONG>::ScaleMultiplyT(tValue.y, DPISCALEYVAL);
				return pt;
			}
			
			//---------------------------------------------------
			// Function Des: UnScaleDevideObj声明
			//---------------------------------------------------
			template<class E>
			static inline typename TupleTraits<E>::ValueType UnScaleDevideObj(typename TupleTraits<E>::ParamType tValue);

			/// ----------------------------------------- RECT CRect
			static inline typename TupleTraits<RECT>::ValueType UnScaleDevideObj(typename TupleTraits<RECT>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				RECT rtRect;
				rtRect.left = (tValue.left == -1) ? tValue.left : MultiplyTraits<LONG>::UnScaleDivideT(tValue.left, DPISCALEXVAL);
				rtRect.top = (tValue.top == -1) ? tValue.top : MultiplyTraits<LONG>::UnScaleDivideT(tValue.top, DPISCALEYVAL);
				rtRect.right = (tValue.right == -1) ? tValue.right : MultiplyTraits<LONG>::UnScaleDivideT(tValue.right, DPISCALEXVAL);
				rtRect.bottom = (tValue.bottom == -1) ? tValue.bottom : MultiplyTraits<LONG>::UnScaleDivideT(tValue.bottom, DPISCALEYVAL);
				return rtRect;
			}

			static inline typename TupleTraits<DM::CRect>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CRect>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				DM::CRect rtRect;
				rtRect.left = (tValue.left == -1) ? tValue.left : MultiplyTraits<LONG>::UnScaleDivideT(tValue.left, DPISCALEXVAL);
				rtRect.top = (tValue.top == -1) ? tValue.top : MultiplyTraits<LONG>::UnScaleDivideT(tValue.top, DPISCALEYVAL);
				rtRect.right = (tValue.right == -1) ? tValue.right : MultiplyTraits<LONG>::UnScaleDivideT(tValue.right, DPISCALEXVAL);
				rtRect.bottom = (tValue.bottom == -1) ? tValue.bottom : MultiplyTraits<LONG>::UnScaleDivideT(tValue.bottom, DPISCALEYVAL);
				return rtRect;
			}

			///------------------------------------------------------- SIZE CSize
			static inline typename TupleTraits<SIZE>::ValueType UnScaleDevideObj(typename TupleTraits<SIZE>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				SIZE sz;
				sz.cx = (tValue.cx == -1) ? tValue.cx : MultiplyTraits<LONG>::UnScaleDivideT(tValue.cx, DPISCALEXVAL);
				sz.cy = (tValue.cy == -1) ? tValue.cy : MultiplyTraits<LONG>::UnScaleDivideT(tValue.cy, DPISCALEYVAL);
				return sz;
			}

			static inline typename TupleTraits<DM::CSize>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CSize>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				DM::CSize sz;
				sz.cx = (tValue.cx == -1) ? tValue.cx : MultiplyTraits<LONG>::UnScaleDivideT(tValue.cx, DPISCALEXVAL);
				sz.cy = (tValue.cy == -1) ? tValue.cy : MultiplyTraits<LONG>::UnScaleDivideT(tValue.cy, DPISCALEYVAL);
				return sz;
			}

			///------------------------------------------------------- POINT CPoint
			static inline typename TupleTraits<POINT>::ValueType UnScaleDevideObj(typename TupleTraits<POINT>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				POINT pt;
				pt.x = (tValue.x == -1) ? tValue.x : MultiplyTraits<LONG>::UnScaleDivideT(tValue.x, DPISCALEXVAL);
				pt.y = (tValue.y == -1) ? tValue.y : MultiplyTraits<LONG>::UnScaleDivideT(tValue.y, DPISCALEYVAL);
				return pt;
			}

			static inline typename TupleTraits<DM::CPoint>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CPoint>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				DM::CPoint pt;
				pt.x = (tValue.x == -1) ? tValue.x : MultiplyTraits<LONG>::UnScaleDivideT(tValue.x, DPISCALEXVAL);
				pt.y = (tValue.y == -1) ? tValue.y : MultiplyTraits<LONG>::UnScaleDivideT(tValue.y, DPISCALEYVAL);
				return pt;
			}
		};

		//---------------------------------------------------
		// Function Des: 特化引用类型的参数
		//---------------------------------------------------
		template<class T>
		struct MultiplyTraits<T&>
		{
			typedef T& Param;
			typedef typename TupleTraits<Param>::ValueType ReturnType;
			typedef typename TupleTraits<Param>::ParamType ParamType;

			///-------------- ScaleMultiplyT
			static inline ReturnType ScaleMultiplyT(ParamType tValue, float fScale)
			{
				CHECK_DPIXY(tValue);
				tValue = static_cast<ReturnType>(tValue * fScale);
				return tValue;
			}

			///-------------- UnScaleDivideT
			static inline ReturnType UnScaleDivideT(ParamType tValue, float fScale)
			{
				CHECK_DPIXY(tValue);
				tValue = static_cast<ReturnType>(tValue / fScale);
				return tValue;
			}

			//---------------------------------------------------
			// Function Des:  ScaleMultiplyObj声明
			//---------------------------------------------------
			template<class E>
			static inline typename TupleTraits<E&>::ValueType ScaleMultiplyObj(typename TupleTraits<E&>::ParamType tValue);

			/// --------------------  特化 好像不是特化 是重载     RECT CRect
			static inline typename TupleTraits<RECT&>::ValueType ScaleMultiplyObj(typename TupleTraits<RECT&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.left != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.left, DPISCALEXVAL);
				if(tValue.top != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.top, DPISCALEYVAL);
				if(tValue.right != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.right, DPISCALEXVAL);
				if(tValue.bottom != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.bottom, DPISCALEYVAL);
				return tValue;
			}

			static inline typename TupleTraits<DM::CRect&>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CRect&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if (tValue.left != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.left, DPISCALEXVAL);
				if (tValue.top != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.top, DPISCALEYVAL);
				if (tValue.right != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.right, DPISCALEXVAL);
				if (tValue.bottom != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.bottom, DPISCALEYVAL);
				return tValue;
			}

			///------------------------------------------------------- SIZE CSize
			static inline typename TupleTraits<SIZE&>::ValueType ScaleMultiplyObj(typename TupleTraits<SIZE&>::ParamType tValue)
			{
				if(tValue.cx != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.cx, DPISCALEXVAL);
				if(tValue.cy != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.cy, DPISCALEYVAL);
				return tValue;
			}

			static inline typename TupleTraits<DM::CSize&>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CSize&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if (tValue.cx != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.cx, DPISCALEXVAL);
				if (tValue.cy != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.cy, DPISCALEYVAL);
				return tValue;
			}

			///------------------------------------------------------- POINT CPoint
			static inline typename TupleTraits<POINT&>::ValueType ScaleMultiplyObj(typename TupleTraits<POINT&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.x != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.x, DPISCALEXVAL);
				if(tValue.y != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.y, DPISCALEYVAL);
				return tValue;
			}

			static inline typename TupleTraits<DM::CPoint&>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CPoint&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.x != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.x, DPISCALEXVAL);
				if(tValue.y != -1) MultiplyTraits<LONG&>::ScaleMultiplyT(tValue.y, DPISCALEYVAL);
				return tValue;
			}

			//---------------------------------------------------
			// Function Des: UnScaleDevideObj声明
			//---------------------------------------------------
			template<class E>
			static inline typename TupleTraits<E&>::ValueType UnScaleDevideObj(typename TupleTraits<E&>::ParamType tValue);

			/// ----------------------------------------- RECT CRect
			static inline typename TupleTraits<RECT&>::ValueType UnScaleDevideObj(typename TupleTraits<RECT&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.left != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.left, DPISCALEXVAL);
				if(tValue.top != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.top, DPISCALEYVAL);
				if(tValue.right != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.right, DPISCALEXVAL);
				if(tValue.bottom != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.bottom, DPISCALEYVAL);
				return tValue;
			}

			static inline typename TupleTraits<DM::CRect&>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CRect&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.left != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.left, DPISCALEXVAL);
				if(tValue.top != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.top, DPISCALEYVAL);
				if(tValue.right != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.right, DPISCALEXVAL);
				if(tValue.bottom != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.bottom, DPISCALEYVAL);
				return tValue;
			}

			///------------------------------------------------------- SIZE CSize
			static inline typename TupleTraits<SIZE&>::ValueType UnScaleDevideObj(typename TupleTraits<SIZE&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.cx != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.cx, DPISCALEXVAL);
				if(tValue.cy != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.cy, DPISCALEYVAL);
				return tValue;
			}

			static inline typename TupleTraits<DM::CSize&>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CSize&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if(tValue.cx != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.cx, DPISCALEXVAL);
				if(tValue.cy != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.cy, DPISCALEYVAL);
				return tValue;
			}

			///------------------------------------------------------- POINT CPoint
			static inline typename TupleTraits<POINT&>::ValueType UnScaleDevideObj(typename TupleTraits<POINT&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if (tValue.x != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.x, DPISCALEXVAL);
				if (tValue.y != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.y, DPISCALEYVAL);
				return tValue;
			}

			static inline typename TupleTraits<DM::CPoint&>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CPoint&>::ParamType tValue)
			{
				CHECK_DPIXY(tValue);
				if (tValue.x != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.x, DPISCALEXVAL);
				if (tValue.y != -1) MultiplyTraits<LONG&>::UnScaleDivideT(tValue.y, DPISCALEYVAL);
				return tValue;
			}
		};

		//---------------------------------------------------
		// Function Des: 特化指针类型的参数
		//---------------------------------------------------
		template<class T>
		struct MultiplyTraits<T*>
		{
			typedef T* Param;
			typedef typename TupleTraits<Param>::ValueType ReturnType;
			typedef typename TupleTraits<Param>::ParamType ParamType;

			static inline ReturnType ScaleMultiplyT(ParamType tValue, float fScale)
			{
				if (!tValue)
				{
					return static_cast<ReturnType>(0);
				}
				CHECK_DPIXY(*tValue);
				*tValue = static_cast<ReturnType>((*tValue) * fScale);
				return *tValue;
			}

			///-------------- UnScaleDivideT
			static inline ReturnType UnScaleDivideT(ParamType tValue, float fScale)
			{
				if (!tValue)
				{
					return static_cast<ReturnType>(0);
				}
				CHECK_DPIXY(*tValue);
				*tValue = static_cast<ReturnType>(*tValue / fScale);
				return *tValue;
			}

			//---------------------------------------------------
			// Function Des:  ScaleMultiplyObj声明
			//---------------------------------------------------
			template<class E>
			static inline typename TupleTraits<E*>::ValueType ScaleMultiplyObj(typename TupleTraits<E*>::ParamType tValue);

			/// --------------------  特化 好像不是特化 是重载     RECT CRect
			static inline typename TupleTraits<RECT*>::ValueType ScaleMultiplyObj(typename TupleTraits<RECT*>::ParamType tValue)
			{
				if (!tValue)
				{
					return {0, 0, 0, 0};
				}
				CHECK_DPIXY(*tValue);
				if (tValue->left != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->left, DPISCALEXVAL);
				if (tValue->top != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->top, DPISCALEYVAL);
				if (tValue->right != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->right, DPISCALEXVAL);
				if (tValue->bottom != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->bottom, DPISCALEYVAL);
				return *tValue;
			}

			static inline typename TupleTraits<DM::CRect*>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CRect*>::ParamType tValue)
			{
				if (!tValue)
				{
					return DM::CRect( 0,0,0,0 );
				}
				CHECK_DPIXY(*tValue);
				if (tValue->left != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->left, DPISCALEXVAL);
				if (tValue->top != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->top, DPISCALEYVAL);
				if (tValue->right != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->right, DPISCALEXVAL);
				if (tValue->bottom != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->bottom, DPISCALEYVAL);
				return *tValue;
			}

			///------------------------------------------------------- SIZE CSize
			static inline typename TupleTraits<SIZE*>::ValueType ScaleMultiplyObj(typename TupleTraits<SIZE*>::ParamType tValue)
			{
				if (!tValue)
				{
					return {0, 0};
				}
				if (tValue->cx != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->cx, DPISCALEXVAL);
				if (tValue->cy != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->cy, DPISCALEYVAL);
				return *tValue;
			}

			static inline typename TupleTraits<DM::CSize*>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CSize&>::ParamType tValue)
			{
				if (!tValue)
				{
					return DM::CSize(0, 0);
				}
				CHECK_DPIXY(*tValue);
				if (tValue->cx != -1) MultiplyTraits<INT*>::ScaleMultiplyT(&tValue->cx, DPISCALEXVAL);
				if (tValue->cy != -1) MultiplyTraits<INT*>::ScaleMultiplyT(&tValue->cy, DPISCALEYVAL);
				return *tValue;
			}

			///------------------------------------------------------- POINT CPoint
			static inline typename TupleTraits<POINT*>::ValueType ScaleMultiplyObj(typename TupleTraits<POINT*>::ParamType tValue)
			{
				if (!tValue)
				{
					return { 0, 0 };
				}
				CHECK_DPIXY(*tValue);
				if (tValue->x != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->x, DPISCALEXVAL);
				if (tValue->y != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->y, DPISCALEYVAL);
				return *tValue;
			}

			static inline typename TupleTraits<DM::CPoint*>::ValueType ScaleMultiplyObj(typename TupleTraits<DM::CPoint*>::ParamType tValue)
			{
				if (!tValue)
				{
					return DM::CPoint(0, 0);
				}
				CHECK_DPIXY(*tValue);
				if (tValue->x != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->x, DPISCALEXVAL);
				if (tValue->y != -1) MultiplyTraits<LONG*>::ScaleMultiplyT(&tValue->y, DPISCALEYVAL);
				return *tValue;
			}

			//---------------------------------------------------
			// Function Des: UnScaleDevideObj声明
			//---------------------------------------------------
			template<class E>
			static inline typename TupleTraits<E*>::ValueType UnScaleDevideObj(typename TupleTraits<E*>::ParamType tValue);

			/// ----------------------------------------- RECT CRect
			static inline typename TupleTraits<RECT*>::ValueType UnScaleDevideObj(typename TupleTraits<RECT*>::ParamType tValue)
			{
				if (!tValue)
				{
					return { 0,0,0,0 };
				}
				CHECK_DPIXY(*tValue);
				if (tValue->left != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->left, DPISCALEXVAL);
				if (tValue->top != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->top, DPISCALEYVAL);
				if (tValue->right != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->right, DPISCALEXVAL);
				if (tValue->bottom != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->bottom, DPISCALEYVAL);
				return *tValue;
			}

			static inline typename TupleTraits<DM::CRect*>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CRect*>::ParamType tValue)
			{
				if (!tValue)
				{
					return DM::CRect(0,0,0,0);
				}
				CHECK_DPIXY(*tValue);
				if (tValue->left != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->left, DPISCALEXVAL);
				if (tValue->top != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->top, DPISCALEYVAL);
				if (tValue->right != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->right, DPISCALEXVAL);
				if (tValue->bottom != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->bottom, DPISCALEYVAL);
				return *tValue;
			}

			///------------------------------------------------------- SIZE CSize
			static inline typename TupleTraits<SIZE*>::ValueType UnScaleDevideObj(typename TupleTraits<SIZE*>::ParamType tValue)
			{
				if (!tValue)
				{
					return {0, 0};
				}
				CHECK_DPIXY(*tValue);
				if (tValue->cx != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->cx, DPISCALEXVAL);
				if (tValue->cy != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->cy, DPISCALEYVAL);
				return *tValue;
			}

			static inline typename TupleTraits<DM::CSize&>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CSize&>::ParamType tValue)
			{
				if (!tValue)
				{
					return DM::CSize(0, 0 );
				}
				CHECK_DPIXY(*tValue);
				if (tValue->cx != -1) MultiplyTraits<INT*>::UnScaleDivideT(&tValue->cx, DPISCALEXVAL);
				if (tValue->cy != -1) MultiplyTraits<INT*>::UnScaleDivideT(&tValue->cy, DPISCALEYVAL);
				return *tValue;
			}

			///------------------------------------------------------- POINT CPoint
			static inline typename TupleTraits<POINT*>::ValueType UnScaleDevideObj(typename TupleTraits<POINT*>::ParamType tValue)
			{
				if (!tValue)
				{
					return{ 0, 0 };
				}
				CHECK_DPIXY(*tValue);
				if (tValue->x != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->x, DPISCALEXVAL);
				if (tValue->y != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->y, DPISCALEYVAL);
				return *tValue;
			}

			static inline typename TupleTraits<DM::CPoint*>::ValueType UnScaleDevideObj(typename TupleTraits<DM::CPoint*>::ParamType tValue)
			{
				if (!tValue)
				{
					return DM::CPoint( 0, 0);
				}
				CHECK_DPIXY(*tValue);
				if (tValue->x != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->x, DPISCALEXVAL);
				if (tValue->y != -1) MultiplyTraits<LONG*>::UnScaleDivideT(&tValue->y, DPISCALEYVAL);
				return *tValue;
			}
		};

		//---------------------------------------------------
		// Function Des: DpiScale x,y,obj方法
		//---------------------------------------------------
		template<class T, class DPITraits = MultiplyTraits< T > >
		inline typename TupleTraits<T>::ValueType DpiScaleX(typename TupleTraits<T>::ParamType tValue)
		{
			return DPITraits::ScaleMultiplyT(tValue, m_fScaleX);
		}

		template<class T, class DPITraits = MultiplyTraits< T > >
		inline typename TupleTraits<T>::ValueType DpiScaleY(typename TupleTraits<T>::ParamType tValue)
		{
			return DPITraits::ScaleMultiplyT(tValue, m_fScaleY);
		}

		template<class T, class DPITraits = MultiplyTraits< T > >
		inline typename TupleTraits<T>::ValueType DpiScaleObj(typename TupleTraits<T>::ParamType tValue)
		{
			return DPITraits::ScaleMultiplyObj(tValue);
		}

		//---------------------------------------------------
		// Function Des: DpiUnScale x,y,obj方法
		//---------------------------------------------------
		template<class T, class DPITraits = MultiplyTraits< T > >
		inline typename TupleTraits<T>::ValueType DpiUnScaleX(typename TupleTraits<T>::ParamType tValue)
		{
			return DPITraits::UnScaleDivideT(tValue, m_fScaleX);
		}

		template<class T, class DPITraits = MultiplyTraits< T >>
		inline typename TupleTraits<T>::ValueType DpiUnScaleY(typename TupleTraits<T>::ParamType tValue)
		{
			return DPITraits::UnScaleDivideT(tValue, m_fScaleY);
		}

		template<class T, class DPITraits = MultiplyTraits< T >>
		inline typename TupleTraits<T>::ValueType DpiUnScaleObj(typename TupleTraits<T>::ParamType tValue)
		{
			return DPITraits::UnScaleDevideObj(tValue);
		}
		///---------------------------------------------------------------------------------------- end

		// Determine the screen dimensions in relative pixels.
		int ScaledScreenWidth();
		int ScaledScreenHeight();

		// Detemine if needed dpi scale, based 96 dpi.
		bool IsNeededScale();

	private:

		// This function initializes the CDPI Class
		void _Init();

		// This returns a 96-DPI scaled-down equivalent value for nIndex
		// For example, the value 120 at 120 DPI setting gets scaled down to 96
		// X and Y versions are provided, though to date all Windows OS releases
		// have equal X and Y scale values
		int _ScaledSystemMetricX(int nIndex);

		// This returns a 96-DPI scaled-down equivalent value for nIndex
		// For example, the value 120 at 120 DPI setting gets scaled down to 96
		// X and Y versions are provided, though to date all Windows OS releases
		// have equal X and Y scale values
		int _ScaledSystemMetricY(int nIndex);

	private:
		// Member variable indicating whether the class has been initialized
		bool m_fInitialized;

		bool m_bDPIAdaptFlag;

		// X and Y DPI values are provided, though to date all
		// Windows OS releases have equal X and Y scale values
	private:
		int m_dpiX;
		int m_dpiY;
		int m_realdpiX;
		int m_realdpiY;
		float m_fScaleX;
		float m_fScaleY;
	};
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值