How to properly code a broadcaster and listener in LO Basic

I have read Pitonyak’s section on listeners in OOo Macros Explained, and it left me bewildered and confused (but bless his heart for taking the time to write such a comprehensive document on OOo Basic). Unfortunately, I’m quite new at coding in OOo Basic (and coding in general) and I’m trying to learn on the fly (by doing). Therefore, much of his explanation went zinging over my head.

That said, here’s what I’m trying to accomplish:

I’m writing a macro contained within in a Base form. In this macro, I have several image buttons that when clicked pass a text string to a textbox via a short sub routine that is triggered when the mouse button is pressed on the image button. Each of these image buttons have their own unique text string. At times, I will need to concatinate two of these text strings together (originating from different buttons).

The problem is that I don’t know in what order the buttons will be pushed, so I need the macro to detect when a second (or third, fourth, fifth, etc) is pushed and add the string associated with that button to the growing text string. Therefore, I need the macro to “listen” for one of the image buttons to be pushed (I’m assuming the image button would be the broadcaster), and when detected by the listener, pass the detected button’s associated text string to the subroutine that is building the concatinated text string.

When I read Pitonyak’s statement, “Knowing which broadcaster to use is not always an easy task. It requires understanding how OOo is designed; this comes with experience.” I knew i was in trouble.

If someone would be kind enough to show me some example code that is a possible solution for the above, or point me toward a tutorial regarding this topic that is slanted more toward the beginner, I would be most appreciative.

Cheers.

docbda

OK. I’ve limited experience with this but have some info for you. First is the code from Pitonyak. This gets you the methods you need to code. Copy this code:

   Sub InspectListenerMethods
      Dim sPrefix$
      Dim sService$
      Dim vService
      sPrefix = "sel_change_"
  '	sService = "com.sun.star.view.XSelectionChangeListener"
  '	sService = "com.sun.star.lang.XEventListener"
  '	sService = "com.sun.star.awt.XMenuListener"
   sService = "com.sun.star.awt.XKeyHandler"
  '	sService = "com.sun.star.awt.XButton"
   vService = CreateUnoListener(sPrefix, sService)
   DisplayDbgInfoStr(vService.dbg_methods, ";", 35, "Methods")
  End Sub
Sub DisplayDbgInfoStr(sInfo$, sSep$, nChunks, sHeading$)
Dim aInfo()
 'Array to hold each string
Dim i As Integer
 'Index variable
Dim j As Integer
'Junk integer variable for temporary values
Dim s As String
'holds the portion that is not completed
s = sInfo$
j = InStr(s, ":")
'Initial colon
If j > 0 Then Mid(s, 1, j, "") 'Remove portion up to the initial colon
	Do
		aInfo() = Split(s, sSep$, nChunks)
'Split string based on delimiter.
		s = aInfo(UBound(aInfo()))
 'Grab the last piece. Contains
		If InStr(s, sSep$) < 1 Then
 'the rest if there were too many.
			s = ""
 'If there were not, then clear s.
		Else
'If there was a delimiter then
			ReDim Preserve aInfo(nChunks - 2)
'change array dimension to
		End If
'remove the extra last piece.
		For i = LBound(aInfo()) To UBound(aInfo())'Look at each piece to remove
			aInfo(i) = Trim(aInfo(i))
'leading and trailing spaces.
			j = InStr(aInfo(i), CHR$(10))
'Some have an extra
			If j > 0 Then Mid(aInfo(i), j, 1, "") 'new line that should be removed.
		Next
		MsgBox Join(aInfo(), CHR$(10)), 0, sHeading$
	Loop Until Len(s) = 0
  End Sub

Running the macro InspectListenerMethods will display the methods you need to incorporate into your code. sService is the the only thing you need to modify. It is currently set for XKeyHandler with others commented out. Easier for later examination. So if you run this three items need definition even if they don’t do anything (queryInterface can be ignored)- disposing, keyPressed and keyReleased. Knowing that, here is my key handler(working model):

   global oXKeyHandler as object
   sub sStartXKeyHandler
       if isNull(oXKeyHandler) then 'only if not jet running
           oXKeyHandler = CreateUnoListener("KeyHandler_", "com.sun.star.awt.XKeyHandler")
           ThisComponent.CurrentController.AddKeyHandler(oXKeyHandler)
       endif
   end sub

