autotextbox enhancement

R

riccifs

Hi to everyone in the newsgroups,
I am using on my form, a Lebans's code, to auto size the dimensions of
text box to fit its content.
I find this example at, http://www.lebans.com/autosize_textbox.htm
Of course, it works great and I am happy with that, but what I really
would like is ''to see'' the box to resize itself each time I press a
single key!
In other words, I'd like to have the text box to grow and to shrink
''on live'', at same time I am writing something in the box!
Is it possible to modify the code to do that? (may be using the
keypress event or something like that!)

I hope to have an answer to someone in the N.G.
Bye and thanks a lot,
Stefano.
 
M

Marshall Barton

Hi to everyone in the newsgroups,
I am using on my form, a Lebans's code, to auto size the dimensions of
text box to fit its content.
I find this example at, http://www.lebans.com/autosize_textbox.htm
Of course, it works great and I am happy with that, but what I really
would like is ''to see'' the box to resize itself each time I press a
single key!
In other words, I'd like to have the text box to grow and to shrink
''on live'', at same time I am writing something in the box!
Is it possible to modify the code to do that? (may be using the
keypress event or something like that!)


I think you can use the same code you have now, just move it
to the text box's Change event and use the .Text property
instead of the .Value property. E,g,

Me.thetextbox.Width = fTextWidth(Me.thetextbox, _
Me.thetextbox.Text)
 
R

riccifs

I think you can use the same code you have now, just move it
to the text box's Change event and use the .Text property
instead of the .Value property. E,g,

Me.thetextbox.Width = fTextWidth(Me.thetextbox, _
Me.thetextbox.Text)

Hi Marsh,
thanks to have answered me, could you explain better your idea?
I am not very good in VBA coding and I need a step by step
explanation, or something like that.
sorry... but again, I don't known how to do!

Tanks a lot again for your help,
Stefano.
 
M

Marshall Barton

thanks to have answered me, could you explain better your idea?
I am not very good in VBA coding and I need a step by step
explanation, or something like that.
sorry... but again, I don't known how to do!


You said that you have some code that does what you want,
but after the data was entered. Because you did not poat
your existing code, I guessed that it was in the text box's
AfterUpdate event and looked like:
Me.thetextbox.Width = fTextWidth(Me.thetextbox)
I said to move it to the Change event and modify it as I
demonstrated. I really don't know what about my reply you
don't understand.

You might be able to help me understand if post post a
Copy/Paste of your code. Then maybe I can explain how it
should be changed.
 
R

riccifs

You said that you have some code that does what you want,
but after the data was entered. Because you did not poat
your existing code, I guessed that it was in the text box's
AfterUpdate event and looked like:
Me.thetextbox.Width = fTextWidth(Me.thetextbox)
I said to move it to the Change event and modify it as I
demonstrated. I really don't know what about my reply you
don't understand.

You might be able to help me understand if post post a
Copy/Paste of your code. Then maybe I can explain how it
should be changed.

Hi Marsh,
the code I am using is quite long to post, that's why I thought it was
better to write the web-link where to find it.
In any case in "Private Sub Form_Current" event there is that code:
'************* Start Code
**************************************************
' This example if formatted for a control
' in the Detail Section.
' Obviously changes will be required if your
' Control is placed in a different Section.

' This example resizes the Control Width and Height
' to fit all the current contents. I have sized the
' Form at 18 inches in width for this Demo to allow
' for testing of large Font sizes.

' You can easily modify these functions to
' fix the Height or Width of the Control if


' ***************NOTE***************
' Be aware of the Fudge values you
' see here if you are using these routines
' to align multiple controls to simulate
' one larger Control.
' ***************NOTE***************

Dim sRect As RECT
Dim sRectInt As sRectInteger

sRect = fAutoSizeTextBoxM(Me.txtExtraInfo)

' SRect's members are all LONG values.
' Let's copy to a dup structure but with
' all members as Integers
With sRectInt
..Bottom = CInt(sRect.Bottom)
..Right = CInt(sRect.Right)

' Becasue of the internal fomatting(Margins) Access uses we have
' to fudge the Control's Height a bit.
If .Bottom > 0 Then
'If .Bottom < Me.Detail.Height Then
Me.txtExtraInfo.Height = .Bottom + (.Bottom * 0.05)
'Else: Me.txtExtraInfo.Height = Me.Detail.Height
'End If
End If

' Fudge Problem
' on a relative narrow box, <1440 twips, the Text is not rendered
' correctly with my .02 Fudge factor. Access must be using an
' inset margin and the .02 Fudge is not sufficient at narrower widths.
' I stuck this IIF statement in for now until I figure out
' the method Access is using.
If .Right > 0 Then
If .Right < Me.Width Then
Me.txtExtraInfo.Width = .Right + IIf((.Right * 0.01) < 50,
50, .Right * 0.01)

