Top > OOobbs > 53

OOobbs/53 Edit

  • サマリ: ドローページ上のオブジェクトにイベントを追加したい
  • 環境: Draw
  • 状態: 解決
  • 投稿者: 河井?
  • 投稿日: 2005-03-17 (木) 16:38:19

質問 Edit

シェープオブジェクト等には、addEventListener があり、イベント処理が追加できそうなので、以下のコードを書いて試してみました。動作状況としては、Draw 上に適当なシェープがあり、その中の特定のオブジェクトに"face"と名前をつけてあります。

REM  *****  BASIC  *****

Const TARGETNAME = "face"
Global oEventHandle As Object
Global oDoc As Object
Global oPage As Object
Global oTarget As Object
Global oNull As Object

'	イベントの追加
Sub AddEvent
	if IsNull(oEventHandle) then
		oDoc = ThisComponent
		oPage = GetDrawPageAllways(oDoc)
		for i=0 to oPage.getCount() -1
			oTarget = oPage.getByIndex(i)
			if    oTarget.supportsService(_
 "com.sun.star.drawing.FillProperties") or oTarget.supportsService(_
 "com.sun.star.drawing.Shape3DScene") then
				if oTarget.getName() = TARGETNAME then
					exit for
				end if
			end if
			oTarget = oNull
		next i
		if Not IsNull(oTarget) then
			oEventHandle = CreateUnoListener(_
 "OnEvent_", "com.sun.star.awt.XMouseListener")
			oTarget.addEventListener(oEventHandle)
		end if
	end if
End Sub

'	イベントの削除
Sub RemoveEvent
	if Not IsNull(oEventHandle) then
		for i=0 to oPage.getCount() -1
			oTarget = oPage.getByIndex(i)
			if oTarget.getName() = TARGETNAME then
				exit for
			end if
			oTarget = oNull
		next i
		if Not IsNull(oTarget) then
			oTarget.removeEventListener(oEventHandle)
		end if
	end if
End Sub

' TARGETに対するイベント処理
Sub OnEvent_mousePressed(oEvent)
	MsgBox "マウスが押された!"
End Sub
Sub OnEvent_mouseReleased(oEvent)
	MsgBox "マウスが離された!"
End Sub
Sub OnEvent_mouseEntered(oEvent)
	MsgBox "マウスが入った!"
End Sub
Sub OnEvent_mouseExited(oEvent)
	MsgBox "マウスが出た!"
End Sub
Sub OnEvent_disposing()
End Sub

' 対象ドキュメントの種類に応じた現在の DrawPage の取得
Sub GetDrawPageAllways(oDocument As Object) As Object
	'-- Draw or Impress
	if oDocument.supportsService(_
 "com.sun.star.drawing.DrawingDocument") or _
		  oDocument.supportsService(_
 "com.sun.star.presentation.PresentationDocument") then
		GetDrawPageAllways = oDocument.CurrentController.getCurrentPage()
		Exit Sub
	'-- Calc
	elseif oDocument.supportsService(_
 "com.sun.star.sheet.SpreadsheetDocument") then
		GetDrawPageAllways = _
 oDocument.CurrentController.ActiveSheet.getDrawPage()
		Exit Sub
	'-- Writer
	elseif oDocument.supportsService(_
 "com.sun.star.text.TextDocument") then
		GetDrawPageAllways = _
 oDocument.CurrentController.Model.getDrawPage()
		Exit Sub
	'-- other, DB?
	else
		' Nothing
	end if
End Sub

エラーにこそなりませんが、反応もしません。マウス以外でも対応出来るイベントがあれば、何かに使えそうなのですが。

回答 Edit

  • リスナーはややこしいのと,奥が深いので難しいのです。addEventListener メソッドで勝手に om.sun.star.awt.XMouseListener を追加していますが,オブジェクトがオブジェクトがサポートしているリスナーしか動作しません。なので,ここでは勝手にマウスリスナーを追加することはできません。

