| 网站首页 | 业界新闻 | 小组 | 交易 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
买学问 - 大牛一对一辅导,有问必答买学问 - 专业的付费知识问答平台
共有 2511 人关注过本帖, 1 人收藏
标题:利用API函数LineTo绘图的问题
只看楼主 加入收藏
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
  得分:0 
已找到原因!
是因为坐标系的缘故,在这之前一直被那个0.01毫米的精度纠结。实际上在没有设定hdc度量单位的话,默认的作图单位是像素,由于我数组里面记录的是按单位缇记录的坐标数据,我按照0.01毫米的精度转换大致是1缇=1.78(0.01毫米),所以我都乘以2了,这样定位的坐标超出屏幕外了,所以看不到。实际上还是要将缇转换为像素,即除以15才可以得到正确结果(注:PlayEnhMetaFile 设定的屏幕大小还是要按照0.01毫米精度转换),修改后的saveemf函数如下:
程序代码:
Private Sub saveemf()
  '存储图元文件
  Dim hemf As Long, hpen As Long, ret As Long, lp As RECT, c As Integer, i As Integer
  c = 0
  For i = 0 To 100
    If dxy(i, 0) = 0 And dxy(i, 1) = 0 Then Exit For
    c = c + 1
  Next
  If c < 2 Or Trim(Text1) = "" Then
    MsgBox "线段太少或文件名为空,存图失败"
    Exit Sub  '少于一条线段的坐标或文件名为空则不存图
  End If
  lp.Right = Pic1.ScaleWidth * 2
  lp.Bottom = Pic1.ScaleHeight * 2     '创建图元屏幕大小仍然按照0.01毫米的单位转换乘以
  lp.Top = 0
  lp.Left = 0
  hemf = CreateEnhMetaFile(Pic1.hdc, Text1 & ".emf", lp, vbNullString)
  If hemf = 0 Then
    MsgBox "图元文件创建失败"
    Exit Sub
  End If
  hpen = CreatePen(0, 1, vbRed)
  ret = SelectObject(hemf, hpen)
  ret = MoveToEx(hemf, dxy(0, 0) / 15, dxy(0, 1) / 15, 0&)   '作图的坐标按像素转换除以15
  For i = 1 To 100
    If dxy(i, 0) = 0 And dxy(i, 1) = 0 Then Exit For
    ret = LineTo(hemf, dxy(i, 0) / 15, dxy(i, 1) / 15)
  Next
  ret = CloseEnhMetaFile(hemf)
  ret = DeleteEnhMetaFile(ret)
End Sub

效果图:
附件: 您没有浏览附件的权限,请 登录注册
2017-09-26 15:58
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:248
帖 子:4394
专家分:26986
注 册:2008-10-15
  得分:0 
xzlxzlxzl 就是厉害。

授人于鱼,不如授人于渔
早已停用QQ了
2017-09-26 16:26
Artless
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:4211
专家分:28888
注 册:2009-4-8
  得分:0 
都是高手

无知
2017-09-27 00:32
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
  得分:0 
哈哈,我看到了不是初中就是高中的信息技术教材有Form1的东东~不过久久都忘记很多了/wn~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-09-27 00:39
xiangyue0510
Rank: 14Rank: 14Rank: 14Rank: 14
等 级:贵宾
威 望:86
帖 子:909
专家分:5237
注 册:2015-8-10
  得分:0 
回复 11楼 xzlxzlxzl

以前还真没有注意过单位制的问题,不过精度上似乎还有一些问题。附件上可以看出有一部分区域丢失

请帮看一下我的理解是否正确?
Pic1 (单位:Twip,缇):
                         ↓
Rect (单位:0.01 mm) =Twip *2
我查到的是 1cm= 567 Twips。 xzlxzlxzl你这个是粗略的换算,准确的应该是1/567*1000=1.763688,对吧? 这样应该“画布”更大才对
                         ↓
图片、设备场景hdc、LineTo函数(单位:pixel 像素)
   = Twip /15

