最近我司程序需要处理下DpiAware的问题,所以在dpi变化时根据dpi的比例需要将按钮等贴图等比放大, 但之前用的duilib版本是基于gdi绘图的,在125% 150% 175%等比例中放大后惨不忍睹.
于是参考其它一些已经支持dpi的duilib版本将绘制函数改为了GdiPlus,但在处理按钮贴图时遇到了问题.
按钮一般是多态,所以在界面中会有source='0,0,25,24'
这种定义,然后将其画在25x24的按钮上, dpi正常时一切都很好,但在比如dpi为200%的屏幕上时, 用gdi的绘制函数取源图bitmap的 0,0,25,24
区域然后绘制到屏幕的比如: 0,0,50,48
时在按钮最右边多出了一像素的竖线,百思不得其解后查阅一通资料,最有用的在 c# - 为什么 GDI+ 会截断缩放的图像?- 堆栈溢出 (stackoverflow.com) 中.
问题原因总归就是gdiplus绘制图片时为了平滑在放大时默认逻辑下会取源图的区域的相邻像素参与绘制.
解决办法一
放大绘制时调整参数, 这里如果只加一个参数,效果也都不一样的,有时会是纯粹多一条线,有时会多一条混合颜色的线.
graphics.SetInterpolationMode(Gdiplus::InterpolationModeNearestNeighbor);
graphics.SetPixelOffsetMode(PixelOffsetModeHalf);
解决办法二
克隆一个不含相邻像素的Gdiplus::Bitmap进行放大绘制
// 裁剪后绘制
Gdiplus::Rect srcRect(0, 0, 25, 24);
Gdiplus::Bitmap* croppedBitmap = pGdiPlusBitmap->Clone(srcRect, pGdiPlusBitmap->GetPixelFormat());
graphics.DrawImage(croppedBitmap, Gdiplus::Rect{ 300, 200, 50, 48 });
delete croppedBitmap; // 注意释放内存