Else: Me.txtExtraInfo.Width = Me.Width
End If
End If
End With
End Sub
'*************** End Code
*********************************************
The fAutoSizeTextBoxM is a function in this Module:
'*************** Start Module Code ***********************************
Option Compare Database
Option Explicit

Private Const DT_NOPREFIX = &H800
Public Type RECT
Left As Long
top As Long
right As Long
Bottom As Long
End Type


' Declare API functions
Private Declare Function apiCreateFont Lib "gdi32" Alias "CreateFontA"
_
(ByVal H As Long, ByVal W As Long, ByVal E As Long, ByVal O As Long, _
ByVal W As Long, ByVal i As Long, ByVal u As Long, ByVal S As Long, _
ByVal c As Long, ByVal OP As Long, ByVal CP As Long, ByVal Q As Long,
_
ByVal PAF As Long, ByVal F As String) As Long

Private Declare Function apiSelectObject Lib "gdi32" Alias
"SelectObject" (ByVal hDC As Long, _
ByVal hObject As Long) As Long

Private Declare Function apiDeleteObject Lib "gdi32" _
Alias "DeleteObject" (ByVal hObject As Long) As Long

Private Declare Function apiGetDeviceCaps Lib "gdi32" Alias
"GetDeviceCaps" _
(ByVal hDC As Long, ByVal nIndex As Long) As Long

Private Declare Function apiMulDiv Lib "kernel32" Alias
"MulDiv" (ByVal nNumber As Long, _
ByVal nNumerator As Long, ByVal nDenominator As Long) As Long

Private Declare Function apiCreateIC Lib "gdi32" Alias "CreateICA" _
(ByVal lpDriverName As String, ByVal lpDeviceName As String, _
ByVal lpOutput As String, lpInitData As Any) As Long

Private Declare Function apiGetDC Lib "user32" _
Alias "GetDC" (ByVal hwnd As Long) As Long

Private Declare Function apiReleaseDC Lib "user32" _
Alias "ReleaseDC" (ByVal hwnd As Long, _
ByVal hDC As Long) As Long

Private Declare Function apiDeleteDC Lib "gdi32" _
Alias "DeleteDC" (ByVal hDC As Long) As Long

Private Declare Function apiDrawText Lib "user32" Alias "DrawTextA" _
(ByVal hDC As Long, ByVal lpStr As String, ByVal nCount As Long, _
lprect As RECT, ByVal wFormat As Long) As Long


' CONSTANTS
Private Const TWIPSPERINCH = 1440
' Used to ask System for the Logical pixels/inch in Y axis
Private Const LOGPIXELSY = 90

' DrawText() Format Flags
Private Const DT_TOP = &H0
Private Const DT_LEFT = &H0
Private Const DT_SINGLELINE = &H20
Private Const DT_CALCRECT = &H400




Public Function fAutoSizeTextBoxM(ctl As Control) As RECT

'Name fAutoSizeTextBoxM
'
'Purpose: Returns Control Width & Height needed to
' display the contents of the Control passed
' to this function. This function
' uses the Control's font attributes to
build
' a Font for the required
Calculations. currently selected into the
Control passed to this Function
'Version: 2.0 RAW :)
'Calls: Text API stuff. DrawText pewrforms the
actual
' calculation to determine Control Width/
Height
'Returns: Standard Rectangle Structure
'Created by: Stephen Lebans
'Credits: Dimitri Furman for debugging the Function
'Date: Jan. 14, 2000
'Time: 12:19:23pm
'Feedback: (e-mail address removed)
'My Web Page: www.lebans.com
'Copyright: Lebans Holdings Ltd.
' May not be resold in whole or part
' but may be used without restriction
' in any application you develop.
'


'Bugs:
'Not tested enough to tell. Let me know
'NEEDS ERROR CHECKING!!!!!
'
'Enjoy
'Stephen Lebans

'***************Code Start***************

' Did we get a valid control passed to us?
If IsNull(ctl.fontsize) Then Exit Function

' Did we get a valid control passed to us?
If Len(ctl & "") = 0 Then Exit Function

' Structure for DrawText calc
Dim sRect As RECT

' Handle to Report's window
Dim hwnd As Long

' Reports Device Context
Dim hDC As Long

' Holds the current screen resolution
Dim lngYdpi As Long

Dim newfont As Long
' Handle to our Font Object we created.
' We must destroy it before exiting main function

Dim oldfont As Long
' Device COntext's Font we must Select back into the DC
' before we exit this function.