ScaleWidth =6315、 Scaleheight=3555 , 那么计算得到像素应该是421×237,但是得到的图片是359×203。 我也算了一下X、Y方面误差还不太一样,分别是1.1727、1.167488。考虑到前面用的是Twip *2定义的rect,似乎这个误差还要大一些
这么看似乎保存emf的时候,还有一个折减。 xzlxzlxzl这方面你了解是怎么回事么? 毕竟我的图片是全部代码生成,如果保存的时候丢失部分不好。 就是故意避开这个范围也得清楚比例多大
附件: 您没有浏览附件的权限,请 登录注册
2017-09-27 11:55
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
  得分:0 
经测试,不同的屏幕分辨率,1 twip对应的0.01毫米比例不确定,按照计算比例是1.763688,在屏幕1440*900的分辨率下比例是1.842,在屏幕分辨率是1680*1050时,比例是1.88。你可以根据你的电脑计算的像素/实际像素来计算比例,比如你计算的应该是421*237,由于我的twip单位都乘以2了,所以实际像素是842*474,产生的图元文件尺寸是359*203,你电脑的横坐标比例实际为842/359=2.3454,纵坐标实际比例为474/203=2.335,所以你应该将下述代码比例进行修改如下:
  lp.Right = Pic1.ScaleWidth * 2
  lp.Bottom = Pic1.ScaleHeight * 2     '创建图元屏幕大小仍然按照0.01毫米的单位转换乘以

修改为
  lp.Right = Pic1.ScaleWidth * 2.3454
  lp.Bottom = Pic1.ScaleHeight * 2.335     '创建图元屏幕大小仍然按照0.01毫米的单位转换乘以

可以使用自动比例测算,方法是先用CreateEnhMetaFile(Pic1.hdc, vbNullString, lp, vbNullString)产生一个内存图元句柄,在使用GetEnhMetaFileHeader获取该句柄对应图元实际尺寸,用理论尺寸/实际尺寸即可自动得到调整比例。
2017-09-27 19:35
xiangyue0510
Rank: 14Rank: 14Rank: 14Rank: 14
等 级:贵宾
威 望:86
帖 子:909
专家分:5237
注 册:2015-8-10
  得分:0 
回复 16楼 xzlxzlxzl
哦,原来是这样的,我再研究研究。谢了!
2017-09-28 01:12
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
  得分:0 
两天前我还不知道emf文件,通过对题主问题的解答和共同讨论,自觉已经掌握了“vb制作和访问图元文件”方法,现做个总结:
1,我掌握这个的基础知识全部来自百度,而大部分方法是通过由此及彼的领悟和程序调试中获得的。比如2楼代码的确如风版主所说是百度的,可是百度里的代码都没有ENHMETAHEADER结构,没有足够经验的人是找不到这个结构的。我后来提供的代码就完全是自己的了。
2,windows图元文件有普通图元文件和增强图元文件,两种类型的文件需要用两套api访问,不能通用,如创建增强的api函数是CreateEnhMetaFile、显示用PlayEnhMetaFile,创建普通的是CreateMetaFile、显示用PlayMetaFile。目前看来,普通图元的矢量坐标是相对的、16位的,而增强的矢量坐标是绝对的、32位的,增强的图放大缩小和显示位置只需要调整RECT里的值即可达到,而普通的随意显示比较麻烦,我现在的代码只能从坐标0,0开始显示。
3,图元文件的RECT单位是0.01毫米,而api作图的默认单位是像素。
4,由于图元文件的设备无关性,不同显示分辨率下制作图元文件时就涉及到标准的自动转换,反应到图元文件上时就是查看图元文件属性的DPI不同。这也很容易理解,比如我19吋的屏幕,分辨率在1024*768和1440*900时,每个像素实际宽度肯定都不同。这和书上或百度上说的一个像素固定月0.33毫米或一公分567twips不同,那是按分辨率96DPI计算出来的,因为windows显示设备的DPI固定为96。这样以来代码里需要自动计算不同分辨率下图元文件的DPI,以实现图元文件的设备无关性,我现在的代码里已实现自动计算,拿到任何显示分辨率下制作图元文件都会所见即所得,不会再出现题主15楼所说的问题。这是通过ENHMETAHEADER结构里szlDevice、szlMillimeters成员变量计算得到的,如下图:



5,矢量图的优点就是平滑放大缩小,放个比较图片体会下,可感受到矢量图的优点。


附件: 您没有浏览附件的权限,请 登录注册
2017-09-29 04:43







关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.032485 second(s), 9 queries.
Copyright©2004-2019, BCCN.NET, All Rights Reserved