注册 登录
编程论坛 VFP论坛

VFP中GDI+中遇到的问题

ly504 发布于 2023-11-04 13:36, 679 次点击
在用GDI打印文字时,我想用gpGraphics中的measurestringa来测量文字的宽度和高度,但怎么样试都没有用,不知道有没有大神能给给予指导。用其他语言很容易,但VFP中好多类型没有,实在搞不定。求求了!
10 回复
#2
吹水佬2023-11-04 17:18
给个其他语言的示例代码看看

#3
sam_jiang2023-11-05 20:11
把你的代码发上来看看,哪里搞不定了?
#4
ly5042023-11-05 22:34
form.init:
DECLARE integer CreateCompatibleDC IN gdi32 integer
DECLARE integer DeleteDC IN gdi32 integer
Set ClassLib To "_gdiplus.vcx"
PUBLIC loGraphics ,lfont
loGraphics = CreateObject("gpGraphics") &&创建画布对象
lfont=CreateObject("gpfont")


form.计算文字宽:
PARAMETERS 计算文本,字体名称,字体大小,字体风格
LOCAL _图形,mdc_id,_文本矩形,_字体
mdc_id=CreateCompatibleDC(0)
IF mdc_id=0

    RETURN 0
ENDIF
PUBLIC a,c,d,rect
rect=NEWOBJECT("gprectangle")
IF loGraphics.CreateFromHDC(mdc_id)
    lfont.Create(字体名称,字体大小,字体风格,2)
    a=loGraphics.MeasureStringw(计算文本,lfont,@rect,,@c,@d)
ENDIF
?c,d


command.click:
thisform.计算文字宽("微软雅黑微软雅黑","微软雅黑",30,)


想要结果:文字相关字体和字号下出来的宽度,但出不来。
出来的是
8   1


?a
结果是
对象

[此贴子已经被作者于2023-11-6 08:57编辑过]

#5
sych2023-11-06 11:47
DECLARE INTEGER GdipCreateFontFamilyFromName IN GdiPlus.dll STRING familyname, INTEGER FontCollection, INTEGER @FontFamily
DECLARE INTEGER GdipCreateFont IN GdiPlus.dll;
        INTEGER fontFamily, SINGLE emSize,;
        INTEGER fntstyle, INTEGER unit, INTEGER @fnt
DECLARE INTEGER GdipCreateStringFormat IN GdiPlus.dll INTEGER formatAttributes, INTEGER language, INTEGER @nFormat
DECLARE LONG GdipSetStringFormatAlign IN GDIPLUS LONG StringFormat, LONG
DECLARE LONG GdipSetStringFormatLineAlign IN GDIPLUS LONG StringFormat, LONG align
DECLARE LONG GdipSetStringFormatTrimming IN GDIPLUS LONG StringFormat, LONG trimming
DECLARE LONG GdipCreatePen1 IN GDIPLUS LONG Colr, SINGLE nWidth, LONG unit, LONG @pen
DECLARE LONG GdipSetPenMode IN GDIPLUS LONG pen, LONG penMode
DECLARE LONG GdipCreatePath IN GDIPLUS LONG brushmode, LONG @path
DECLARE LONG GdipAddPathString IN GDIPLUS LONG path, STRING str, LONG length, LONG family, LONG style, SINGLE emSize, STRING @layoutRect, LONG StringFormat
DECLARE LONG GdipGetPathWorldBounds IN GDIPLUS LONG path, STRING @bounds, LONG matrix, LONG pen
DECLARE LONG GdipDrawPath IN GDIPLUS LONG graphics, LONG pen, LONG path
DECLARE LONG GdipDrawRectangles IN GDIPLUS LONG graphics, LONG pen, STRING @rects, LONG Count
DECLARE LONG GdipCreateFromHDC IN GDIPLUS LONG hdc, LONG @graphics
DECLARE INTEGER GetDC IN win32api INTEGER hwnd
lctext="我要测量长和宽"
lcFontName="宋体"
lnsize=127
lnsize0=lnsize*96/72
lnFontFamily=0
GdipCreateFontFamilyFromName(STRCONV(lcFontName+CHR(0),5),0,@lnFontFamily)
lnFont=0
lnfontstyle=0
GdipCreateFont(lnFontFamily,lnSize0,lnFontStyle, 2 ,@lnFont)
lnFormatHandle = 0
=GdipCreateStringFormat(0x1004, 0, @lnFormatHandle )
=GdipSetStringFormatAlign(lnFormatHandle,0)
=GdipSetStringFormatLineAlign(lnFormatHandle, 0)
=GdipSetStringFormatTrimming(lnFormatHandle,0)
lnpen=0
lnColor = RGB(0,0,0)
=GdipCreatePen1(CTOBIN(CHR(255)+LEFT(BINTOC(lnColor,'4RS'),3),'4S'), 0, 2, @lnpen)
=GdipSetPenMode(lnpen,1)
lctxtrect= replicate(chr(0), 16)
lctxtrect= BINTOC(20,"f")+BINTOC(200,"f")+replicate(chr(0), 8)
lnpath=0
GdipCreatePath(0,@lnpath)
GdipAddPathString( lnpath, strconv(lctext+chr(0), 5),-1, lnFontFamily, lnFontStyle, lnSize0, @lctxtRect, lnFormatHandle)
GdipGetPathWorldBounds(lnpath,@lctxtrect,0,lnpen)
Graphics=0
hDC=GetDC(_screen.HWnd)
GdipCreateFromHDC(hdc, @Graphics)
GdipDrawPath(Graphics,lnpen,lnpath)
GdipDrawRectangles(Graphics,lnpen, @lctxtrect,1)
=INKEY(0)
?"x=",CTOBIN(SUBSTR(lctxtrect,1,4),"n"),CTOBIN(SUBSTR(lctxtrect,1,4),"n")/96*254
?"y=",CTOBIN(SUBSTR(lctxtrect,5,4),"n"),CTOBIN(SUBSTR(lctxtrect,5,4),"n")/96*254
?"w=",CTOBIN(SUBSTR(lctxtrect,9,4),"n"),CTOBIN(SUBSTR(lctxtrect,9,4),"n")/96*254
?"h=",CTOBIN(SUBSTR(lctxtrect,13,4),"n"),CTOBIN(SUBSTR(lctxtrect,13,4),"n")/96*254