ここで addEventListener メソッドを提供しているインターフェースは,com.sun.star.lang.XComponent なのでこのメソッドが追加することのできるリスナーしか使用できません。使用できるのは,com.sun.star.lang.XEventListener です。

はっきり言うと,この com.sun.star.lang.XComponent と com.sun.star.lang.XEventListener は全てのオブジェクトのためのインターフェースです。com.sun.star.lang.XComponent の addEventListener はそのオブジェクトがリスナーを使用できる一般的なオブジェクトになるようにするために備えるインターフェースです。ほぼ全ての OOo のオブジェクトがこのオブジェクトを備えています。自分で Java などでオブジェクト (サービスによるインターフェース) を作成するときにも継承したりします。また,com.sun.star.lang.XEventListener は全てのリスナーが必要とするインターフェースで,オブジェクトがリスナーになるためのインターフェースと考えられているものでリスナーに一般的かつ必要なものです。

上記のとおりなので,機能を持たない (作成と追加はできる) がリスナーしか作成できません。

このシェープオブジェクトに対して addEventListener メソッドを提供しているインターフェースがなぜ com.sun.star.lang.XComponent なのかということについては,シェープオブジェクトのプロパティー Dbg_SupportedInterfaces をみてもらえると分かると思います。また,Dbg_Methodsdispose, addEventListener, removeEventListener が並んでいることからもそれと分かります。

追加しても面白くない com.sun.star.lang.XEventListener を使った例を示しておきます。作成時に呼ばれるだけで何の動作についてもリスナーとして働きません。

示していただいた例と違って選択中のオブジェクトにリスナーを追加するだけの例です。なので,シェープを選択してコードを実行してください。リスナーの削除については記述していませんので,リスナーを削除するには一度 OpenOffice.org を終了してください。

Global oEventListener As Object

Sub Main
Dim oDoc As Object
Dim oSelection As Object
  oDoc = ThisComponent
  oSelection = oDoc.getCurrentController().Selection
  oEventListener = CreateUnoListener(_
         "EventListener_","com.sun.star.lang.XEventListener")
  oSelection.com_sun_star_lang_XComponent_addEventListener(oEventListener)
End Sub

Sub EventListener_disposing(oEvt)
  MsgBox oEvt.Dbg_Properties
  MsgBox oEvt.Source.Dbg_Properties
End Sub
  • はにゃ?? 2005-03-17 (木) 23:09:43
  • いつもながら、素早い回答と詳細な解説ありがとうございます。シェープオブジェクトに有効なイベントを追加して動的な動きを作り出すことは出来ないのですね。フォームのラベルをぴったりオブジェクトにかぶせて対応してみます。 -- 河井? 2005-03-18 (金) 09:50:38
  • シェープオブジェクトにイベントが張り付かないので、フォーム上の透明なラベルを配置してイベントを割り当てることで代用してみました。こういう状態を選択したオブジェクトに対して自動的に生成(選択したオブジェクトに対するイベント処理付きの透明なラベル)させようと思うと実現はできるかもしれませんが、大変そうですね・・・。(catchさんからの依頼物?だったりします。)fileイベントテスト02.sxd -- 河井? 2005-03-18 (金) 15:41:50
  • えっと,

作成には,

  • 選択中のオブジェクトの位置とサイズの取得
  • フォームのテキストラベルの追加
  • テキストラベルへのイベント設定
  • イベントのためのプロシージャ

が必要です。

これら四つの方法が分かっているので途中までマクロを書いたのですが, どこまでをマクロで自動生成させればいいでしょうか?各イベントに対するマクロのためのプロシージャの外形作成とその設定ぐらいでしょうか?実際の処理はイベントごとに変わってきますよね?マクロのプロシージャ名の管理が面倒ですがモジュールを増やすことで対処しましょうか。

  • はにゃ?? 2005-03-19 (土) 01:21:49
  • 作成していただいた上記の添付ファイルの例と同じような形で動作するものを生成するように作成してみます。 -- はにゃ?? 2005-03-19 (土) 01:28:12
  • さすが「はにゃ」さん、挑戦されているのですね!!一番気になっていたのが「テキストラベルへのイベント設定」なのですが、マクロ上で動的にイベント設定を割り当てた場合とフォームのコントロールからイベントプロパティタブで割り当てた場合の違いです。「イベントプロパティタブで割り当てた状態」が作り出せると他にも有効利用が出来そうです。 -- 河井? 2005-03-19 (土) 06:08:51
  • イベントの設定ですが,上記の場合ではマクロを使って「イベントプロパティータブで割り当てたときと同じ状態」を作り出します。マクロの実行後にイベントタブを確認すると,手動で行ったときと同じように表示されています。 -- はにゃ?? 2005-03-19 (土) 22:13:39
  • 周辺MLも拝見しましたが、マクロで出来るのですね。はにゃさんが作られているのでしたら、出来るのを楽しみに待つこととします。 -- 河井? 2005-03-20 (日) 08:06:02
  • "イベントテスト02.sxd" とほぼ同じようになるように作成して,機能的にはほぼ完成しました。あとは,エラー処理などです。

また,一般的なマクロに仕立て上げるのであれば色々と変更しなければいけませんが ...

  • はにゃ?? 2005-03-20 (日) 09:39:39
  • ということで,コードを示します。

使い方は次のとおりです。fileTEST-1.sxd

  • Draw ドキュメントの Standard ライブラリの Module1 に以下のマクロを記述します。
  • ドローシェープで図形を描いた後に,"face" としてシェープに名前をつけておきます。
  • そのシェープを選択状態でマクロの "Main" を実行してください。
REM  *****  BASIC  *****
Sub Main
Dim oDoc As Object
Dim oDrawPage As Object, oController As Object
Dim oForms As Object, oForm As Object
Dim oLabelModel As Object, oSelection As Object
Dim nObjects As Long
Dim aSize As New com.sun.star.awt.Size
Dim aPosition As New com.sun.star.awt.Point
Dim aEvents(3) As New com.sun.star.script.ScriptEventDescriptor
Dim sLibName As String, sModName As String
  sLibName = "Standard"
  sModName = "Module2"
  oDoc = ThisComponent
  oController = oDoc.getCurrentController()
  oSelection = oController.getSelection()'.getByIndex(0)
  If NOT (oSelection.ImplementationName = "SvxShapeCollection") Then
    Exit Sub
  End If
  oSelection = oController.getSelection().getByIndex(0)
  oDrawPage = oController.getCurrentPage()
  oForms = oDrawPage.getForms()
  If NOT oForms.hasElements Then
    oForm = oDoc.createInstance("com.sun.star.form.component.Form")
    oForms.insertByName("Standard",oForm)
  End If
  oForm = oForms.getByIndex(0)
  nObjects = oForm.getCount() ' number of existing objects on the form
  With aEvents(0) 'Mouse inside
    .ListenerType = "XMouseListener"
    .EventMethod = "mouseEntered"
    .AddListenerParam = ""
    .ScriptType = "StarBasic"
    .ScriptCode = "document:Standard.Module2.Event_mouseInside"
  End With
  With aEvents(1) 'Mouse button pressed
    .ListenerType = "XMouseListener"
    .EventMethod = "mousePressed"
    .AddListenerParam = ""
    .ScriptType = "StarBasic"
    .ScriptCode = "document:Standard.Module2.Event_mousePressed"
  End With
  With aEvents(2) 'Mouse button released
    .ListenerType = "XMouseListener"
    .EventMethod = "mouseReleased"
    .AddListenerParam = ""
    .ScriptType = "StarBasic"
    .ScriptCode = "document:Standard.Module2.Event_mouseReleased"
  End With
  With aEvents(3) 'Mouse outside
    .ListenerType = "XMouseListener"
    .EventMethod = "mouseExited"
    .AddListenerParam = ""
    .ScriptType = "StarBasic"
    .ScriptCode = "document:Standard.Module2.Event_mouseExited"
  End With
  
  aSize = oSelection.getSize()
  aPosition = oSelection.getPosition()
  
  oControl = oDoc.createInstance("com.sun.star.drawing.ControlShape")
  oControl.setSize(aSize)
  oControl.setPosition(aPosition)
  oLabelModel = oDoc.createInstance("com.sun.star.form.component.FixedText")
  oLabelModel.Label = Chr(10)
  
  oControl.setControl(oLabelModel)
  
  oDrawPage.add(oControl)
  nObjects = oForm.getCount()
  oForm.registerScriptEvents(nObjects-1,aEvents())
  oLabelModel.Label = ""
  
  AddCode(oDoc,sLibName,sModName,GenerateCode)