' Temporary holder for returns from API calls
Dim lngRet As Long

' Calculate screen Font height
Dim fheight As Long

' Get Controls Parents Window handle
hwnd = ctl.Parent.hwnd
If hwnd = 0 Then Exit Function

' retrieve a handle to a display device context (DC)
' for the client area of the specified window
hDC = apiGetDC(hwnd)

' Because Access control's do not have a permanent Device Context,
' we cannot depend on what we find selected into the DC unless
' the Control has the focus. In this case we are simply using the
' Control's Font attributes to build our own font in whatever
' DC is handy. We must Save this DC's Font so we can restore
' the Font when we exit this function.

' Clear our return value
lngRet = 0


' Temporary Information Context for Screen info.
Dim lngIC As Long

' Modified to allow for different screen resolutions
' and printer output. Needed to Calculate Font size
lngIC = apiCreateIC("DISPLAY", vbNullString, vbNullString,
vbNullString)
If lngIC <> 0 Then
lngYdpi = apiGetDeviceCaps(lngIC, LOGPIXELSY)
apiDeleteDC (lngIC)
Else
lngYdpi = 120 'Default average value
End If

' Calculate/Convert requested Font Height
' into Font's Device Coordinate space
fheight = apiMulDiv(ctl.fontsize, lngYdpi, 72)

' We use a negative value to signify
' to the CreateFont function that we want a Glyph
' outline of this size not a bounding box.

With ctl
newfont = apiCreateFont(-fheight, 0, _
0, 0, .FontWeight, _
.FontItalic, .FontUnderline, _
0, 0, 0, _
0, 0, 0, .FontName)
End With

' Select the new font into our DC.
oldfont = apiSelectObject(hDC, newfont)

' Use DrawText to Calculate height of Rectangle required to hold
' the current contents of the Control passed to this function

With sRect
.Left = 0
.top = 0
.Bottom = 0 'ctl.Height / (TWIPSPERINCH / lngYdpi)
.right = 0 'ctl.Width / (TWIPSPERINCH / lngYdpi)
lngRet = apiDrawText(hDC, ctl.Value, -1, sRect, DT_CALCRECT Or
DT_TOP Or DT_LEFT Or DT_NOPREFIX)

' Cleanup
lngRet = apiSelectObject(hDC, oldfont)
' Delete the Font we created
apiDeleteObject (newfont)

lngRet = apiReleaseDC(hwnd, hDC)

' Convert RECT values to TWIPS
.Bottom = .Bottom * (TWIPSPERINCH / lngYdpi)
.right = .right * (TWIPSPERINCH / lngYdpi)
End With
fAutoSizeTextBoxM = sRect

End Function
'***************** End Module Code
*************************************************

bye,
Stefano.
 
M

Marshall Barton

the code I am using is quite long to post, that's why I thought it was
better to write the web-link where to find it.


My fault, I saw the lebans part of the url and my mind lept
to the page that I use for that sort of thing.

I am not familiar with that particular code (not surprising
considering the amount of stuff Stephen has there), but I
think you can just call the Current event procedure from the
text box's Change event with just one line of code:
Call Form_Current()
I doubt that I can help you if that idea causes trouble.

The approach I use to resize a text box is to download and
use Stephen's TextHeightWidth module as I posted earlier.
 
R

riccifs

My fault, I saw the lebans part of the url and my mind lept
to the page that I use for that sort of thing.

I am not familiar with that particular code (not surprising
considering the amount of stuff Stephen has there), but I
think you can just call the Current event procedure from the
text box's Change event with just one line of code:
Call Form_Current()
I doubt that I can help you if that idea causes trouble.

The approach I use to resize a text box is to download and
use Stephen's TextHeightWidth module as I posted earlier.

Hi Marsh,
many thanks for your help, your procedure is working fine, but only
after I press the ''tab'' key.
Is it possible make it works for each key pressed as well? or I am
asking to much from that code?
What is your opinion about it?

In any case, you give to me a great help, I really appreciate that
Stefano.
 
M

Marshall Barton

Hi Marsh,
many thanks for your help, your procedure is working fine, but only
after I press the ''tab'' key.
Is it possible make it works for each key pressed as well? or I am
asking to much from that code?
What is your opinion about it?

In any case, you give to me a great help, I really appreciate that
Stefano.


Which procedure did you use, the one you had before or the
TextHeightWidth approach that I use?

Which version of Access are you using?

I just realized that your original procedure always uses the
text box's Value property and has no way to use the Text
property. This means that you either have to change the
code in the fAutoSizeTextBoxM function or use a different
function.

Are you adjusting both the text box's Height and Width or
just the Width? If you are changing the Height, then I will
have to revise my suggestion of how to use the
TextHeightWidth module.
 
