VC获取屏幕dpi,win32绘图适配高dpi模式,windows屏幕缩放图像拉伸失真问题

6 篇文章 0 订阅

默认MFC支持高dpi模式

mfc程序和控件都是支持高dpi的自适应的,不需要特殊处理,本篇幅可以用在winapi绘制图形高dpi糊掉。

通过winapi提供接口获取屏幕dpi

win8以上通过函数GetDpiForWindow获取
例:

int iDpi = GetDpiForWindow(m_hWnd);

通用推荐使用函数GetDeviceCaps获取
例:

int iDpi = GetDeviceCaps(pDC->m_hDC, LOGPIXELSX);

使用StretchBlt代替BitBlt进行图像绘制

注意MulDiv函数

MulDiv函数执行示例
int resWidth = MulDiv(rect.Width(), 96, iDpi);
使用MuDiv 就相当于
int resWidth = rect.Width() * 96 / iDpi;
其中iDpi就是上面获取到的dpi值,96为设备绘制为100%大小时dpi。
通过这个函数算出实际需要绘制的图形大小。

推测

根据推测高dpi模式图像会糊掉应该是windows在图形绘制到dc之后又进行了一次放大。
所以想要不被糊掉一个途径就是在绘制时进行缩放,在实际的高dpi生效时就会把图像放大,具实际操作发现此时缩放绘制的图像在高dpi模式下并不会失真,估计是系统底层又进行了一次操作。

StrechBlt替换

此过程在OnDraw函数中,&dcMem是原生成内存dc,已在上绘制完,接下来就往窗口dc上进行绘制
原来的绘制流程是直接使用BitBlt进行,此过程中rect是通过 GetClientRect 获取到的窗口区域。
dcMem是对整个窗口区域绘制的内存dc,大小是正常的96dpi的大小。

CRect rect;
GetClientRect(rect);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &dcMem, 0, 0, SRCCOPY);

现在需要把绘制流程改为StretchBlt,将dcMem中的数据缩小绘制到窗口dc中,再由系统高dpi进行放大

int iDpi = GetDeviceCaps(pDC->m_hDC, LOGPIXELSX);
pDC->StretchBlt(0, 0, MulDiv(rect.Width(), 96, iDpi), MulDiv(rect.Height(), 96, iDpi), &dcMem, 0, 0, rect.Width(), rect.Height(), SRCCOPY);

高dpi模式设置

高dpi VS项目设置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

frankz61

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值