sub sStopXKeyHandler
    if not IsNull(oXKeyHandler) then 'only if still running
        ThisComponent.CurrentController.removeKeyHandler(oXKeyHandler)
        oXKeyHandler = Nothing 'To know later this handler has stopped.
    end if
end sub

sub XKeyHandler_Disposing(oEvent)
end sub

function KeyHandler_KeyPressed(oEvent) as boolean
 'The entire objective of the key handler:
 'On the menu, when the 'Enter' key is pressed
 'don't move to the next field(cancel)
	If (oEvent.KeyCode = 1280) Or (oEvent.KeyCode = 1284) Then
        KeyHandler_KeyPressed = True 'cancel KeyPressed
	Else
        KeyHandler_KeyPressed = False 'cancel KeyPressed
	End If
End function

function KeyHandler_KeyReleased(oEvent) as boolean
 'but when the 'Enter' key is released,
 'execute the 'Key Released' event assigned in the control
	If oEvent.KeyCode = 1280 Then
        KeyHandler_KeyReleased = False 'cancel KeyReleased
    Else
	    KeyHandler_KeyReleased = True 'cancel KeyReleased
    End If
end function

This was used in a menuing form in which I wanted the normal function of the Enter key to be overridden (next field & select it).

As you can see, XButton is one of the service selections. Start there and try Pitonayaks’ book again. This isn’t the easiest of sections.

ADDITIONAL INFO!!

Not sure why you are taking this approach. I should have realized this earlier. I’ve eluded to this in one of our previous posts but let you lead me astray (my fault not yours) with your mention of listeners & such. If your looking to see which button is doing the calling you can just set a variable. I’ve attached a (dumb) sample but it does display what I mean. The button pushed will only record the answer once and a different button pushed will add to the answer. PBTest.odb

1 Like

Whoa!!! Thanks a ton. Let me digest this, and I’ll get back to you with the questions I’m sure to have.
docbda

Ratslinger, Here’s what I’ve done so far: 1) copied both pieces of code into the same module. 2) identified where sService is set for XKeyHandler. I’m not sure how I need to modify this. 3) I identified _Disposing (which was an empty sub routine), _KeyPressed (function that stated if keys 1280 or 1284 were pressed, then KeyHandler_KeyPressed was True), and _KeyRealeased (function that says if oEvent.KeyCode = 1280 then _KeyReleased is false. You state that these items need definitions.

I’m guessing that I need to add some dummy code to disposing, and replace your If Then Else statements in KeyPressed and KeyReleased with more dummy code, but I’m not sure how to go about this. I apologize for my ignorance.

I see where you commented out sService = XButton. Not sure how I “start there and try Pitonayak’s book again.” Remember … super noob here…

By running InspectListenerMethods exactly as presented will display what methods were needed for my key handler (less of course the starting & stopping of the handler itself). This explains just what methods I needed to code as can be seen in my KeyHandler section. Now the harder part. Comment out the sService XKeyHandler line and remove the comment from the XButton line & run InspectListenerMethods again. These are probably the methods you will need for your handler.

1 Like

I say probably because it is not always clear cut as to which service to use. That’s why I have various commented lines. Looking at different services to find ones I need. Disposing is empty because my stop handler does all I need. Disposing can do additional but not needed here. However, it is a required method thus it is empty. That is why I say go through all this then go back to the book. It should add some clarity.

When I first tried to run this I had a run-time error. I just tried it again, and it worked fine. The methods you needed to code were:
SbxEMPTY queryInterface ( SbxOBJECT )
SbxVOID disposing ( SbxOBJECT )
SbxBOOL keyPressed ( SbxOBJECT )
SbxBOOL keyReleased ( SbxOBJECT )

Now for step 2…

Result:
SbxEMPTY queryInterface ( SbxOBJECT )
SbxVOID addActionListener ( SbxOBJECT )
SbxVOID removeActionListener ( SbxOBJECT )
SbxVOID setLabel ( SbxSTRING )
SbxVOID setActionCommand ( SbxSTRING )
…OK, back to Pitonyak
I’ll be in touch

Please see additional info in my answer!!!

That is a much easier solution!!! Although, at some point I need to learn how to code the listener too. I might give it a try anyway just to complete this post for the next guy that comes along that needs some help in this regard. Thanks, as always.

That would be my suggestion. Store this away for when you have time. I know it was helpful to me. And actually the post has the complete code for a Key Handler.