R

riccifs

Which procedure did you use, the one you had before or the
TextHeightWidth approach that I use?

Which version of Access are you using?

I just realized that your original procedure always uses the
text box's Value property and has no way to use the Text
property. This means that you either have to change the
code in the fAutoSizeTextBoxM function or use a different
function.

Are you adjusting both the text box's Height and Width or
just the Width? If you are changing the Height, then I will
have to revise my suggestion of how to use the
TextHeightWidth module.

Hi Marsh,
the module function that I'm using is fAutoSizeTextBoxMulti on Access
2003 service SP2.
I'm applying your last hint, the one that call the Current event
procedure from the text box's Change event with this line of code:
Call Form_Current().
At moment I'm adjusting both text box's Height and Width, but if it
can more easy to do , I can decide to change just the Width of the
textbox, I realy don't mind that! My font size and kind will always
stay the same.
Which function I have to use? Where I can find TextHeightWidth module
that you are using?

Stefano.
 
M

Marshall Barton

the module function that I'm using is fAutoSizeTextBoxMulti on Access
2003 service SP2.
I'm applying your last hint, the one that call the Current event
procedure from the text box's Change event with this line of code:
Call Form_Current().
At moment I'm adjusting both text box's Height and Width, but if it
can more easy to do , I can decide to change just the Width of the
textbox, I realy don't mind that! My font size and kind will always
stay the same.
Which function I have to use? Where I can find TextHeightWidth module
that you are using?


Well, I didn't expect this to take half the afternoon, but I
think I got what you want out of the code you had. I did
have to change the code in several places though.

Be careful fixing up all the line wrapping that one or both
if our news reader programs introduce into the code.
--
Marsh
MVP [MS Access]

------------------------------------------------------------------------------
Here's what I ended up with in the form's module:

Private Sub txtExtraInfo_Change()
FudgeIt fAutoSizeTextBoxM(Me.txtExtraInfo, True)
End Sub

Private Sub Form_Current()
FudgeIt fAutoSizeTextBoxM(Me.txtExtraInfo, False)
End Sub

Private Sub FudgeIt(Srect As RECT)
With Srect
' ***************NOTE***************
' Be aware of the Fudge values you
' see here if you are using these routines
' to align multiple controls to simulate
' one larger Control.
' ***************NOTE***************

' Becasue of the internal fomatting(Margins) Access
' uses we have to fudge the Control's Height a bit.
If .Bottom > 0 Then
If .Bottom < Me.Detail.Height Then
Me.txtExtraInfo.Height = .Bottom * 1.1
Else
Me.txtExtraInfo.Height = Me.Detail.Height
End If
End If

' Fudge Problem
' on a relative narrow box, <1440 twips, the Text is not
rendered
' correctly with my .02 Fudge factor. Access must be using
' an inset margin and the .02 Fudge is not sufficient at
narrower widths.
' I stuck this IIF statement in for now until I figure out
' the method Access is using.
If .right > 0 Then
If .right < Me.Width Then
Me.txtExtraInfo.Width = .right + IIf((.right * 0.1)
< 50, 50, .right * 0.1)
Else
Me.txtExtraInfo.Width = Me.Width
End If
End If
End With

End Sub
------------------------------------------------------------------------------
And here's the modified version of the fAutoSizeTextBoxM
function:

Public Type RECT
Left As Long
top As Long
right As Long
Bottom As Long
End Type

' Declare API functions
Private Declare Function apiCreateFont Lib "gdi32" _
Alias "CreateFontA" (ByVal H As Long, _
ByVal W As Long, ByVal E As Long, _
ByVal O As Long, ByVal W As Long, _
ByVal i As Long, ByVal u As Long, _
ByVal S As Long, ByVal c As Long, _
ByVal OP As Long, ByVal CP As Long, _
ByVal Q As Long, ByVal PAF As Long, _
ByVal F As String) As Long

Private Declare Function apiSelectObject Lib "gdi32" _
Alias "SelectObject" (ByVal hDC As Long, _
ByVal hObject As Long) As Long

Private Declare Function apiDeleteObject Lib "gdi32" _
Alias "DeleteObject" (ByVal hObject As Long _
) As Long

Private Declare Function apiGetDeviceCaps Lib "gdi32" _
Alias "GetDeviceCaps" (ByVal hDC As Long, _
ByVal nIndex As Long) As Long

Private Declare Function apiMulDiv Lib "kernel32" _
Alias "MulDiv" (ByVal nNumber As Long, _
ByVal nNumerator As Long, _
ByVal nDenominator As Long) As Long

Private Declare Function apiCreateIC Lib "gdi32" _
Alias "CreateICA" (ByVal lpDriverName As String, _
ByVal lpDeviceName As String, _
ByVal lpOutput As String, _
lpInitData As Any) As Long

Private Declare Function apiGetDC Lib "user32" _
Alias "GetDC" (ByVal hwnd As Long) As Long

Private Declare Function apiReleaseDC Lib "user32" _
Alias "ReleaseDC" (ByVal hwnd As Long, _
ByVal hDC As Long) As Long

Private Declare Function apiDeleteDC Lib "gdi32" _
Alias "DeleteDC" (ByVal hDC As Long) As Long

Private Declare Function apiDrawText Lib "user32" _
Alias "DrawTextA" (ByVal hDC As Long, _
ByVal lpStr As String, ByVal nCount As Long, _
lprect As RECT, ByVal wFormat As Long) As Long

' CONSTANTS
Private Const TWIPSPERINCH = 1440
' Used to ask System for the Logical pixels/inch in Y axis
Private Const LOGPIXELSY = 90

' DrawText() Format Flags
Private Const DT_TOP = &H0
Private Const DT_LEFT = &H0
Private Const DT_SINGLELINE = &H20
Private Const DT_CALCRECT = &H400


Public Function fAutoSizeTextBoxM(ctl As Control, _
UseText As Boolean) As RECT

'Name fAutoSizeTextBoxM
'
'Purpose: Returns Control Width & Height needed to
' display the contents of the Control passed
' to this function. This function
' uses the Control's font attributes to Build
' a Font for the required Calculations into the
' Control passed to this Function
'Version: 2.0 RAW :)
'Calls: Text API stuff. DrawText performs the actual
' calculation to determine Control Width/Height
'Returns: Standard Rectangle Structure
'Created by: Stephen Lebans
'Credits: Dimitri Furman for debugging the Function
'Date: Jan. 14, 2000
'Time: 12:19:23pm
'Feedback: (e-mail address removed)
'My Web Page: www.lebans.com
'Copyright: Lebans Holdings Ltd.
' May not be resold in whole or part
' but may be used without restriction
' in any application you develop.
'
'Bugs:
'Not tested enough to tell. Let me know
'NEEDS ERROR CHECKING!!!!!
'
'Enjoy
'Stephen Lebans
'***************Code Start***************

' Did we get a valid control passed to us?
If IsNull(ctl.FontSize) Then Exit Function

' Did we get a valid control passed to us?
If Len(ctl & "") = 0 Then Exit Function

' Structure for DrawText calc
Dim Srect As RECT

' Handle to Report's window
Dim hwnd As Long

' Reports Device Context
Dim hDC As Long

' Holds the current screen resolution
Dim lngYdpi As Long

Dim newfont As Long
' Handle to our Font Object we created.
' We must destroy it before exiting main function

Dim oldfont As Long
' Device COntext's Font we must Select back into the DC
' before we exit this function.

' Temporary holder for returns from API calls
Dim lngRet As Long

' Calculate screen Font height
Dim fheight As Long

' Get Controls Parents Window handle
hwnd = ctl.Parent.hwnd
If hwnd = 0 Then Exit Function

' retrieve a handle to a display device context (DC)
' for the client area of the specified window
hDC = apiGetDC(hwnd)

' Because Access control's do not have a permanent
' Device Context, we cannot depend on what we find
' selected into the DC unless the Control has the focus.
' In this case we are simply using the Control's Font
' attributes to build our own font in whatever
' DC is handy. We must Save this DC's Font so we can
' restore the Font when we exit this function.

' Clear our return value
lngRet = 0

' Temporary Information Context for Screen info.
Dim lngIC As Long

' Modified to allow for different screen resolutions
' and printer output. Needed to Calculate Font size
lngIC = apiCreateIC("DISPLAY", vbNullString, _
vbNullString, vbNullString)
If lngIC <> 0 Then
lngYdpi = apiGetDeviceCaps(lngIC, LOGPIXELSY)
apiDeleteDC (lngIC)
Else
lngYdpi = 120 'Default average value
End If

' Calculate/Convert requested Font Height
' into Font's Device Coordinate space
fheight = apiMulDiv(ctl.FontSize, lngYdpi, 72)

' We use a negative value to signify
' to the CreateFont function that we want a Glyph
' outline of this size not a bounding box.

With ctl
newfont = apiCreateFont(-fheight, 0, _
0, 0, .FontWeight, _
.FontItalic, .FontUnderline, _
0, 0, 0, _
0, 0, 0, .FontName)
End With

' Select the new font into our DC.
oldfont = apiSelectObject(hDC, newfont)

' Use DrawText to Calculate height of Rectangle
' required to hold the current contents of the
' Control passed to this function

With Srect
.Left = 0
.top = 0
.Bottom = 0 'ctl.Height / (TWIPSPERINCH / lngYdpi)
.right = 0 'ctl.Width / (TWIPSPERINCH / lngYdpi)
If UseText Then
lngRet = apiDrawText(hDC, ctl.Text, -1, Srect,
DT_CALCRECT _
Or DT_TOP Or DT_LEFT Or DT_NOPREFIX)
Else
lngRet = apiDrawText(hDC, ctl.Value, -1, Srect,
DT_CALCRECT _
Or DT_TOP Or DT_LEFT Or DT_NOPREFIX)
End If

' Cleanup
lngRet = apiSelectObject(hDC, oldfont)
' Delete the Font we created
apiDeleteObject (newfont)

lngRet = apiReleaseDC(hwnd, hDC)

' Convert RECT values to TWIPS
.Bottom = .Bottom * (TWIPSPERINCH / lngYdpi)
.right = .right * (TWIPSPERINCH / lngYdpi)
End With
fAutoSizeTextBoxM = Srect

End Function
 
R

riccifs

the module function that I'm using is fAutoSizeTextBoxMulti on Access
2003 service SP2.
I'm applying your last hint, the one that call the Current event
procedure from the text box's Change event with this line of code:
Call Form_Current().
At moment I'm adjusting both text box's Height and Width, but if it
can more easy to do , I can decide to change just the Width of the
textbox, I realy don't mind that! My font size and kind will always
stay the same.
Which function I have to use? Where I can find TextHeightWidth module
that you are using?

Well, I didn't expect this to take half the afternoon, but I
think I got what you want out of the code you had. I did
have to change the code in several places though.

Be careful fixing up all the line wrapping that one or both
if our news reader programs introduce into the code.
--
Marsh
MVP [MS Access]

------------------------------------------------------------------------------
Here's what I ended up with in the form's module:

Private Sub txtExtraInfo_Change()
FudgeIt fAutoSizeTextBoxM(Me.txtExtraInfo, True)
End Sub

Private Sub Form_Current()
FudgeIt fAutoSizeTextBoxM(Me.txtExtraInfo, False)
End Sub

Private Sub FudgeIt(Srect As RECT)
With Srect
' ***************NOTE***************
' Be aware of the Fudge values you
' see here if you are using these routines
' to align multiple controls to simulate
' one larger Control.
' ***************NOTE***************

' Becasue of the internal fomatting(Margins) Access
' uses we have to fudge the Control's Height a bit.
If .Bottom > 0 Then
If .Bottom < Me.Detail.Height Then
Me.txtExtraInfo.Height = .Bottom * 1.1
Else
Me.txtExtraInfo.Height = Me.Detail.Height
End If
End If

' Fudge Problem
' on a relative narrow box, <1440 twips, the Text is not
rendered
' correctly with my .02 Fudge factor. Access must be using
' an inset margin and the .02 Fudge is not sufficient at
narrower widths.
' I stuck this IIF statement in for now until I figure out
' the method Access is using.
If .right > 0 Then
If .right < Me.Width Then
Me.txtExtraInfo.Width = .right + IIf((.right * 0.1)
< 50, 50, .right * 0.1)
Else
Me.txtExtraInfo.Width = Me.Width
End If
End If
End With

End Sub
------------------------------------------------------------------------------
And here's the modified version of the fAutoSizeTextBoxM
function:

Public Type RECT
Left As Long
top As Long
right As Long
Bottom As Long
End Type

' Declare API functions
Private Declare Function apiCreateFont Lib "gdi32" _
Alias "CreateFontA" (ByVal H As Long, _
ByVal W As Long, ByVal E As Long, _
ByVal O As Long, ByVal W As Long, _
ByVal i As Long, ByVal u As Long, _
ByVal S As Long, ByVal c As Long, _
ByVal OP As Long, ByVal CP As Long, _
ByVal Q As Long, ByVal PAF As Long, _
ByVal F As String) As Long

Private Declare Function apiSelectObject Lib "gdi32" _
Alias "SelectObject" (ByVal hDC As Long, _
ByVal hObject As Long) As Long

Private Declare Function apiDeleteObject Lib "gdi32" _
Alias "DeleteObject" (ByVal hObject As Long _
) As Long

Private Declare Function apiGetDeviceCaps Lib "gdi32" _
Alias "GetDeviceCaps" (ByVal hDC As Long, _
ByVal nIndex As Long) As Long

Private Declare Function apiMulDiv Lib "kernel32" _
Alias "MulDiv" (ByVal nNumber As Long, _
ByVal nNumerator As Long, _
ByVal nDenominator As Long) As Long

