TextBoxの幅/高さを 入れる文字列毎に計算し設定したい

現在 当方の算出方法は以下のとおり

行の高さは フォントSize(pt)から単位変換(mm➡Pixel➡AppFontUnits)で求めた値に一定の定数をかけて利用
文字列幅は com.sun.star.awt.Toolkit に対し createScreenCompatibleDevice
で生成したDeviceに getFont( aFntDscrptr ).getStringWidth( aStr ) を適用し求めた値(Pixel)を 高さ同様の 単位変換(Pixel➡AppFontUnits)を基準に一定の定数をかけて利用
※単位変換は convertSizeToLogic/convertSizeToPixel を使用しました
※Tabは半角空白4文字で位置決めする前提で算出しました

表示対象文字列から テキストボックスの幅/高さを算出>設定し表示具合を確認しまてます

等倍/プロポーショナル フォント数種 × フォントサイズ 数種で 確認してますが、等倍フォントは フォント名やサイズが変わっても 前述の方法である程度追従しているようですが、プロポーショナルはフォント名により かなりの乖離がみられました(とくに"メイリオ"は幅も高さも大きめにかわります)

もっと精度いい方法があれば知りたいとおもい 問い合わせました。

【補足】
※解決上の制約事項としては、ダイアログの表示前に表示幅/高さを求めたいとおもってます。
※高さ/幅の算出は 高い精度はもとめていません。幅/高さ 1割程度余裕があってもいいと思ってます(見切れるのはマズイ)

ちょっと脇道にそれる様な話かもしれませんが参考までに…
Calcの列幅や行の高さの自動調整でサイズを自動計算させたらどうなるか試してみました。

(1)ダイアログのテキストボックスとSheet1のA1セルのフォント名、サイズを合わせる(以下の例ではメイリオ15pt)

(2)実行例 「abcde」

(3)実行例 「こんにちは12345abcde」

Sub Test()
    Dim oDialog As Object 
    oDialog = CreateUnoDialog(DialogLibraries.Standard.Dialog1)

    Dim oText As Object
    oText = oDialog.getControl("TextField1")    

    Dim sText As String	
    sText = "こんにちは12345abcde"
    oText.Text = sText

    Dim oDoc As Object
    Dim oCell As Object
    Dim oSheet As Object
    Dim oCol As Object
    Dim oRow As Object
    oDoc = ThisComponent      
    oSheet = oDoc.Sheets.getByIndex(0)
    oCell = oSheet.getCellByPosition(0, 0)
    oCell.setString(sText)
    
    oCol = oSheet.getColumns().getByIndex(0)
    oCol.OptimalWidth = True
    oRow = oSheet.getRows().getByIndex(0)
    oRow.OptimalHeight = True
 
    'Calcで自動幅調整した列幅を調整
    oText.Model.Width = oCol.Width  / 50 '←ここを調整
    oText.Model.Height= oRow.Height / 50 '←ここを調整
    oDialog.execute() 
End Sub

Version: 26.2.2.2 (X86_64)
Build ID: 1f77d10d6938fd34972958f64b2bcfa54f8b1ba5
CPU threads: 4; OS: Windows 11 X86_64 (build 22631); UI render: Skia/Vulkan; VCL: win
Locale: ja-JP (ja_JP); UI: ja-JP
Calc: threaded

Q_Taro様、getPreferredSize()でコントロールの推奨サイズが取れる様です。こちらをお試しいただけますでしょうか?

(1)ダイアログのテキストボックスのフォント名、サイズを設定(以下の例ではメイリオ15pt)

(2)実行例 「12345」

(3)実行例 「こんにちは!!12345abcde」

Sub Test()
    Dim oDialog As Object
    oDialog = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
    
    Dim oText As Object
    oText = oDialog.getControl("TextField1")

    oText.Text = "12345"

    Dim oPreferred As Object
    oPreferred = oText.getPreferredSize()

    Dim oCurPos As Object
    oCurPos = oText.getPosSize()

    oText.setPosSize( _
        oCurPos.X, _
        oCurPos.Y, _
        oPreferred.Width, _
        oPreferred.Height, _
        com.sun.star.awt.PosSize.SIZE)

    oDialog.execute()
