Top > OOoBasic > Dialog > Example10
*モードレスダイアログ [#c71c6f60]

ダイアログエディタで作成して利用するダイアログはモダルなダイアログになってしまいます。モダルなダイアログではユーザーが閉じるまで下に表示されているドキュメントなどが利用できません。ダイアログと開いた元のウィンドウを両方同時に使用できません。

モードレスダイアログでは両方同時に利用できます。しかし、ダイアログエディタで作成したダイアログをモードレスダイアログにする方法はありません。その代わり、コードを書くことでモードレスダイアログを作成できます。

#contents

結構大変です。また、普通のダイアログと違いいくつか制約があります。
-Step が使えない
-ステータスバーのような部分が表示されるが利用できない
**1.単純なモードレスダイアログ [#s14e6e65]

コントロールを配置していないダイアログです。ここではドキュメントのサブフレームとして表示されるように作成します。

&ref(modelessdialog-1.png,,60%);

&ref(modelessdialog-1.odt);

コードの最後で setVisible(True) としているところを execute とするとモダルダイアログになります。
   oWindow.setVisible(True)
   'oWindow.execute()
 End Sub

また、ウィンドウの作成は以下のようになります。"dialog" を "window" に変えるとウィンドウになります。

 Function CreateNewWindow( _
   oToolkit,oParent,nX,nY,nWidth,nHeight) As Object
   aRect = CreateUnoStruct("com.sun.star.awt.Rectangle")
   With aRect
     .X = nX
     .Y = nY
     .Width = nWidth
     .Height = nHeight
   End With
   aWinDesc = CreateUnoStruct("com.sun.star.awt.WindowDescriptor")
   With aWinDesc
     .Type = com.sun.star.awt.WindowClass.TOP
     .WindowServiceName = "dialog"
     .ParentIndex = -1
     .Bounds = aRect
     .Parent = oParent
     .WindowAttributes = _
       com.sun.star.awt.WindowAttribute.MOVEABLE + _
       com.sun.star.awt.WindowAttribute.CLOSEABLE
   End With
   CreateNewWindow = oToolkit.createWindow(aWinDesc)
 End Function
**2.コントロールを配置する [#c374d182]

1で作成したダイアログは普通のダイアログとは違うため普通にコントロールを配置できません。コントロールを配置するためにコントロールコンテナを利用します。

&ref(modelessdialog-2.png,,80%);

&ref(modelessdialog-2.odt);

ラベル、テキストボックス、ボタンを配置しました。ボタンに動作を割り当てるにはアクションリスナーを利用します。また、ボタンが複数あるときには ActionCommand でボタンを区別すればアクションリスナーは一つしか作成する必要ありません。

コントロールの作成には次の関数を利用しました。

 Function CreateControl(sType,nX,nY,nWidth,nHeight,sNames,vValues) As Object
   oCtrl = CreateUnoService("com.sun.star.awt.UnoControl" & sType)
   oCtrlModel = CreateUnoService("com.sun.star.awt.UnoControl" & sType & "Model")
   oCtrlModel.setPropertyValues(sNames,vValues)
   oCtrl.setModel(oCtrlModel)
   oCtrl.setPosSize(nX,nY,nWidth,nHeight,com.sun.star.awt.PosSize.POSSIZE)
   CreateControl = oCtrl
 End Function

ボタンのためのリスナーではコントロールコンテナ oCont 変数からテキストエディットを取得していますが、この変数は Global 変数にしておく必要があります。
 Sub ButtonListener_actionPerformed( oEv )
   sCmd = oEv.ActionCommand
   If sCmd = "btn" Then
     msgbox oCont.getControl("edit").getText()
   End If
 End Sub
 Sub ButtonListener_disposing( oEv )
 End Sub

**3.XSelectionChangeListener [#t14e3d2d]

せっかくのモードレスダイアログなのでドキュメントとダイアログを同時に利用します。今回はドキュメントの選択範囲の変更を調べられるように XSelectionChangeListener を利用します。

&ref(modelessdialog-3.odt);

安定したものにするためにいくつか注意する点があります。
+サブフレームを閉じるときにリスナーを削除する
+ドキュメントファイルを閉じる前にリスナーを削除する
+選択範囲オブジェクトがサポートしているサービスを調べる
+selectionChanged が実行中のときには実行されないようにする

1、2 を怠るとドキュメントを閉じるときに OOo がクラッシュします。ドキュメントまたはサブフレームを閉じるときにリスナーを削除する必要があるので XCloseListener を利用します。

 Sub RemoveListeners()
   oFrame.removeCloseListener(oListeners(1))
   oParentFrame.removeCloseListener(oListeners(1))
   oParentFrame.Controller.removeSelectionChangeListener(oListeners(2))
 End Sub
 
 Sub DocClose_queryClosing( oEv, oOwnership )
 End Sub
 Sub DocClose_notifyClosing( oEv )
   RemoveListeners()
 End Sub
 Sub DocClose_disposing( oEv )
 End Sub

3、4 は以下のようにします。実行中のときに bUpdated で実行を規制します。また、オブジェクトがサポートしているサービスを supportsService で調べています。選択範囲はテキスト範囲コンテナ、図形描写コンテナなどさまざまなのでチェックする必要があります。

 Sub DocSelection_selectionChanged( oEv )
   If NOT bUpdated Then Exit Sub
   bUpdated = False
   oSelection = oEv.Source.getSelection()
   If oSelection.supportsService("com.sun.star.text.TextRanges") Then
     If oSelection.getCount() > 0 Then
       oRange = oSelection.getByIndex(0)
       sTxt = oRange.getString()
       oCont.getControl("edit").setText(sTxt)
     End If
   End If
   bUpdated = True
 End Sub
 Sub DocSelection_disposing( oEv )
 End Sub

oEv.Source で取得できるのはドキュメントのコントローラです。ThisComponent.getCurrentController() としたときと同じインターフェースになります。

Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes