Artisan Posted May 10, 2013 Posted May 10, 2013 (edited) Hi all. I need a little help with GDI+.I am attempting to display a block of pre-wrapped text using GDI+. (Ultimately I want to be able to print it, so I'm using GDI+ with GRS' UDF. But that doesn't come into play here.) I want to be able to calculate the height and width automatically based on the font and text used. I made a "small" application that asks a user for a font/style and displays a block of typical Latin "lorem ipsum" text. I'm using Melba32's and as far as I can tell it works perfectly. The size it comes up with should be large enough to hold the text. GDI+ disagrees with me, and wraps the text occasionally, causing some lines to have only 1 word and pushing lower lines out of view. Below is my code. Can anyone help me figure out what's causing this? The only current workaround I've found is to pad the width returned by _StringSize by 30 pixels, and I'd really rather not rely on something like that. I suspect there's some kind of a "frame" issue going on, like margin/padding issues in CSS, but I just can't nail it down. Thanks in advance!EDIT - How do I preserve the tabs in my code when pasting here?expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <Misc.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> #include "StringSize.au3" ; GDI Fonts ; Get a font, show some text. ; Credit: Melba ; For: StringSize UDF ; http://www.autoitscript.com/forum/topic/114034-stringsize-m23-new-version-16-aug-11/ ; Credit: ReFran and UEZ ; For: GDI Repainting ; Source: http://www.autoitscript.com/forum/topic/135199-table-wit-gdiborder-lines-dont-redraw/ ; Credit: loremipsum.net ; For: Lorem Ipsum text ; Source: http://www.loremipsum.net/ AutoItSetOption("MustDeclareVars", 1) Global Const $_ATTRIB = 1, $_NAME = 2, $_SIZE = 3, $_WEIGHT = 4, $_COLOR = 7 ; $aFont indices Global Const $_TEXT = 0, $_WIDTH = 2, $_HEIGHT = 3 ; $aStringSize indices Global $aFont, $aStringSize, $hGUI, $hGraphic, $hBrush, $hFormat, $hFamily, $hFont, $tLayout, $aInfo, $sText Main() Func Main() ; Sample Text $sText = _ " 1 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt" & @CRLF & _ " 2 - ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci" & @CRLF & _ " 3 - tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum" & @CRLF & _ " 4 - iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat" & @CRLF & _ " 5 - nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum" & @CRLF & _ " 6 - zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis" & @CRLF & _ " 7 - eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non" & @CRLF & _ " 8 - habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes" & @CRLF & _ " 9 - demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus" & @CRLF & _ "10 - dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica," & @CRLF & _ "11 - quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta " & @CRLF & _ "12 - decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes" & @CRLF & _ "13 - in futurum. ##" ; Get font data $aFont = _ChooseFont() If Not IsArray($aFont) Then Return -1 $aFont[$_ATTRIB] = Number($aFont[$_ATTRIB]) ; _ChooseFont() returns an array of strings which must be converted for use $aFont[$_SIZE] = Number($aFont[$_SIZE]) $aFont[$_WEIGHT] = Number($aFont[$_WEIGHT]) $aStringSize = _StringSize($sText, $aFont[$_SIZE], $aFont[$_WEIGHT], $aFont[$_ATTRIB], $aFont[$_NAME]) If Not IsArray($aStringSize) Then Return -1 ; Build GUI $hGUI = GUICreate("GDI+ Font Test (13 Lines)", $aStringSize[$_WIDTH] + 20, $aStringSize[$_HEIGHT] + 50) GUICtrlCreateLabel("Font: " & $aFont[$_NAME] & ", Size: " & $aFont[$_SIZE] & ", Attribute: " & $aFont[$_ATTRIB] & ", Weight: " & $aFont[$_WEIGHT] & ", Color: " & $aFont[$_COLOR], 10, 10, $aStringSize[$_WIDTH], 20) _GDIPlus_Startup () $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) $hBrush = _GDIPlus_BrushCreateSolid("0xFF" & StringMid($aFont[$_COLOR], 3)) $hFormat = _GDIPlus_StringFormatCreate() $hFamily = _GDIPlus_FontFamilyCreate($aFont[$_NAME]) $hFont = _GDIPlus_FontCreate($hFamily, $aFont[$_SIZE], $aFont[$_ATTRIB]) $tLayout = _GDIPlus_RectFCreate(10, 30, $aStringSize[$_WIDTH], $aStringSize[$_HEIGHT]) $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $aStringSize[$_TEXT], $hFont, $tLayout, $hFormat) GUIRegisterMsg($WM_PAINT, "_WMPAINT") GUISetState(@SW_SHOW, $hGUI) ; Message Loop Do Until GUIGetMsg() == $GUI_EVENT_CLOSE ; Clean up _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() EndFunc Func _WMPAINT() ; Repaints the GDI+ stuff (border & text) ; I only tested this on Win7 (x32 and x64), but it *should* be compatible with other Windows versions _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_UPDATENOW) _GDIPlus_GraphicsDrawStringEx($hGraphic, $aStringSize[$_TEXT], $hFont, $aInfo[0], $hFormat, $hBrush) _GDIPlus_GraphicsDrawRect($hGraphic, 10, 30, $aStringSize[$_WIDTH], $aStringSize[$_HEIGHT]) _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_VALIDATE) EndFunc Edited May 10, 2013 by Artisan
Solution UEZ Posted May 10, 2013 Solution Posted May 10, 2013 (edited) Try this: expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <Misc.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> ;~ #include "StringSize.au3" ; GDI Fonts ; Get a font, show some text. ; Credit: Melba ; For: StringSize UDF ; http://www.autoitscript.com/forum/topic/114034-stringsize-m23-new-version-16-aug-11/ ; Credit: ReFran and UEZ ; For: GDI Repainting ; Source: http://www.autoitscript.com/forum/topic/135199-table-wit-gdiborder-lines-dont-redraw/ ; Credit: loremipsum.net ; For: Lorem Ipsum text ; Source: http://www.loremipsum.net/ AutoItSetOption("MustDeclareVars", 1) Global Const $_ATTRIB = 1, $_NAME = 2, $_SIZE = 3, $_WEIGHT = 4, $_COLOR = 7 ; $aFont indices Global Const $_TEXT = 0, $_WIDTH = 2, $_HEIGHT = 3 ; $aStringSize indices Global $aFont, $aStringSize, $hGUI, $hGraphic, $hBrush, $hFormat, $hFamily, $hFont, $tLayout, $aInfo, $sText Main() Func Main() ; Sample Text $sText = _ " 1 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt" & @CRLF & _ " 2 - ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci" & @CRLF & _ " 3 - tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum" & @CRLF & _ " 4 - iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat" & @CRLF & _ " 5 - nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum" & @CRLF & _ " 6 - zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis" & @CRLF & _ " 7 - eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non" & @CRLF & _ " 8 - habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes" & @CRLF & _ " 9 - demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus" & @CRLF & _ "10 - dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica," & @CRLF & _ "11 - quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta " & @CRLF & _ "12 - decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes" & @CRLF & _ "13 - in futurum. ##" ; Get font data $aFont = _ChooseFont() If Not IsArray($aFont) Then Return -1 _GDIPlus_Startup() $aFont[$_ATTRIB] = Number($aFont[$_ATTRIB]) ; _ChooseFont() returns an array of strings which must be converted for use $aFont[$_SIZE] = Number($aFont[$_SIZE]) $aFont[$_WEIGHT] = Number($aFont[$_WEIGHT]) ;~ $aStringSize = _StringSize($sText, $aFont[$_SIZE], $aFont[$_WEIGHT], $aFont[$_ATTRIB], $aFont[$_NAME]) $aStringSize = _GDIPlus_MeasureString($sText, $aFont[$_NAME], $aFont[$_SIZE], $aFont[$_ATTRIB]) ;~ _GDIPlus_MeasureString($sString, $sFont = "Arial", $fSize = 12, $iStyle = 0) If Not IsArray($aStringSize) Then Return -1 ; Build GUI $hGUI = GUICreate("GDI+ Font Test (13 Lines)", $aStringSize[0] + 20, $aStringSize[1] + 50) GUICtrlCreateLabel("Font: " & $aFont[$_NAME] & ", Size: " & $aFont[$_SIZE] & ", Attribute: " & $aFont[$_ATTRIB] & ", Weight: " & $aFont[$_WEIGHT] & ", Color: " & $aFont[$_COLOR], 10, 10, $aStringSize[0], 20) $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) $hBrush = _GDIPlus_BrushCreateSolid("0xFF" & StringMid($aFont[$_COLOR], 3)) $hFormat = _GDIPlus_StringFormatCreate() $hFamily = _GDIPlus_FontFamilyCreate($aFont[$_NAME]) $hFont = _GDIPlus_FontCreate($hFamily, $aFont[$_SIZE], $aFont[$_ATTRIB]) $tLayout = _GDIPlus_RectFCreate(10, 30, $aStringSize[0], $aStringSize[1]) ;~ $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sText, $hFont, $tLayout, $hFormat) GUIRegisterMsg($WM_PAINT, "_WMPAINT") GUISetState(@SW_SHOW, $hGUI) ; Message Loop Do Until GUIGetMsg() == $GUI_EVENT_CLOSE ; Clean up _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() EndFunc ;==>Main Func _WMPAINT() ; Repaints the GDI+ stuff (border & text) ; I only tested this on Win7 (x32 and x64), but it *should* be compatible with other Windows versions _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_UPDATENOW) _GDIPlus_GraphicsDrawStringEx($hGraphic, $sText, $hFont, $tLayout, $hFormat, $hBrush) _GDIPlus_GraphicsDrawRect($hGraphic, 10, 30, $aStringSize[0], $aStringSize[1]) _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_VALIDATE) EndFunc ;==>_WMPAINT Func _GDIPlus_MeasureString($sString, $sFont = "Arial", $fSize = 12, $iStyle = 0, $bRound = True) Local $aSize[2] Local Const $hFamily = _GDIPlus_FontFamilyCreate($sFont) If Not $hFamily Then Return SetError(1, 0, $aSize) Local Const $hFormat = _GDIPlus_StringFormatCreate() Local Const $hFont = _GDIPlus_FontCreate($hFamily, $fSize, $iStyle) Local Const $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0) Local Const $hGraphic = _GDIPlus_GraphicsCreateFromHWND(0) Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sString, $hFont, $tLayout, $hFormat) $aSize[0] = $bRound ? Round($aInfo[0].Width, 0) : $aInfo[0].Width $aSize[1] = $bRound ? Round($aInfo[0].Height, 0) : $aInfo[0].Height _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_GraphicsDispose($hGraphic) Return $aSize EndFunc ;==>_GDIPlus_MeasureStringBr,UEZ Edited October 30, 2014 by UEZ Artisan 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
Artisan Posted May 10, 2013 Author Posted May 10, 2013 Very clever, using a "dummy" GDI graphic with no defined size to get the size needed. It works well. Thanks UEZ!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now