End Sub

Version: 26.2.2.2 (X86_64)
Build ID: 1f77d10d6938fd34972958f64b2bcfa54f8b1ba5
CPU threads: 4; OS: Windows 11 X86_64 (build 22631); UI render: Skia/Vulkan; VCL: win
Locale: ja-JP (ja_JP); UI: ja-JP
Calc: threaded

1 Like

oDialog = CreateUnoDialog(DialogLibraries.Standard.Dialog1)の前に

    DialogLibraries.LoadLibrary("Standard")

があるとエラーが出ません。

com.sun.star.awt.PosSize.POSSIZEかなと思ったんですが、今回のケースはサイズ変更だけですので
com.sun.star.awt.PosSize.SIZEでいいようです。


意地悪な(AやIのみ)ケースでは余白が発生します。

1 Like

sabr0様、フォローありがとうございます。

DialogLibraries.LoadLibrary(“Standard”)

こちら、以前から確かに気になってたのですが、なくても動作するケースとエラーになるケースがある様ですね。
つけておいた方が良さそうですね。

su_do様、sabr0様

提案いただいた getPreferredSize の利用 ほぼ満足いくものでした。
1点 考慮が必要だったのは getPreferredSize を利用すると 紐つくDialogが無条件に表示されてしまう点でした。
しかも endExecute で消えないのです。
本処理途中で、他のメッセージ表示も想定したので。この想定外のDialog表示解消も必要となりました。
いろいろ考えた挙句、いささか力業ですが…以下の手順を踏みました
① 必要な CtlのSizeを getPreferredSize で求めた後 一旦 Dialogをdisposeして消す
※この部分だけだと表示に気づかない。心配した画面のちらつきも感じませんでした(私が鈍感なだけ…)
② ①で求めた Ctlの各Sizeを使って 表示するDialog および 配置するCltのModelの Size/Positionを設定
※この処理中で表示できない場合や補正する場合などのMsg表示をしたかった
※getPreferredSize でえられる情報は Pixel単位らしく(記述が見つからず) Modelへの設定は 単位変換(Pixel➡AppFontUnits)が必要みたい
③ ②で設定した CtlModelが配置された DialogModelでDialogCtlを再Create>再CreatePeer>Listener等の設定>execute() で表示

いくつかためしましたが、以前私が報告した方策と比べると
A.等倍/プロポーショナルいずれも高さは ほぼ追従できている
※メイリオが追従できるのが大きい!
B.等倍は幅も追従できているようだが、プロポーショナルで一部
大きな情報(下記)等ではすこしだけ折れ曲がる
※10%マージンを取ると用意したTestDataでは折れ曲がらなかった
C.getPreferredSize は Tabも考慮したSizeをかえしてくれてる(あたりまえか…)
D.参考ですが TextBox以外のLabelやButtonもcom.sun.star.awt.XLayoutConstrains(getPreferredSizeを含むI/F群)を持っていたので同様のSize調整ができてました。
※ためしていませんが 日付/時間/数字入力フィールド等も前述のI/F群の存在を確認しました

【Q_Taroが使用した大きな表示情報の始まり】
===============D_E_B_U_G============================
boxx_msg_calcSizPos最期(正常終了)
====================================================
Font  ::Nam:メイリオ【プロポーショナル】 Siz:18
====================================================
Title ::Ttl:〇 Siz(273/14) Pos(4/4)
====================================================
Icon  ::Icn:〇 Siz(29/29) Pos(4/22)
Icon  ::Typ:Crit FntSiz:36
====================================================
Messag::Msg:〇 Siz(240/29) Pos(37/22) Typ:Left----
====================================================
Button::Typ:OkOnly DefBtn:DefBtn1 Num:1
Button::[1]Siz(39/25) Pos(121/55)[2]Siz(--/--)/Pos(--/--)[3]Siz(--/--)/Pos(--/--)
====================================================
Dialog::MaxSiz:768/432 Siz(281/84) Pos(340/222)
====================================================
OKは処理続行、Cancelは終了
【Q_Taroが使用した大きな表示情報の終わり】

ともあれ、getPreferredSize利用と上記手順で当初の目的は達せられたように思います。
ありがとうございました。

2 Likes