End Sub


Function GenerateCode() As String
Dim sCode As String, sLF As String, sTab As String
Dim sMouseInside As String, sMousePressed As String
Dim sMouseReleased As String, sMouseExited As String
Dim sGetHasByName As String, sGetDrawPageAllways As String
  sLF = Chr(10)
  sMousePressed = _
    "Sub Event_mouseInside()" & sLF & _
    "Dim oShape As Object" & sLF & _
    "  oShape = GetHasByName(TARGETNAME)" & sLF & _
    "  If NOT IsNull(oShape) Then" & sLF & _
    "    oShape.FillColor = RGB(255,0,0)" & sLF & _
    "  End If" & sLF & _
    "End Sub" & sLF
  sMouseReleased = _
    "Sub Event_mousePressed()" & sLF & _
    "Dim oShape As Object" & sLF & _
    "  oShape = GetHasByName(TARGETNAME)" & sLF & _
    "  If NOT IsNull(oShape) Then" & sLF & _
    "    oShape.FillColor = RGB(0,184,255)" & sLF & _
    "  End If" & sLF & _
    "End Sub" & sLF
  sMouseInside = _
    "Sub Event_mouseReleased()" & sLF & _
    "Dim oShape As Object" & sLF & _
    "  oShape = GetHasByName(TARGETNAME)" & sLF & _
    "  If NOT IsNull(oShape) Then" & sLF & _
    "    oShape.FillColor = RGB(255,255,102)" & sLF & _
    "  End If" & sLF & _
    "End Sub" & sLF
  sMouseExited = _
    "Sub Event_mouseExited()" & sLF & _
    "Dim oShape As Object" & sLF & _
    "  oShape = GetHasByName(TARGETNAME)" & sLF & _
    "  If NOT IsNull(oShape) Then" & sLF & _
    "    oShape.FillColor = RGB(0,184,255)" & sLF & _
    "  End If" & sLF &_
    "End Sub" & sLF
  sCode = "REM  *****  BASIC  *****" & sLF & sLF
  sCode = sCode & "Const TARGETNAME = " & """" & "face" & """" & sLF & sLF
  sCode = sCode & sMousePressed & sLF
  sCode = sCode & sMouseInside & sLF
  sCode = sCode & sMouseExited & sLF
  sGetHasByName = _
    "Sub GetHasByName(sName As String) As Object" & sLF & _
    "Dim oNull As Object, oDoc As Object" & sLF & _
    "Dim oPage As Object, oTarget As Object" & sLF & _
    "  oDoc = ThisComponent" & sLF & _
    "  oPage = GetDrawPageAllways(oDoc)" & sLF & _
    "  for i=0 to oPage.getCount() -1" & sLF & _
    "    oTarget = oPage.getByIndex(i)" & sLF & _
    "    if oTarget.supportsService(" & """" & "com.sun.star.drawing.FillProperties" & """" & ") or oTarget.supportsService(" & """" & "com.sun.star.drawing.Shape3DScene" & """" & ") then" & sLF & _
    "      if oTarget.getName() = sName then" & sLF & _
    "        exit for" & sLF & _
    "      end if" & sLF & _
    "    end if" & sLF & _
    "    oTarget = oNull" & sLF & _
    "  next i" & sLF & _
    "  GetHasByName = oTarget" & sLF & _
    "End Sub" & sLF
  sGetDrawPageAllways = _
    "Sub GetDrawPageAllways(oDocument As Object) As Object" & sLF & _
    "  if oDocument.supportsService(" & """" & "com.sun.star.drawing.DrawingDocument" & """" & ") or _" & sLF & _
    "    oDocument.supportsService(" & """" & "com.sun.star.presentation.PresentationDocument" & """" & ") then" & sLF & _
    "    GetDrawPageAllways = oDocument.CurrentController.getCurrentPage()" & sLF & _
    "    Exit Sub" & sLF & _
    "  elseif oDocument.supportsService(" & """" & "com.sun.star.sheet.SpreadsheetDocument" & """" & ") then" & sLF & _
    "    GetDrawPageAllways = oDocument.CurrentController.ActiveSheet.getDrawPage()" & sLF & _
    "    Exit Sub" & sLF & _
    "  elseif oDocument.supportsService(" & """" & "com.sun.star.text.TextDocument" & """" & ") then" & sLF & _
    "    GetDrawPageAllways = oDocument.CurrentController.Model.getDrawPage()" & sLF & _
    "    Exit Sub" & sLF & _
    "  else" & sLF & _
    "  end if" & sLF & _
    "End Sub" & sLF
  sCode = sCode & sGetHasByName & sLF
  sCode = sCode & sGetDrawPageAllways
  GenerateCode = sCode