Private Declare Function apiCreateIC Lib "gdi32" _
Alias "CreateICA" (ByVal lpDriverName As String, _
ByVal lpDeviceName As String, _
ByVal lpOutput As String, _
lpInitData As Any) As Long

Private Declare Function apiGetDC Lib "user32" _
Alias "GetDC" (ByVal hwnd As Long) As Long

Private Declare Function apiReleaseDC Lib "user32" _
Alias "ReleaseDC" (ByVal hwnd As Long, _
ByVal hDC As Long) As Long

Private Declare Function apiDeleteDC Lib "gdi32" _
Alias "DeleteDC" (ByVal hDC As Long) As Long

Private Declare Function apiDrawText Lib "user32" _
Alias "DrawTextA" (ByVal hDC As Long, _
ByVal lpStr As String, ByVal nCount As Long, _
lprect As RECT, ByVal wFormat As Long) As Long

' CONSTANTS
Private Const TWIPSPERINCH = 1440
' Used to ask System for the Logical pixels/inch in Y axis
Private Const LOGPIXELSY = 90

' DrawText() Format Flags
Private Const DT_TOP = &H0
Private Const DT_LEFT = &H0
Private Const DT_SINGLELINE = &H20
Private Const DT_CALCRECT = &H400

Public Function fAutoSizeTextBoxM(ctl As Control, _
UseText As Boolean) As RECT

'Name fAutoSizeTextBoxM
'
'Purpose: Returns Control Width & Height needed to
' display the contents of the Control passed
' to this function. This function
' uses the Control's font attributes to Build
' a Font for the required Calculations into the
' Control passed to this Function
'Version: 2.0 RAW :)
'Calls: Text API stuff. DrawText performs the actual
' calculation to determine Control Width/Height
'Returns: Standard Rectangle Structure
'Created by: Stephen Lebans
'Credits: Dimitri Furman for debugging the Function
'Date: Jan. 14, 2000
'Time: 12:19:23pm
'Feedback: (e-mail address removed)
'My Web Page: www.lebans.com
'Copyright: Lebans Holdings Ltd.
' May not be resold in whole or part
' but may be used without restriction
' in any application you develop.
'
'Bugs:
'Not tested enough to tell. Let me know
'NEEDS ERROR CHECKING!!!!!
'
'Enjoy
'Stephen Lebans
'***************Code Start***************

' Did we get a valid control passed to us?
If IsNull(ctl.FontSize) Then Exit Function

' Did we get a valid control passed to us?
If Len(ctl & "") = 0 Then Exit Function

' Structure for DrawText calc
Dim Srect As RECT

' Handle to Report's window
Dim hwnd As Long

' Reports Device Context
Dim hDC As Long

' Holds the current screen resolution
Dim lngYdpi As Long

Dim newfont As Long
' Handle to our Font Object we created.
' We must destroy it before exiting main function

Dim oldfont As Long
' Device COntext's Font we must Select back into the DC
' before we exit this function.

' Temporary holder for returns from API calls
Dim lngRet As Long

' Calculate screen Font height
Dim fheight As Long

' Get Controls Parents Window handle
hwnd = ctl.Parent.hwnd
If hwnd = 0 Then Exit Function

' retrieve a handle to a display device context (DC)
' for the client area of the specified window
hDC = apiGetDC(hwnd)

' Because Access control's do not have a permanent
' Device Context, we cannot depend on what we find
' selected into the DC unless the Control has the focus.
' In this case we are simply using the Control's Font
' attributes to build our own font in whatever
' DC is handy. We must Save this DC's Font so we can
' restore the Font when we exit this function.

' Clear our return value
lngRet = 0

' Temporary Information Context for Screen info.
Dim lngIC As Long

' Modified to allow for different screen resolutions
' and printer output. Needed to Calculate Font size
lngIC = apiCreateIC("DISPLAY", vbNullString, _
vbNullString, vbNullString)
If lngIC <> 0 Then
lngYdpi = apiGetDeviceCaps(lngIC, LOGPIXELSY)
apiDeleteDC (lngIC)
Else
lngYdpi = 120 'Default average value
End If

' Calculate/Convert requested Font Height
' into Font's Device Coordinate space
fheight = apiMulDiv(ctl.FontSize, lngYdpi, 72)

' We use a negative value to signify
' to the CreateFont function that we want a Glyph
' outline of this size not a bounding box.

With ctl
newfont = apiCreateFont(-fheight, 0, _
0, 0, .FontWeight, _
.FontItalic, .FontUnderline, _
0, 0, 0, _
0, 0, 0, .FontName)
End With

' Select the new font into our DC.
oldfont = apiSelectObject(hDC, newfont)

' Use DrawText to Calculate height of Rectangle
' required to hold the current contents of the
' Control passed to this function

With Srect
.Left = 0
.top = 0
.Bottom = 0 'ctl.Height / (TWIPSPERINCH / lngYdpi)
.right = 0 'ctl.Width / (TWIPSPERINCH / lngYdpi)
If UseText Then
lngRet = apiDrawText(hDC, ctl.Text, -1, Srect,
DT_CALCRECT _
Or DT_TOP Or DT_LEFT Or DT_NOPREFIX)
Else
lngRet = apiDrawText(hDC, ctl.Value, -1, Srect,
DT_CALCRECT _
Or DT_TOP Or DT_LEFT Or DT_NOPREFIX)
End If

' Cleanup
lngRet = apiSelectObject(hDC, oldfont)
' Delete the Font we created
apiDeleteObject (newfont)

lngRet = apiReleaseDC(hwnd, hDC)

' Convert RECT values to TWIPS
.Bottom = .Bottom * (TWIPSPERINCH / lngYdpi)
.right = .right * (TWIPSPERINCH / lngYdpi)
End With
fAutoSizeTextBoxM = Srect

End Function

Hi Marsh,
I'm really believing that you are a genius a something like that!!!
Your code works AT TOP! and it does EXACTLY want I wanted.
You did a master job! I think you are even better than Lebans, (sorry
Stephen...!)

Many many thanks for the great help you give to me!
I would not be able to do all that on my own, even after a couple of
years of work!
Bye,
Stefano.
 
M

Marshall Barton

Hi Marsh,
I'm really believing that you are a genius a something like that!!!
Your code works AT TOP! and it does EXACTLY want I wanted.
You did a master job! I think you are even better than Lebans, (sorry
Stephen...!)

Many many thanks for the great help you give to me!
I would not be able to do all that on my own, even after a couple of
years of work!


I do appreciate the accolades, but let's put the credit
where credit is due. Don't forget that all this started
after you downloaded the original code from
www.lebans.com

I have no pretensions of doing what Stephen does and just
because I can read a few parts of some of his procedures
does not in any way imply that I could write even a small
fraction of the incredible stuff he has created.
 
R

riccifs

I do appreciate the accolades, but let's put the credit
where credit is due. Don't forget that all this started
after you downloaded the original code fromwww.lebans.com

I have no pretensions of doing what Stephen does and just
because I can read a few parts of some of his procedures
does not in any way imply that I could write even a small
fraction of the incredible stuff he has created.

Of course, you're right and I do agree with you.
I have been only too much enthusiastic.... but I known what you mean!
Sorry about that...

Bye,
Stefano.

P.S. (believe to me, it's the last one!)
Is there an easy way to fire this routine for any Textbox in a form,
without having to write the usual code for each textbox?
 
M

Marshall Barton

Is there an easy way to fire this routine for any Textbox in a form,
without having to write the usual code for each textbox?


There are several things that can be done to make it easier
for you to use on other text boxes. The first thing would
be to modify the FudgeIt procedure to accept the text box as
an argument. Then, the only code needed a text box's event
procedure would be the one line of code to call FudgeIt.

You could even take it one step further by changing FudgeIt
from a Sub to a Function. Then you can do away with the one
line event procedures by changing the event property from
[Event Procedure]
to
=FudgeIt(textboxname, fAutoSizeTextBoxM(textboxname,
False))

At this point I feel compelled to ask what kind of UI are
you creating. It seems to me that more than one or two of
these dynamically growing text boxes would create a lot of
confusion both to the users and to your code that tries to
make sure these text boxes don't collide with each other.
 
R

riccifs

Is there an easy way to fire this routine for any Textbox in a form,
without having to write the usual code for each textbox?

There are several things that can be done to make it easier
for you to use on other text boxes. The first thing would
be to modify the FudgeIt procedure to accept the text box as
an argument. Then, the only code needed a text box's event
procedure would be the one line of code to call FudgeIt.

You could even take it one step further by changing FudgeIt
from a Sub to a Function. Then you can do away with the one
line event procedures by changing the event property from
[Event Procedure]
to
=FudgeIt(textboxname, fAutoSizeTextBoxM(textboxname,
False))

At this point I feel compelled to ask what kind of UI are
you creating. It seems to me that more than one or two of
these dynamically growing text boxes would create a lot of
confusion both to the users and to your code that tries to
make sure these text boxes don't collide with each other.

May be you are right Marsh.
Make no sense to have more than a couple of these dynamically growing
text boxes for each form.
In any case I'm more than thank to you.
Bye...
Stefano.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top