FUNCTION NeededHeightForAnEditBox (Contents AS String, AvailableWidth AS Integer, Model AS StringOrEditBox) LOCAL NeededHeightForAnEditBox AS Integer LOCAL TestBox AS EditBox LOCAL RealAvailableWidth AS Integer LOCAL CurrentHeight AS Integer IF PCOUNT() = 3 IF VARTYPE(m.Model) == "C" m.TestBox = CREATEOBJECT(m.Model) ELSE m.TestBox = CREATEOBJECT("EditBox") WITH m.Model AS EditBox m.TestBox.FontName = .FontName m.TestBox.FontSize = .FontSize m.TestBox.FontItalic = .FontItalic m.TestBox.FontBold = .FontBold m.TestBox.Margin = .Margin m.TestBox.BorderStyle = .BorderStyle m.TestBox.Margin = .Margin ENDWITH ENDIF ELSE m.TestBox = CREATEOBJECT("EditBox") ENDIF m.RealAvailableWidth = m.AvailableWidth - m.TestBox.Margin * 2 - m.TestBox.BorderStyle * 2 m.CurrentHeight = m.TestBox.Height LOCAL LineHeight AS Integer LOCAL ExtraHeight AS Integer LOCAL FontStyle AS String m.FontStyle = EVL(; IIF(m.TestBox.FontBold,"B","") + ; IIF(m.TestBox.FontItalic,"I",""),"N") m.TestBox.IntegralHeight = .F. m.TestBox.Height = m.TestBox.Margin * 2 m.TestBox.ScrollBars = 0 m.ExtraHeight = m.TestBox.Height m.TestBox.IntegralHeight = .T. m.LineHeight = m.TestBox.Height + FONTMETRIC(4,m.TestBox.FontName,m.TestBox.FontSize,m.FontStyle) - m.ExtraHeight LOCAL ARRAY Words(1) LOCAL WordIndex AS Integer LOCAL WordWidth AS Integer LOCAL SpaceWidth AS Integer LOCAL OcuppiedInLine AS Integer LOCAL LinesNeeded AS Integer m.LinesNeeded = 1 m.OcuppiedInLine = 0 m.SpaceWidth = TXTWIDTH(" ",m.TestBox.FontName,m.TestBox.FontSize,m.FontStyle) * FONTMETRIC(6,m.TestBox.FontName,m.TestBox.FontSize,m.FontStyle) FOR m.WordIndex = 1 TO ALINES(m.Words,m.Contents,1 + 4," ") m.WordWidth = TXTWIDTH(m.Words[m.WordIndex],m.TestBox.FontName,m.TestBox.FontSize,m.FontStyle) * FONTMETRIC(6,m.TestBox.FontName,m.TestBox.FontSize,m.FontStyle) m.OcuppiedInLine = m.OcuppiedInLine + m.WordWidth DO CASE CASE m.OcuppiedInLine > m.RealAvailableWidth m.OcuppiedInLine = m.WordWidth m.LinesNeeded = m.LinesNeeded + 1 CASE m.OcuppiedInLine = m.RealAvailableWidth IF m.WordIndex < ALEN(m.Words) m.OcuppiedInLine = 0 m.LinesNeeded = m.LinesNeeded + 1 ENDIF OTHERWISE m.OcuppiedInLine = m.OcuppiedInLine + m.SpaceWidth ENDCASE ENDFOR m.NeededHeightForAnEditBox = m.LinesNeeded * m.LineHeight + m.TestBox.Margin * 2 IF m.NeededHeightForAnEditBox != m.CurrentHeight AND VARTYPE(m.Model) == "O" m.Model.Refresh() ENDIF RETURN m.NeededHeightForAnEditBox ENDFUNCAnd two demos for it. The first one is a message log similar to the one you posted before in this thread.
LOCAL MessagesInAForm AS ExchangedMessages m.MessagesInAForm = CREATEOBJECT("ExchangedMessages") m.MessagesInAForm.Show() WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.T., "Hi, Alice") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.F., "Hi, Bob") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.T., "Did you read the report I sent you?") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.T., "If you did, I would like that you pass me the figures from the last quarter of 2016, please") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.F., "I already took a look at it") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.F., "Sure, I can do that, as soon as I ask Paul to hand them to me") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.T., "Yeah, that would be great, my manager is on me to get this before the weekend") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.F., "By the way, are you coming to the party, on saturday?") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.F., "All the guys already confirmed, I think") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.F., "Only you and Carla are yet to be confirmed") WAIT WINDOW "Typing..." TIMEOUT 1 m.MessagesInAForm.NewMessage(.T., "Can't say for Carla, but I'm going for sure!") WAIT WINDOW DEFINE CLASS ExchangedMessages AS Form ADD OBJECT Log AS MessageLog WITH Width = 400 - 18 MinWidth = 400 MaxWidth = 400 ScrollBars = 2 FUNCTION NewMessage (IsItMe AS Boolean, Contents AS String) This.Log.NewMessage(m.IsItMe, m.Contents) IF This.Log.Height > This.Height This.SetViewPort(0, This.Log.Height - This.Height) ENDIF This.Refresh() ENDFUNC ENDDEFINE DEFINE CLASS MessageLog AS Container Occupied = 0 Messages = 0 FUNCTION NewMessage (IsItMe AS Boolean, Contents AS String) LOCAL NewBox AS EditBox This.Messages = This.Messages + 1 This.AddObject("Message" + TRANSFORM(This.Messages), "EditBox") m.NewBox = EVALUATE("This.Message" + TRANSFORM(This.Messages)) m.NewBox.BorderStyle = 0 m.NewBox.ScrollBars = 0 m.NewBox.Margin = 2 m.NewBox.BackColor = IIF(m.IsItMe, RGB(128, 255, 255), RGB(128, 255, 128)) m.NewBox.Width = 250 m.NewBox.Left = IIF(m.IsItMe, This.Width - 250, 0) m.NewBox.Height = NEEDEDHEIGHTFORANEDITBOX(m.Contents, 250, m.NewBox) m.NewBox.Value = m.Contents IF This.Occupied + m.NewBox.Height + 4 + m.NewBox.Margin > This.Height This.Height = This.Height + m.NewBox.Height + 4 + m.NewBox.Margin ENDIF m.NewBox.Top = This.Occupied + 4 This.Occupied = This.Occupied + m.NewBox.Height + 2 m.NewBox.Visible = .T. ENDFUNC ENDDEFINEIn the second demo the height of the editbox is adjusted as the user types.
LOCAL MyTest AS TestForm m.MyTest = CREATEOBJECT("TestForm") m.MyTest.Show(1) DEFINE CLASS ExpandedEditBox AS EditBox ScrollBars = 0 PROCEDURE InteractiveChange This.Height = NeededHeightForAnEditBox(This.Value, This.Width, This) ENDPROC PROCEDURE ProgrammaticChange This.InteractiveChange() ENDPROC ENDDEFINE DEFINE CLASS TestForm AS Form ADD OBJECT Expandable AS ExpandedEditBox WITH Top = 10, Left = 10, Width = 200, Height = 27 ENDDEFINE