VC在Windows下让指定程序兼容高分屏(HDPI)模式(转)

80 篇文章 2 订阅

有这样的可能:

某用户的显示器是4K显示器而我们开发的APP的尺寸最大也就1080,那么这时候用户打开这应用就会很小。

这种情况下用户一般是会开启系统的高清分屏的:

一般都会选择缩放125%以上:

这时候我们的程序如果不默认支持高清分屏那么就还是以前(未缩放)之后的大小。

本例就是提供一个操作让指定的exe支持高清分屏模式。

指定某exe支持或停止支持高清分屏:

//* absAppPath : exe的绝对路径
//* enabled    : 是否支持
//* return     : 是否操作成功
bool RegEnable_DPIUNAWARE( const std::wstring absAppPath, bool enabled )
{
 
	//Win8以上 支持
#if 0
	CWinOSVersion os;
	if (!os.IsWin8x())
	{
		return false;
	}
#endif
 
	if(absAppPath.empty())
	{
		//empty path
		return false;
	}
 
	if(!::PathFileExistsW(absAppPath.c_str()))
	{
		//not exists
		return false;
	}
	
	std::wstring appExtension = ::PathFindExtensionW(absAppPath.c_str());
	if(appExtension.empty())
	{	
		//no extension
		return false;
	}
 
	std::wstring appExtension_lower = ::CharLowerW(&appExtension[0]);
	if(appExtension_lower.compare(L".exe") != 0)
	{
		//not exe
		return false;
	}
 
	//open reg key
	HKEY hKey=NULL;
	DWORD dwKeyType = 0;
	REGSAM regSam = KEY_ALL_ACCESS;
 
 
	std::wstring subKey_Layers = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers";
	LSTATUS sRtn = RegOpenKeyExW(HKEY_CURRENT_USER, subKey_Layers.c_str(), NULL, regSam, &hKey);
 
	if( ERROR_SUCCESS != sRtn )//nokey , create..
	{
		if(!enabled)
		{
			return true;
		}
 
		sRtn = RegCreateKeyExW(HKEY_CURRENT_USER, subKey_Layers.c_str(), NULL, L"", REG_OPTION_NON_VOLATILE, regSam, NULL, &hKey, &dwKeyType);
 
		if( ERROR_SUCCESS != sRtn )// create failed
		{
			return false;
		}
	}
 
	std::wstring wszValue = L"~ DPIUNAWARE";
 
	if(enabled) //set value
	{
		sRtn = RegSetValueExW(hKey, absAppPath.c_str(), NULL, REG_SZ, (LPBYTE)wszValue.c_str(), (wszValue.length()+1) * sizeof(wchar_t));
		if( ERROR_SUCCESS != sRtn )//set failed
		{
			return false;
		}
	}
	else//delete value
	{
		sRtn = RegDeleteValueW(hKey, absAppPath.c_str());
		return true;
	}
 
	return true;
}


 

查询某exe是否已经兼容高清分屏

//* absAppPath : exe的绝对路径
//* return     : 是否已经启用
bool RegQuery_DPIUNAWARE_Enabled( const std::wstring absAppPath )
{
	//Win8以上 支持
#if 0
	CWinOSVersion os;
	if (!os.IsWin8x())
	{
		return false;
	}
#endif
 
	if(absAppPath.empty())
	{
		//empty path
		return false;
	}
 
	if(!::PathFileExistsW(absAppPath.c_str()))
	{
		//not exists
		return false;
	}
 
	std::wstring appExtension = ::PathFindExtensionW(absAppPath.c_str());
	if(appExtension.empty())
	{	
		//no extension
		return false;
	}
 
	std::wstring appExtension_lower = ::CharLowerW(&appExtension[0]);
	if(appExtension_lower.compare(L".exe") != 0)
	{
		//not exe
		return false;
	}
 
	//open reg key
	HKEY hKey=NULL;
	DWORD dwKeyType = 0;
	REGSAM regSam = KEY_ALL_ACCESS;
 
 
	std::wstring subKey_Layers = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers";
 
	std::wstring wszValue = L"~ DPIUNAWARE";
 
	wchar_t wszGetValue[MAX_PATH]={0};
	DWORD type = RRF_RT_REG_SZ;
	DWORD vSize =  MAX_PATH*sizeof(wchar_t);
	LSTATUS sRtn = ::RegGetValueW(HKEY_CURRENT_USER, subKey_Layers.c_str(), absAppPath.c_str(), type, 0, (LPBYTE)wszGetValue, &vSize);
	if(ERROR_SUCCESS != sRtn) //get value error
	{
		return false;
	}
 
	int n = StrCmpW(wszValue.c_str(),wszGetValue);
	return n == 0;
 
	return true;
}

使用方法:

wchar_t appPath[MAX_PATH] = {0};
::GetModuleFileNameW(0,appPath, MAX_PATH);
 
bool res = RegEnable_DPIUNAWARE(appPath, true);
 
res = RegQuery_DPIUNAWARE_Enabled(appPath);


运行之后再次打开我们的程序就会根据系统设置的缩放比例进行缩放了。

 

 

原理:

修改在注册表启用配置以支持系统的高清分屏模式

 


————————————————
版权声明:本文为CSDN博主「Eosin_Sky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/r5014/article/details/112368460

ps:微软用的是DPIUNAWARE,不知道这个文章为啥用的是~ DPIUNAWARE

参考:Windows10显示缩放导致Visual Studio 2017 WinForm窗体设计器在高DPI下设计时界面/布局/大小问题_夏侯依风的博客-CSDN博客

官方文档请参阅:https://docs.microsoft.com/en-us/visualstudio/designers/disable-dpi-awareness?view=vs-2019#add-a-registry-entr

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值