End Function


Sub AddCode(oLocDoc As Object, sLibName As String, sModName As String, sCode As String)
Dim oBasicLib As Object
Dim oLib As Object, oModule As Object
  oBasicLib = oLocDoc.BasicLibraries
  If oBasicLib.hasByName(sLibName) Then
    If NOT oBasicLib.isLibraryPasswordProtected(sLibName) Then
      If NOT oBasicLib.isLibraryReadOnly(sLibName) Then
        oLib = oBasicLib.getByName(sLibName)
        If oLib.hasByName(sModName) Then
          oLib.removeByname(sModName)
          oLib.insertByName(sModName,sCode)
        Else
          oLib.insertByname(sModName,sCode)
        End If
      End If
    End If
  End If
End Sub

なんだか無駄に長くなっていますが,割り当てるイベントのためのマクロコードをマクロの文字列として記述しようとしているためです。 Function GenerateCode() As String 中の処理に関しては河井さんの "イベントテスト02.sxd" から処理を借りさせていただきました。

最後の Sub AddCode でドキュメントの "Standard" ライブラリの "Module2" にイベントのためのコードを保存しています。これに関しては OOoBasic/Generic/storeinmodule のページで取り上げたものです。

  • はにゃ?? 2005-03-20 (日) 09:41:51
  • ScriptEventDescriptor についてまとめる前に OOoBasic/Generic/ScriptEventDescriptor に少し調べたことを書きました。 -- はにゃ?? 2005-03-20 (日) 11:44:55
  • 素晴らしいですね!「選択したドローオブジェクトにイベントを貼り付ける」を実現出来た事になります!(テキストラベルを使っていますが、挙動的にはこれで充分かと思います。)処理を一般化すれば、Impress 向けの便利ツールとなりますね。コードを生成する前の時点でオブジェクトの属性をあらかじめ調べておけば、私の書いている処理の大半は省略して属性のみ変更する位のコード生成でよさそうです。この質問は解決にしておきますね。 -- 河井? 2005-03-21 (月) 11:22:16


Attach file: fileイベントテスト02.sxd 1009 download [Information] fileTEST-1.sxd 1049 download [Information]

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