我正在努力尝试在Windows上使用可识别dpi的emf文件。主要问题来自它们不能以dpi感知方式处理文本的事实。例如,无论屏幕分辨率是多少,或者内部是电动势,从电动势获得的图形对象始终报告96 dpi。这样就无法正确处理文本。
在我的情况下,给我一个以英寸为单位的图像尺寸,我需要使我的绘图适合该尺寸。该图是带有图例,标题和轴名称的X-Y图。我使用MeasureString的结果为布局设置填充变量。 emf不能为其图形对象返回正确的dpi的事实会导致文本随着缩放/分辨率从96移到更远并且布局也发生变化而变得越来越差,因为填充不一样。
代码如下:
首先计算显示设置比例因子
// Calculate the scale setting
// Note: Changing the Display Settings scale changes the screen pixel resolution (HORZRES).
// The desktop res is the physical numbers of pixels, and the logical pixel is set at boot up and never changes.
System.Drawing.Graphics pGFX = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
IntPtr hemfDC = pGFX.GetHdc();
int dtX = GetDeviceCaps(hemfDC, DeviceCap.DESKTOPHORZRES);
int dtY = GetDeviceCaps(hemfDC, DeviceCap.DESKTOPVERTRES);
int scX = GetDeviceCaps(hemfDC, DeviceCap.HORZRES);
int scY = GetDeviceCaps(hemfDC, DeviceCap.VERTRES);
int lpX = GetDeviceCaps(hemfDC, DeviceCap.LOGPIXELSX);
int lpY = GetDeviceCaps(hemfDC, DeviceCap.LOGPIXELSY);
pGFX.ReleaseHdc();
int dpiX = (int)(((float)dtX / (float)scX) * lpX);
int dpiY = (int)(((float)dtY / (float)scY) * lpY);
float scaleX = ((((float)dtX / (float)scX) * lpX) / pGFX.DpiX);
float scaleY = ((((float)dtY / (float)scY) * lpY) / pGFX.DpiY);
下一步创建图元文件
Metafile image = null;
MetafileHeader mfh = null;
SizeF emfSize = new SizeF(pageSize);
using (MemoryStream stream = new MemoryStream())
{
IntPtr hDC = gfx.GetHdc();
try
{
image = new Metafile(
stream,
hDC,
new RectangleF(new PointF(0, 0), emfSize),
MetafileFrameUnit.Inch,
EmfType.EmfPlusOnly);
}
finally
{
gfx.ReleaseHdc();
}
}
最后,调用图形代码。绘图代码的大小以像素为单位,而不是英寸。请注意,文件的大小(以像素为单位)是用户定义的比例因子的大小,其中100%假定为g.Dpi(即96)。事实证明,这种假设对我测试过的所有显示器都是正确的。
if (image != null)
{
using (Graphics g = Graphics.FromImage(image))
{
mfh = image.GetMetafileHeader();
emfSize.Width *= g.DpiX * scaleX;
emfSize.Height *= g.DpiY * scaleY;
g.PageUnit = GraphicsUnit.Pixel;
g.ScaleTransform(mfh.DpiX / g.DpiX, mfh.DpiY / g.DpiY);
DrawGraph(g, ref emfSize);
}
}
答案 0 :(得分:0)
我包装了Graphic DrawString和MeasureString,以便使用计算出的Display设置的比例临时缩放字体。这不是理想的,但我能找到的最佳折衷方案。
private void DrawString(Graphics g, string s, Font font, Brush brush, PointF point)
{
Font f = new Font(font.FontFamily, font.SizeInPoints * Graph.FontScale, font.Style, GraphicsUnit.Point);
g.DrawString(s, f, brush, point);
}