Ask Your Question

Dialog Modal with Basic IDE, Non-Modal with documents [closed]

asked 2016-09-30 23:22:13 +0200

mark_t gravatar image

updated 2020-09-13 00:30:30 +0200

Alex Kemp gravatar image

I've noticed that if I start a dialog from a macro located in "My Macros & Dialogs", running the macro from the Basic IDE (for example using ctrl-shift-F8), then the dialog started is modal with the basic IDE and not with the active document.

This can then be a problem trying to debug the macros called from events triggered by controls in the dialog.

I can work around this problem by first setting the document active, I'm using the following to set the current document active.

StarDesktop.loadComponentFromURL(ThisComponent.URL,"_default",0,array()) ' sets focus to the document'

Is there a better method than this to set the active focus to ThisComponent?

Edit. Slightly better method to change focus from the Basic IDE to the document when starting a modal dialog. Either the DoEvents or a Wait seems to be needed to avoid the dialog still being attached to the Basic IDE.


Also is there some similar method that could create a dialog that is non-modal with documents but without it being modal with the basic IDE?

I saw this prior question how-to-make-non-modal-dialog answered by @pierre-yves-samyn, but wondered if the above behaviour could lead to some other method.

Attached contains sample dialog and macro. Untitled 29.ods

Note the macro module and dialog needs to be copied to "My Macros & Dialogs" to show the problem.

I'm using LibreOffice x64 on Windows 8.1.

Edit to add code for fake non-modal dialog created using IDE and setting the dummy document invisible. Note the dialog is not shown in the windows task bar and can become hidden behind other windows. Also reference to ThisComponent will refer to the hidden dummy document.

Sub ShowHiddenDocDialog

    Dim oDummyDoc As Object
    Dim oController As Variant

    oDummyDoc = StarDesktop.loadComponentFromURL("private:factory/scalc", "_default", 0, array())
    oController = oDummyDoc.CurrentController

    DoEvents    '   Wait for the new document to be activated'

    MySampleDialog = CreateUnoDialog(DialogLibraries.Standard.DocIdentify)

    oController.Frame.ContainerWindow.Visible = False


End Sub
edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by Alex Kemp
close date 2020-09-13 00:30:49.989493

2 Answers

Sort by » oldest newest most voted

answered 2016-10-01 02:25:12 +0200

Ratslinger gravatar image

updated 2016-10-01 03:59:39 +0200

Hello @mark_t

Hopefully I understand all your questions. First, access to controls. I do this by setting the dialog as a global object.

Global oHatchDialog As Object

Sub DisplayHatchDialog
Dim oUndoManager As Variant
Dim isLocked as Boolean
Dim oSheet As Object
oUndoManager = ThisComponent.getUndoManager()
oSheet = ThisComponent.CurrentController.ActiveSheet
Globalscope.BasicLibraries.LoadLibrary( "CalcHatchCellsLib" )
oHatchDialog = CreateUnoDialog(DialogLibraries.CalcHatchCellsLib.getByName("HatchDialog"))
oHatchDialog.GetControl("HatchCountDisplay").Text = "Hatch Cells Applied = " & CountHatchCells
End Sub

The in other routines I then access the controls as such:

    oHatchDialog.GetControl("TextMessage").Text = "Ready for Processing"
oHatchDialog.GetControl("HatchCountDisplay").Text = "Hatch Cells Applied = " & CountHatchCells

Now for modal & non-modal. Typically a dialog is modal. Since you're looking for a non-modal, I believe you are looking for something other than using the setVisible method - see my sample here. What sets this as non-modal (actually modal to desktop) is

    setProperties(oDlgModel, Array("PositionX", 50, "PositionY", 50,_
            "Width", iDlgWidth, "Height", iDlgHeight, "Title",_
            "Budget System - Average Expenses", "DesktopAsParent", True))

the desktopAsParent property. For properties see this link.

Hope this is what you are looking for.

Edit: Took a look at your sample. Made a couple of minor changes. Will display what is entered in Text line. Use Close button to end dialog.


edit flag offensive delete link more


Thanks @Ratslinger, for the second part of my question I think the property "DesktopAsParent" is what I was looking for to create a non modal dialog without resorting to the setVisible method (which looks like it needs to keep the macro running while the dialog is open). I'll test it out and post back later. I did find one other method, also quite messy, which was to create a new document, create the dialog and then set the new document invisible before executing the dialog.