[此贴子已经被作者于2023-11-7 12:26编辑过]

#6
ly5042023-11-06 12:36
回复 5楼 sych
sych哥,你好,辛苦了。
你这用纯代码方式解决,也是一条思路。
但有一个问题你这个只取了有文字像素存在的区域,但文字中间都是有留白空间的,所以会导致出现一个状况,字符串两头的留白空间没有取到,但中间的却取到了
比如一个字和多个字,宽度不是倍数关系,再比如竖“丨”这个中文字,他只取了有像素的区域,所以没有达到我想要的那个效果
我试了一下,比如
同样是“宋体”和“127号”字的情况,
“丨”,w=12
“丿”,w=36
“我”,w=116
“我要”,w=245
“我要测”,w=372
小数点后的位数没写
是否有解决方法呢?
#7
iswith2023-11-06 13:58
a=loGraphics.MeasureStringw(计算文本,lfont,@rect,,@c,@d) ,你转unicode字符后传入,整个2000以后都这个玩意儿做内核字符处理
#8
schtg2023-11-06 19:28
回复 5楼 sych
学习啦,谢谢!
#9
ly5042023-11-06 22:05
谢谢大家,我现在对_gdiplus.vcx类中的gpgraphics进行了重定义后,已经可以返回正确值了,谢谢你们,有你们真好。
#10
sych2023-11-07 10:10
不过5楼的不知道哪里出问题了,计算结果和测量出来的有出入

#11
sych2023-11-11 10:08
TEXTMETRIC是在WINGDI.H中定义的型态的结构。TEXTMETRIC结构有20个栏位:
  typedef struct tagTEXTMETRIC { // tm
  LONG tmHeight; //字符高度
  LONG tmAscent; //字符上部高度(基线以上)
  LONG tmDescent; //字符下部高度(基线以下)
  LONG tmInternalLeading, //由tmHeight定义的字符高度的顶部空间数目
  LONG tmExternalLeading, //加在两行之间的空间数目
  LONG tmAveCharWidth, //平均字符宽度
  LONG tmMaxCharWidth, //最宽字符的宽度
  LONG tmWeight; //字体的粗细轻重程度
  LONG tmOverhang, //加入某些拼接字体上的附加高度
  LONG tmDigitizedAspectX, //字体设计所针对的设备水平方向
  LONG tmDigitizedAspectY, //字体设计所针对的设备垂直方向
  BCHAR tmFirstChar; //为字体定义的第一个字符
  BCHAR tmLastChar; //为字体定义的最后一个字符
  BCHAR tmDefaultChar; //字体中所没有字符的替代字符
  BCHAR tmBreakChar; //用于拆字的字符
  BYTE tmItalic, //字体为斜体时非零
  BYTE tmUnderlined, //字体为下划线时非零
  BYTE tmStruckOut, //字体被删去时非零
  BYTE tmPitchAndFamily, //字体间距(低4位)和族(高4位)
  BYTE tmCharSet; //字体的字符集
  } TEXTMETRIC;
Declare Long GetDC In user32.dll Long
Declare Integer GetTextMetrics In gdi32.dll Long, String @

tm = Replicate(Chr(0),57)
GetTextMetrics(GetDC(_vfp.hWnd),@tm)

*!*    系统字体平均宽度
lnAvgCharWidth = Ctobin(Substr(tm,21,4),'4rs')
?lnAvgCharWidth

*!*    系统字体高度
lnCharHeight = Ctobin(Substr(tm,1,4),'4rs') + Ctobin(Substr(tm,17,4),'4rs')
?lnCharHeight


[此贴子已经被作者于2023-11-11 10:16编辑过]

1