mark_t gravatar imagemark_t ( 2016-10-01 04:19:18 +0200 )edit

In some cases I probably do want the dialog to be modal, in those cases the first part of my question can still be a problem during debug as the dialog becomes modal with the basic IDE. I think I found a slightly better workaround which I'll edit in the question.

mark_t gravatar imagemark_t ( 2016-10-01 04:22:55 +0200 )edit

I had seen the global object method to access the controls, but I thought there was a possible problem if more than one dialog of the same type was open in different documents. It doesn't seem difficult to use the oEvent object passed to the event handlers of controls to find oEvent.Source.Context to access other controls of the dialog.

mark_t gravatar imagemark_t ( 2016-10-01 04:35:24 +0200 )edit

Currently I have two modal dialogs opened and working on two different .ods files. No problem. Also opened the sample I sent you back (using global) from the IDE and read cell data. Also no problem.

Ratslinger gravatar imageRatslinger ( 2016-10-01 04:55:05 +0200 )edit

I tried adding "MySampleDialog.Model.DesktopAsParent = True" using a dialog built by the IDE but this still opens the dialog as modal. Perhaps it only works when the dialog is built by the macro. I'll try this sometime over the weekend.

mark_t gravatar imagemark_t ( 2016-10-01 05:42:36 +0200 )edit

The non-modal sample I pointed you to works as non-modal from the IDE. Also be aware in this case any code changes can be made but not saved or effective until the dialog closes. I do not know of any way around changing code and testing with it with a dialog open - either modal or non-modal. The dialogs' code is executing while it is open preventing any code changes to be saved.

Ratslinger gravatar imageRatslinger ( 2016-10-01 06:13:03 +0200 )edit

Building the Dialog from Basic macro and setting ".DesktopAsParent = True" during creation of the model is working to create the Dialog as Non-Modal.

mark_t gravatar imagemark_t ( 2016-10-01 20:48:40 +0200 )edit

If I create two separate dialogs they are non-modal with documents and the basic IDE, but seem to be modal with each other, in that only the last dialog created can be activated. I had similar issue with modal dialogs. I'll try with Linux in case this is a windows issue and maybe post a new question when I can create a simple demo.

mark_t gravatar imagemark_t ( 2016-10-01 21:04:38 +0200 )edit

answered 2016-10-01 21:19:24 +0200

mark_t gravatar image

Code based on @Ratslinger answer, creates the dialog from basic macro setting DesktopAsParent.

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

Option Explicit 

Sub ID_CreateDialog

    Dim oDlgModel As Variant
    Dim sDialog As String

    sDialog = "DocIdentify"

    Dim oComponents As Variant
    Dim oDoc As Variant

    oDlgModel = CreateUnoService("")
    With oDlgModel
        .Name = sDialog
        .Title = "Doc Identify"
        .PositionX = 170
        .PositionY = 70
        .Width = 190
        .Height = 40
        .DesktopAsParent = True
    End With

    Dim oModel As Variant
    oModel = oDlgModel.createInstance("")
    With oModel
        .TabIndex = 0
        .Name = "TextField1"
        .PositionX = 10
        .PositionY = 6
        .Width = 170
        .Height = 12
    End With
    oDlgModel.insertByName(oModel.Name, oModel)

    oModel = oDlgModel.createInstance("")
    With oModel
        .TabIndex = 1
        .Name = "CommandButton1"
        .Label = "Identify Active Document"
        .PositionX = 55
        .PositionY = 22
        .Width = 80
        .Height = 12
    End With
    oDlgModel.insertByName(oModel.Name, oModel)

    Dim oDlg As Variant
    oDlg = CreateUnoService("")

    Dim oListener As Variant
    Dim oControl As Variant
    oListener = CreateUnoListener("IDButton_", "")
    oControl = oDlg.getControl("CommandButton1")

    Dim oWindow As Variant
    oWindow = CreateUnoService("")

    oDlg.createPeer(oWindow, null)

End Sub

Sub IDButton_actionPerformed(oEvent As Variant)
'   Assigned to the button action event when dialog was created'

    Dim vTextfield As Variant

    vTextfield = oEvent.Source.Context.getControl("TextField1")

    vTextfield.Text = ThisComponent.URL
End Sub
edit flag offensive delete link more

Question Tools

1 follower


Asked: 2016-09-30 23:22:13 +0200

Seen: 1,175 times

Last updated: Oct 01 '16