Difference between revisions of "FR/Documentation/Utilitaires C++"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Les fenêtres MessageBox)
m (Boîte de dialogue d'enregistrement)
Line 376: Line 376:
 
</source>
 
</source>
 
Nous sommes intéressés maintenant par la généralisation de tout ceci à une boîte de dialogue générale.
 
Nous sommes intéressés maintenant par la généralisation de tout ceci à une boîte de dialogue générale.
 +
 +
= Boites de dialogues =
 +
 +
=Exécuter une macro OOoBasic=
 +
==Un premier exemple==
 +
Notre but est d'exécuter un sous-programme OOoBasic à partir du C++. Nous commençons par le message intéressant posté par Danny Brewer (http://www.oooforum.org/forum/viewtopic.php?p=20890#20890) :
 +
Dans le module Essai1 des macros OOo, je place ce sous-programme :
 +
<source lang="oobas">
 +
'Listing 133
 +
REM  *****  BASIC  *****
 +
Sub SaySomething( )
 +
MsgBox "Hello from OOoBasic"
 +
End Sub
 +
</source>
 +
Le code correspondant en OooBasic pour seulement exécuter ce sous-programme devrait être :
 +
<source lang="oobas">
 +
'Listing 134
 +
REM  *****  BASIC  *****
 +
Sub Main
 +
oDispatch = createUnoService( "com.sun.star.frame.DispatchHelper" )
 +
oDispatch.executeDispatch( StarDesktop, "macro:///Standard.Module1.SaySomething()",
 +
"", 0, Array() )
 +
End Sub
 +
</source>
 +
Nous pouvons appeler directement ce sous-programme par son nom dans OOoBasic mais pas dans C++. 
 +
Traduire ce code dans C++ est facile: nous donnons encore le listing complet :
 +
<source lang="cpp">
 +
//Listing 135
 +
// C++
 +
int main( ) {
 +
//retrieve an instance of the remote service manager
 +
    Reference< XMultiServiceFactory > rOfficeServiceManager;
 +
    rOfficeServiceManager = ooConnect();
 +
    if( rOfficeServiceManager.is() ){
 +
        printf( "Connected sucessfully to the office\n" );
 +
    }
 +
 +
//get the desktop service using createInstance returns an XInterface type
 +
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
 +
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 +
 +
//query for the XComponentLoader interface
 +
    Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY);
 +
    if( rComponentLoader.is() ){
 +
        printf( "XComponentloader successfully instanciated\n" );
 +
    }
 +
 +
Reference< XDesktop > rDesktop(Desktop,UNO_QUERY);
 +
 +
// Don't forget to add : #include <com/sun/star/frame/XDispatchHelper.hpp>
 +
// Don't forget to add "com.sun.star.frame.XDispatchHelper \" in the makefile
 +
// Query the XDispatcher Interface
 +
Reference< XDispatchHelper > rDispatchHelper = Reference< XDispatchHelper >
 +
( rOfficeServiceManager->createInstance(
 +
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
 +
                                        "com.sun.star.frame.DispatchHelper" ))), UNO_QUERY );
 +
 +
 +
// Don't forget to add : #include <com/sun/star/frame/XDispatchProvider.hpp>
 +
// Don't forget to add "com.sun.star.frame.XDispatchProvider \" in the makefile
 +
// Query the XDispatchProvider Interface
 +
Reference< XDispatchProvider > rDispatchProvider(rDesktop,UNO_QUERY);
 +
 +
Any any=rDispatchHelper->executeDispatch(rDispatchProvider,
 +
OUString::createFromAscii("macro:///Standard.Essai1.SaySomething()"),
 +
OUString::createFromAscii(""),
 +
0,
 +
Sequence < ::com::sun::star::beans::PropertyValue > ());
 +
    return 0;
 +
}
 +
</source>
 +
lequel affiche un message  “Bonjour d'OOoBasic” mais retourne une erreur. Cette erreur est là seulement parce que le programme une fois terminé essaie de détruire les variables objets pendant qu'OOoBasic est toujours en marche ! Nous avons un processus complètement asynchrone.
 +
==XRay et C++==
 +
Comme dans l'exemple précédent, nous pouvons naturellement appeler l'outil XRay depuis le C++. Ici nous expliquons comment faire cela.
 +
En premier il faut écrire un sub OOoBasic :
 +
<source lang="oobas">
 +
'Listing 136
 +
REM  *****  BASIC  *****
 +
Sub BernardXRay( x )
 +
oBJ = createUnoService(x)
 +
XRAY.XRAY oBJ
 +
End Sub
 +
</source>
 +
dans le module “Essai1”, et en deuxième il faut écrire par exemple :
 +
<source lang="cpp">
 +
//Listing 137
 +
// C++
 +
...
 +
Reference< XDispatchHelper > rDispatchHelper = Reference< XDispatchHelper >
 +
( rOfficeServiceManager->createInstance(
 +
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
 +
                                        "com.sun.star.frame.DispatchHelper" ))), UNO_QUERY );
 +
...
 +
 +
Any any=rDispatchHelper->executeDispatch(rDispatchProvider,
 +
OUString::createFromAscii(
 +
"macro:///Standard.Essai1.BernardXRay(com.sun.star.frame.DispatchHelper)"),
 +
OUString::createFromAscii(""),
 +
0,
 +
Sequence < ::com::sun::star::beans::PropertyValue > ());
 +
</source>
 +
La façon de faire cela est très inefficace comme  explorateur d'objet. La liaison entre C++ et OOoBasic est trop lâche. Il n'y a aucune liaison entre la variable C++ rDispatchHelper et la variable oBJ OOoBasic. Une pourrait très bien être NULLE et pas la seconde. J'explorerai plus tard une autre façon avec un add-on pour faire une liaison entre OOoBasic et C++.
 +
 +
Une autre manière en C++ pourrait être :
 +
<source lang="cpp">
 +
//Listing 138
 +
// C++
 +
void LittleXRay(OUString OUStr,Reference< XMultiServiceFactory > rOServiceManager) {
 +
// Don't forget to add : using namespace com::sun::star::reflection;
 +
// Don't forget to add : #include <com/sun/star/reflection/XIdlReflection.hpp>
 +
// Don't forget to add "com.sun.star.reflection.XIdlReflection \" in the makefile
 +
Reference< XIdlReflection >rIDLReflection = Reference< XIdlReflection >
 +
( rOServiceManager->createInstance(
 +
                                      OUString( RTL_CONSTASCII_USTRINGPARAM(
 +
                                          "com.sun.star.reflection.CoreReflection" ))), UNO_QUERY );
 +
if (! rIDLReflection.is()) printf("Error XIDLRflection\n");
 +
Reference< XIdlClass > rIDLClass=rIDLReflection->forName(OUStr);
 +
// OUString::createFromAscii("com.sun.star.frame.XDesktop"));
 +
 +
 +
Sequence< Reference< XIdlClass > > SeqIdlClass = rIDLClass->getSuperclasses();
 +
printf("******** superClasses :(%d)\n",SeqIdlClass.getLength());
 +
for (int i=0;i<SeqIdlClass.getLength();i++){
 +
OString o = OUStringToOString( SeqIdlClass[i]->getName(),RTL_TEXTENCODING_ASCII_US );
 +
    printf("%s\n", o.pData->buffer );
 +
}
 +
Sequence< Reference< XIdlMethod > > SeqIdlMethods = rIDLClass->getMethods();
 +
printf("******** methods : (%d)\n",SeqIdlMethods.getLength());
 +
for (int i=0;i<SeqIdlMethods.getLength();i++){
 +
OString o = OUStringToOString( SeqIdlMethods[i]->getName(),RTL_TEXTENCODING_ASCII_US );
 +
    printf("%s\n", o.pData->buffer );
 +
}
 +
Sequence< Reference< XIdlField > > SeqIdlFields = rIDLClass->getFields();
 +
printf("******* Fields : (%d)\n",SeqIdlFields.getLength());
 +
for (int i=0;i<SeqIdlFields.getLength();i++){
 +
OString o = OUStringToOString( SeqIdlFields[i]->getName(),RTL_TEXTENCODING_ASCII_US );
 +
    printf("%s\n", o.pData->buffer );
 +
}
 +
}
 +
</source>
 +
laquelle pourrait être appelée :
 +
<source lang="cpp">
 +
//Listing 139
 +
// C++
 +
  LittleXRay(OUString::createFromAscii("com.sun.star.frame.XDesktop"),rOfficeServiceManager);
 +
</source>
 +
Nous préférons utiliser la méthode utilisée par l'exemple Java Inspector qui inspecte l'objet réel. Vous pouvez trouver alors par exemple des valeurs des propriétés. (<OpenOffice.org1.1_SDK>/examples/java/Inspector)
 +
<source lang="cpp">
 +
//Listing 140
 +
// C++
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/reflection/ParamMode.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.reflection.ParamMode \" in the makefile
 +
OString getParamMode(ParamMode paramMode) {
 +
// comes from <OpenOffice1.1_SDK>/examples/java/Inspector
 +
  OString toReturn;
 +
  toReturn = "";
 +
  if (paramMode == ParamMode_IN) toReturn = "IN"; else
 +
    if (paramMode == ParamMode_OUT) toReturn = "OUT"; else
 +
      if (paramMode == ParamMode_INOUT) toReturn = "INOUT";
 +
  return toReturn;
 +
}
 +
 +
void smallXRay(Any any,Reference< XMultiServiceFactory > rOServiceManager) {
 +
// comes from <OpenOffice1.1_SDK>/examples/java/Inspector
 +
 +
// N'oubliez pas d'ajouter : using namespace com::sun::star::beans;
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/XIntrospection.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.beans.XIntrospection \" in the makefile
 +
Reference< XIntrospection >xIntrospection = Reference< XIntrospection >
 +
( rOServiceManager->createInstance(
 +
                                  OUString( RTL_CONSTASCII_USTRINGPARAM(
 +
                                  "com.sun.star.beans.Introspection" ))), UNO_QUERY );
 +
 +
// ********* get all methods for the given object *********************
 +
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/lang/XServiceInfo.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.lang.XServiceInfo \" in the makefile
 +
Reference< XServiceInfo > rServiceInfo(any,UNO_QUERY);
 +
 +
Reference< XIntrospectionAccess > xIntrospec = xIntrospection->inspect(any);
 +
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/MethodConcept.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.beans.MethodConcept \" in the makefile
 +
Sequence< Reference < XIdlMethod > > mMethods = xIntrospec ->
 +
getMethods(MethodConcept::ALL);
 +
printf("******** methods : (%d)\n",mMethods.getLength());
 +
for (int i=0;i<mMethods.getLength();i++){
 +
OString params;
 +
params="";
 +
Sequence< ParamInfo > ParamInfos = mMethods[i]->getParameterInfos();
 +
if (ParamInfos.getLength() > 0) {
 +
for (int j=0;j<ParamInfos.getLength();j++){
 +
Reference< XIdlClass > xIdlClass = ParamInfos[j].aType;
 +
if (j == 0)
 +
// first parameter has no leading comma
 +
params += "[" + getParamMode(ParamInfos[j].aMode)+
 +
"]" + OUStringToOString(xIdlClass->getName(),RTL_TEXTENCODING_ASCII_US );
 +
else
 +
params += ",[" + getParamMode(ParamInfos[j].aMode)+
 +
"]"+OUStringToOString(xIdlClass->getName(),RTL_TEXTENCODING_ASCII_US );
 +
}
 +
}
 +
OString o = OUStringToOString( mMethods[i]->getName(),RTL_TEXTENCODING_ASCII_US )
 +
+ "(" + params + ")";
 +
    printf("%s\n", o.pData->buffer);
 +
}
 +
 +
// ********** get all Interfaces for the given object *********************
 +
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/lang/XTypeProvider.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.lang.XTypeProvider \" in the makefile
 +
Reference< XTypeProvider > rTypeProvider(any,UNO_QUERY);
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/uno/Type.hxx>
 +
// But nothing in MakeFile : this hxx file is provided by SDK
 +
Sequence< Type > types = rTypeProvider->getTypes();
 +
printf("******** interfaces : (%d)\n",types.getLength());
 +
for (int i=0;i<types.getLength();i++){
 +
OString o = OUStringToOString( types[i].getTypeName(),RTL_TEXTENCODING_ASCII_US );
 +
    printf("%s\n", o.pData->buffer );
 +
}
 +
 +
// ********** get all properties for the given object *********************
 +
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/PropertyConcept.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.beans.PropertyConcept \" in the makefile
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/Property.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.beans.Property \" in the makefile
 +
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/XPropertySet.hpp>
 +
// N'oubliez pas d'ajouter "com.sun.star.beans.XPropertySet \" in the makefile
 +
 +
Sequence< Property > Properties = xIntrospec -> getProperties(PropertyConcept::ALL);
 +
printf("******** properties : (%d)\n",Properties.getLength());
 +
for (int i=0;i<Properties.getLength();i++){
 +
// Reference< XPropertySet > rPropertySet(any,UNO_QUERY);
 +
// Any object;
 +
// OUString ou;
 +
// object <<= rPropertySet->getPropertyValue(Properties[i].Name);
 +
// if (object.hasValue()) printf("Valeur trouvee : ");
 +
// object >>= ou;
 +
OString o = OUStringToOString( Properties[i].Name,RTL_TEXTENCODING_ASCII_US ) +
 +
" = (" +
 +
OUStringToOString(Properties[i].Type.getTypeName(),RTL_TEXTENCODING_ASCII_US ) + ") ";
 +
    printf("%s\n", o.pData->buffer );
 +
}
 +
 +
}
 +
</source>
 +
lequel est appelé par :
 +
<source lang="cpp">
 +
//Listing 141
 +
// C++
 +
Any toInspect;
 +
toInspect <<= rDesktop;
 +
smallXRay(toInspect,rOfficeServiceManager);
 +
</source>

Revision as of 09:55, 9 July 2008

Jouer avec les fenêtres du toolkit

Explications de Danny Brewer

Il y a deux choses différentes ici. En réalité il y en a trois.

1. Les dialogues

2. AWT

3. Les formes

Les formes sont d'un plus haut niveau que les deux autres.

  • Sur les deux premiers, les dialogues utilisent le UnoDialogControl et ses modèles. Vous pouvez aussi créer des fenêtres AWT avec les commandes.
  • Les fenêtres AWT peuvent être modales ou non, et ne sont pas attachées à d'autres fenêtres.
  • Les fenêtres AWT ne sont pas comme les dialogues.

Généralement, les dialogues sont réalisés de façon modale en appelant la méthode execute() du dialogue. J'ai réussi à réaliser des boites de dialogue non modales.

Les fenêtres MessageBox

Le code initial est en gros le même que le précédent (examples/DevelopersGuide/ProfUNO/CppBinding/). Nous examinons aussi l'exemple de “<OpenOffice.org1.1_SDK>/examples/DevelopersGuide/Components/Addons/ProtocolHandlerAddon_cpp” où nous trouvons une fenêtre MessageBox. Le code correspondant est donné ici :

//Listing 1
// C++
// N'oubliez pas d'ajouter : #include <com/sun/star/awt/WindowDescriptor.hpp>
// N'oubliez pas d'ajouter "com.sun.star.awt.WindowDescriptor \" dans le makefile
// N'oubliez pas d'ajouter : #include <com/sun/star/awt/WindowAttribute.hpp>
// N'oubliez pas d'ajouter "com.sun.star.awt.WindowAttribute \" dans le makefile
// N'oubliez pas d'ajouter : #include <com/sun/star/awt/XWindowPeer.hpp>
// N'oubliez pas d'ajouter "com.sun.star.awt.XWindowPeer \" dans le makefile
// N'oubliez pas d'ajouter : #include <com/sun/star/awt/XMessageBox.hpp>
// N'oubliez pas d'ajouter "com.sun.star.awt.XMessageBox \" dans le makefile
 
/**
  * Show a message box with the UNO based toolkit
  */
static void ShowMessageBox( const Reference< XToolkit >& rToolkit, const Reference< XFrame >& rFrame, const OUString& aTitle, const OUString& aMsgText )
{
    if ( rFrame.is() && rToolkit.is() )
    {
        // describe window properties.
        WindowDescriptor                aDescriptor;
        aDescriptor.Type              = WindowClass_MODALTOP;
        aDescriptor.WindowServiceName = OUString( RTL_CONSTASCII_USTRINGPARAM( "infobox" ));
        aDescriptor.ParentIndex       = -1;
        aDescriptor.Parent            = Reference< XWindowPeer >( rFrame->getContainerWindow(), UNO_QUERY );
        aDescriptor.Bounds            = Rectangle(0,0,300,200);
        aDescriptor.WindowAttributes  = WindowAttribute::BORDER | WindowAttribute::MOVEABLE | WindowAttribute::CLOSEABLE;
 
        Reference< XWindowPeer > xPeer = rToolkit->createWindow( aDescriptor );
        if ( xPeer.is() )
        {
            Reference< XMessageBox > xMsgBox( xPeer, UNO_QUERY );
            if ( xMsgBox.is() )
            {
                xMsgBox->setCaptionText( aTitle );
                xMsgBox->setMessageText( aMsgText );
                xMsgBox->execute();
            }
        }
    }
}

pour comprendre le WindowAttribute::BORDER et les autres constantes, jetons un oeil au fichier IDL “WindowAttribute.idl” décrivant les attributs de fenêtres :

//Listing 2
// IDL
module com {  module sun {  module star {  module awt {
constants WindowAttribute
{
	const long SHOW = 1; 
	const long FULLSIZE = 2; 
	const long OPTIMUMSIZE = 4; 
	const long MINSIZE = 8; 
	const long BORDER = 16; 
	const long SIZEABLE = 32; 
	const long MOVEABLE = 64; 
	const long CLOSEABLE = 128; 
	const long SYSTEMDEPENDENT = 256;  
};
}; }; }; };

Nous donnons maintenant le listing d'un programme principal complet pour nous apprendre à utiliser cette procédure :

//Listing 3
//C++
int main( ) {
//retrieve an instance of the remote service manager
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
    if( rOfficeServiceManager.is() ){
        printf( "Connected sucessfully to the office\n" );
    }
 
//get the desktop service using createInstance returns an XInterface type
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
//query for the XComponentLoader interface
    Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY);
    if( rComponentLoader.is() ){
        	printf( "XComponentloader successfully instanciated\n" );
    	}
 
// Don't forget to add : #include <com/sun/star/awt/XToolkit.hpp>
// Don't forget to add "com.sun.star.awt.XToolkit \" in the makefile
// Query the XTollkit Interface
	Reference< XToolkit >rToolkit = Reference< XToolkit >( rOfficeServiceManager->createInstance(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                            "com.sun.star.awt.Toolkit" ))), UNO_QUERY );
 
	if (rToolkit.is()) {
	  printf ("OK...\n");
	} else printf("Toolkit Error\n");
 
	Reference< XDesktop > rDesktop(Desktop,UNO_QUERY);
	Reference< XFrame > rFrame=rDesktop->getCurrentFrame();
	if (rFrame.is()) printf("rFrame ... OK\n"); else printf("rFrame Error\n");
 
	ShowMessageBox( rToolkit, rFrame,OUString::createFromAscii("Hello") ,
				OUString::createFromAscii("Your First Message\n OK ?")  );
 
    return 0;
}

Nous pouvons tirer trois choses importantes de ce code :

  • la manière que nous pouvons utiliser un tel fichier IDL (donné au-dessus) avec C++: ce n'est pas la première fois que nous rencontrons ce genre de fichier IDL,
  • la manière dont on peut accéder à une interface à travers un service avec createInstance et UNO_QUERY simultanément (voir comment nous obtenons rToolkit)
  • nous voyons aussi comment nous obtenons une fenêtre.

La boîte de dialogue d'obtention d'un fichier : « file picker dialog »

Nous voulons fournir une boîte de dialogue pour chercher un fichier par exploration et qui rende le nom du fichier choisi. Nous commençons par partir d'un exemple du livre de Bernard Marcelly. Quand nous travaillons avec la boîte de dialogue d'obtention d'un fichier, nous devons nous intéresser à trois fichiers IDL. Voici le premier :

//Listing 4 Le fichier XexecutableDialog.idl
// IDL
module com { module sun { module star { module ui { module dialogs {
interface XFilePicker: com::sun::star::ui::dialogs::XExecutableDialog
{
	void setMultiSelectionMode( [in] boolean bMode );
	void setDefaultName( [in] string aName );
	void setDisplayDirectory( [in] string aDirectory )
		raises( ::com::sun::star::lang::IllegalArgumentException );
	string getDisplayDirectory();
	sequence< string > getFiles();
};
}; }; }; }; };

Le début de ce fichier indique que nous nous inquiétons avec l'XExecutableDialog aussi :

//Listing 5 Le fichier XexecutableDialog.idl
// IDL
module com { module sun { module star { module ui { module dialogs {
interface XExecutableDialog: com::sun::star::uno::XInterface
{
	void setTitle( [in] string aTitle );
	short execute();
};
}; }; }; }; };

et ce qui est plus difficile à voir et qui nous intéresses est un fichier définissant deux constantes :

//Listing 6 Le fichier ExecutableDialogResult
// IDL
module com { module sun { module star { module ui { module dialogs {
constants ExecutableDialogResults
{
	const short CANCEL = 0;
	const short OK     = 1;
};
}; }; }; }; };

La façon de faire peut être expliquée comme suit. Vous devez en premier obtenir une Interface XFilePicker. Après nous utilisons un setDisplayDirectory pour un exemple, ensuite nous exécutons la boîte du dialogue et finalement nous obtenons le premier des dossiers choisis. Voici le code correspondant :

//Listing 7
// LINUX C++ (Only the file path is LINUX-like)
// based on Bernard Marcelly's  Example (Book p512)
// Don't forget #include <osl/file.hxx>
	OUString sDocUrl;
	osl::FileBase::getFileURLFromSystemPath(
				OUString::createFromAscii("/home/smoutou/"),sDocUrl);
 
// N'oubliez pas d'ajouter : using namespace com::sun::star::ui::dialogs;
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/XFilePicker \" in the makefile
// Query the XFilePicker interface
 
	Reference< XFilePicker > rFilePicker = Reference< XFilePicker >
					( rOfficeServiceManager->createInstance(
                          OUString( RTL_CONSTASCII_USTRINGPARAM(
                          "com.sun.star.ui.dialogs.FilePicker" ))), UNO_QUERY );
 
	rFilePicker->setDisplayDirectory( sDocUrl);
	short result=rFilePicker->execute();
 
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/ExecutableDialogResults \" in the makefile
	if (result == ExecutableDialogResults::OK)
	  ShowMessageBox( rToolkit, rFrame,OUString::createFromAscii("Result") ,
			rFilePicker->getFiles()[0]  );

C'est possible de modifier le filtre nommé avec le XFilterManager. Voici le fichier IDL correspondant :

//Listing 8 Le fichier XfilterManager.idl
// IDL
module com { module sun { module star { module ui { module dialogs {
interface XFilterManager: com::sun::star::uno::XInterface
{
	void appendFilter( [in] string aTitle, [in] string aFilter )
		raises( ::com::sun::star::lang::IllegalArgumentException );
	void setCurrentFilter( [in] string aTitle )
		raises( ::com::sun::star::lang::IllegalArgumentException );
	string getCurrentFilter( );
};
}; }; }; }; };

Et maintenant voici un exemple en C++ qui utilise cette interface :

// Listing 9
// LINUX C++
// N'oubliez pas #include <osl/file.hxx>
	OUString sDocUrl;
	osl::FileBase::getFileURLFromSystemPath(
						OUString::createFromAscii("/home/smoutou/"),sDocUrl);
// N'oubliez pas d'ajouter : using namespace com::sun::star::ui::dialogs;
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/XFilePicker \" in the makefile
//	Reference< XFilePicker > rFilePicker(rDesktop,UNO_QUERY);
	Reference< XFilePicker > rFilePicker = Reference< XFilePicker >
					( rOfficeServiceManager->createInstance(
                                 OUString( RTL_CONSTASCII_USTRINGPARAM(
                                 "com.sun.star.ui.dialogs.FilePicker" ))), UNO_QUERY );
 
	rFilePicker->setDisplayDirectory( sDocUrl);
 
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/XFilterManager \" in the makefile
	Reference< XFilterManager > rFilterManager (rFilePicker, UNO_QUERY);
	rFilterManager->appendFilter(OUString::createFromAscii("Texts"),
					OUString::createFromAscii("*.txt"));
	rFilterManager->appendFilter(OUString::createFromAscii("Docs OpenOffice"),
					OUString::createFromAscii("*.sxw;*.sxc"));
	rFilterManager->setCurrentFilter(OUString::createFromAscii("Docs OpenOffice"));
	short result=rFilePicker->execute();
 
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/ExecutableDialogResults \" in the makefile
	if (result == ExecutableDialogResults::OK)
	  ShowMessageBox( rToolkit, rFrame,OUString::createFromAscii("Result") ,
			rFilePicker->getFiles()[0]  );

Il est temps de montrer comment faire une sauvegarde avec une boîte de Dialogue.

Boîte de dialogue d'enregistrement

Nous partons encore d'un exemple de Bernard Marcelly. Notre problème est de traduire ces lignes OOoBasic :

'Listing 10
REM  *****  BASIC  *****
FP=CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
Dim FPtype(0) As Integer
FPtype(0)=com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_SIMPLE
With FP
	.initialize(FPtype())
....
End With

en particulier celles du début.

Nous cherchons d'abord les constantes qui permettent de transformer la boîte de dialogue précédente. Elles sont définies dans le fichier TemplateDescription.idl  :

//Listing 11 Le fichier TemplateDescription.idl
// IDL
module com { module sun { module star { module ui { module dialogs {
constants TemplateDescription
{
	const short FILEOPEN_SIMPLE                                = 0;
	const short FILESAVE_SIMPLE                                = 1;
	const short FILESAVE_AUTOEXTENSION_PASSWORD                = 2;
	const short FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS  = 3;
	const short FILESAVE_AUTOEXTENSION_SELECTION               = 4;
	const short FILESAVE_AUTOEXTENSION_TEMPLATE                = 5;
	const short FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE           = 6;
	const short FILEOPEN_PLAY                                  = 7;
	const short FILEOPEN_READONLY_VERSION                      = 8;
	const short FILEOPEN_LINK_PREVIEW		           = 9;
	const short FILESAVE_AUTOEXTENSION	               = 10;
};
}; }; }; }; };

Pour initialiser nous cherchons dans le fichier FilePicker.idl :

//Listing 12 Description du service FilePicker
module com { module sun { module star { module ui { module dialogs {
interface XFilePicker;
interface XFilePickerNotifier;
interface XFilePickerControlAccess;
interface XFilterManager;
interface XFilePreview;
interface XFilterGroupManager;
 
service FilePicker
{
	[optional, property] string HelpURL;
	interface XFilePicker;
	interface XFilePickerNotifier;
	interface XFilterManager;
	[optional] interface XFilePreview;
	[optional] interface XFilePickerControlAccess;
	[optional] interface XFilterGroupManager;
	[optional] interface com::sun::star::lang::XInitialization;
	[optional] interface com::sun::star::util::XCancellable;
	interface com::sun::star::lang::XComponent;
	interface com::sun::star::lang::XServiceInfo;
	interface com::sun::star::lang::XTypeProvider;
};
}; }; }; }; };

où vous voyez une interface XInitialization. Nous donnons ensuite le fichier XInitialization.idl :

//Listing 13
module com {  module sun {  module star {  module lang {
interface XInitialization: com::sun::star::uno::XInterface
{ 
	void initialize( [in] sequence<any> aArguments ) 
			raises( com::sun::star::uno::Exception ); 
 
}; 
}; }; }; };

C'est bien, nous l'avons. Nous voyons que nous devons passer une séquence à la procédure d'initialisation. Il est temps d'écrire le code correspondant.

//Listing 14
	// LINUX C++
	// inspired by Bernard Marcelly's Example p515
// N'oubliez pas #include <osl/file.hxx>
	OUString sDocUrl;
	osl::FileBase::getFileURLFromSystemPath(
						OUString::createFromAscii("/home/smoutou/"),sDocUrl);
// N'oubliez pas d'ajouter : using namespace com::sun::star::ui::dialogs;
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/XFilePicker \" in the makefile
//	Reference< XFilePicker > rFilePicker(rDesktop,UNO_QUERY);
	Reference< XFilePicker > rFilePicker = Reference< XFilePicker >
					( rOfficeServiceManager->createInstance(
                               OUString( RTL_CONSTASCII_USTRINGPARAM(
                               "com.sun.star.ui.dialogs.FilePicker" ))), UNO_QUERY );
 
	rFilePicker->setDisplayDirectory( sDocUrl);
 
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs.XFilterManager \" in the makefile
	Reference< XFilterManager > rFilterManager (rFilePicker, UNO_QUERY);
 
// N'oubliez pas d'ajouter : #include <com/sun/star/lang/XInitialization.hpp>
// N'oubliez pas d'ajouter "com.sun.star.lang.XInitialization \" in the makefile
	Reference< XInitialization > rInitialize (rFilePicker, UNO_QUERY);
	Sequence < Any > info(1);
 
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs.TemplateDescription \" in the makefile
	info[0] <<=  (short) TemplateDescription::FILESAVE_SIMPLE;
	rInitialize-> initialize(info);
 
	rFilterManager->appendFilter(OUString::createFromAscii("Texts"),
					OUString::createFromAscii("*.txt"));
	rFilterManager->appendFilter(OUString::createFromAscii("Docs OpenOffice"),
					OUString::createFromAscii("*.sxw;*.sxc"));
	rFilterManager->setCurrentFilter(OUString::createFromAscii("Docs OpenOffice"));
	short result=rFilePicker->execute();
 
// N'oubliez pas d'ajouter : #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
// N'oubliez pas d'ajouter "com.sun.star.ui.dialogs/ExecutableDialogResults \" in the makefile
	if (result == ExecutableDialogResults::OK)
	  ShowMessageBox( rToolkit, rFrame,OUString::createFromAscii("Result") ,
			rFilePicker->getFiles()[0]  );

Nous sommes intéressés maintenant par la généralisation de tout ceci à une boîte de dialogue générale.

Boites de dialogues

Exécuter une macro OOoBasic

Un premier exemple

Notre but est d'exécuter un sous-programme OOoBasic à partir du C++. Nous commençons par le message intéressant posté par Danny Brewer (http://www.oooforum.org/forum/viewtopic.php?p=20890#20890) : Dans le module Essai1 des macros OOo, je place ce sous-programme :

'Listing 133
REM  *****  BASIC  *****
Sub SaySomething( ) 
	MsgBox "Hello from OOoBasic" 
End Sub

Le code correspondant en OooBasic pour seulement exécuter ce sous-programme devrait être :

'Listing 134
REM  *****  BASIC  *****
Sub Main 
	oDispatch = createUnoService( "com.sun.star.frame.DispatchHelper" ) 
	oDispatch.executeDispatch( StarDesktop, "macro:///Standard.Module1.SaySomething()", 
		"", 0, Array() ) 
End Sub

Nous pouvons appeler directement ce sous-programme par son nom dans OOoBasic mais pas dans C++. Traduire ce code dans C++ est facile: nous donnons encore le listing complet :

//Listing 135
// C++
int main( ) {
//retrieve an instance of the remote service manager
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
    if( rOfficeServiceManager.is() ){
        printf( "Connected sucessfully to the office\n" );
    }
 
//get the desktop service using createInstance returns an XInterface type
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
//query for the XComponentLoader interface
    Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY);
    if( rComponentLoader.is() ){
        	printf( "XComponentloader successfully instanciated\n" );
    	}
 
	Reference< XDesktop > rDesktop(Desktop,UNO_QUERY);
 
// Don't forget to add : #include <com/sun/star/frame/XDispatchHelper.hpp>
// Don't forget to add "com.sun.star.frame.XDispatchHelper \" in the makefile
// Query the XDispatcher Interface
	Reference< XDispatchHelper > rDispatchHelper = Reference< XDispatchHelper >
				( rOfficeServiceManager->createInstance(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                        "com.sun.star.frame.DispatchHelper" ))), UNO_QUERY );
 
 
// Don't forget to add : #include <com/sun/star/frame/XDispatchProvider.hpp>
// Don't forget to add "com.sun.star.frame.XDispatchProvider \" in the makefile
// Query the XDispatchProvider Interface
	Reference< XDispatchProvider > rDispatchProvider(rDesktop,UNO_QUERY);
 
	Any any=rDispatchHelper->executeDispatch(rDispatchProvider,
			OUString::createFromAscii("macro:///Standard.Essai1.SaySomething()"),
			OUString::createFromAscii(""),
			0,
			Sequence < ::com::sun::star::beans::PropertyValue > ());
    return 0;
}

lequel affiche un message “Bonjour d'OOoBasic” mais retourne une erreur. Cette erreur est là seulement parce que le programme une fois terminé essaie de détruire les variables objets pendant qu'OOoBasic est toujours en marche ! Nous avons un processus complètement asynchrone.

XRay et C++

Comme dans l'exemple précédent, nous pouvons naturellement appeler l'outil XRay depuis le C++. Ici nous expliquons comment faire cela. En premier il faut écrire un sub OOoBasic :

'Listing 136
REM  *****  BASIC  *****
Sub BernardXRay( x ) 
	oBJ = createUnoService(x)
	XRAY.XRAY oBJ
End Sub

dans le module “Essai1”, et en deuxième il faut écrire par exemple :

//Listing 137
// C++
...
	Reference< XDispatchHelper > rDispatchHelper = Reference< XDispatchHelper >
				( rOfficeServiceManager->createInstance(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                        "com.sun.star.frame.DispatchHelper" ))), UNO_QUERY );
...
 
	Any any=rDispatchHelper->executeDispatch(rDispatchProvider,
			OUString::createFromAscii(
				"macro:///Standard.Essai1.BernardXRay(com.sun.star.frame.DispatchHelper)"),
			OUString::createFromAscii(""),
			0,
			Sequence < ::com::sun::star::beans::PropertyValue > ());

La façon de faire cela est très inefficace comme explorateur d'objet. La liaison entre C++ et OOoBasic est trop lâche. Il n'y a aucune liaison entre la variable C++ rDispatchHelper et la variable oBJ OOoBasic. Une pourrait très bien être NULLE et pas la seconde. J'explorerai plus tard une autre façon avec un add-on pour faire une liaison entre OOoBasic et C++.

Une autre manière en C++ pourrait être :

//Listing 138
// C++
void LittleXRay(OUString OUStr,Reference< XMultiServiceFactory > rOServiceManager) {
// Don't forget to add : using namespace com::sun::star::reflection;
// Don't forget to add : #include <com/sun/star/reflection/XIdlReflection.hpp>
// Don't forget to add "com.sun.star.reflection.XIdlReflection \" in the makefile
	Reference< XIdlReflection >rIDLReflection = Reference< XIdlReflection >
					( rOServiceManager->createInstance(
                                      OUString( RTL_CONSTASCII_USTRINGPARAM(
                                          "com.sun.star.reflection.CoreReflection" ))), UNO_QUERY );
	if (! rIDLReflection.is()) printf("Error XIDLRflection\n");
	Reference< XIdlClass > rIDLClass=rIDLReflection->forName(OUStr);
//			OUString::createFromAscii("com.sun.star.frame.XDesktop"));
 
 
	Sequence< Reference< XIdlClass > > SeqIdlClass = rIDLClass->getSuperclasses();
	printf("******** superClasses :(%d)\n",SeqIdlClass.getLength());
	for (int i=0;i<SeqIdlClass.getLength();i++){
		OString o = OUStringToOString( SeqIdlClass[i]->getName(),RTL_TEXTENCODING_ASCII_US );
    		printf("%s\n", o.pData->buffer );
	}
	Sequence< Reference< XIdlMethod > > SeqIdlMethods = rIDLClass->getMethods();
	printf("******** methods : (%d)\n",SeqIdlMethods.getLength());
	for (int i=0;i<SeqIdlMethods.getLength();i++){
		OString o = OUStringToOString( SeqIdlMethods[i]->getName(),RTL_TEXTENCODING_ASCII_US );
    		printf("%s\n", o.pData->buffer );
	}
	Sequence< Reference< XIdlField > > SeqIdlFields = rIDLClass->getFields();
	printf("******* Fields : (%d)\n",SeqIdlFields.getLength());
	for (int i=0;i<SeqIdlFields.getLength();i++){
		OString o = OUStringToOString( SeqIdlFields[i]->getName(),RTL_TEXTENCODING_ASCII_US );
    		printf("%s\n", o.pData->buffer );
	}
}

laquelle pourrait être appelée :

//Listing 139
// C++
  LittleXRay(OUString::createFromAscii("com.sun.star.frame.XDesktop"),rOfficeServiceManager);

Nous préférons utiliser la méthode utilisée par l'exemple Java Inspector qui inspecte l'objet réel. Vous pouvez trouver alors par exemple des valeurs des propriétés. (<OpenOffice.org1.1_SDK>/examples/java/Inspector)

//Listing 140
// C++
// N'oubliez pas d'ajouter : #include <com/sun/star/reflection/ParamMode.hpp>
// N'oubliez pas d'ajouter "com.sun.star.reflection.ParamMode \" in the makefile
OString getParamMode(ParamMode paramMode) {
// comes from <OpenOffice1.1_SDK>/examples/java/Inspector
  OString toReturn;
  toReturn = "";
  if (paramMode == ParamMode_IN) toReturn = "IN"; else
    if (paramMode == ParamMode_OUT) toReturn = "OUT"; else
      if (paramMode == ParamMode_INOUT) toReturn = "INOUT";
  return toReturn;
}
 
void smallXRay(Any any,Reference< XMultiServiceFactory > rOServiceManager) {
// comes from <OpenOffice1.1_SDK>/examples/java/Inspector
 
// N'oubliez pas d'ajouter : using namespace com::sun::star::beans;
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/XIntrospection.hpp>
// N'oubliez pas d'ajouter "com.sun.star.beans.XIntrospection \" in the makefile
	Reference< XIntrospection >xIntrospection = Reference< XIntrospection >
					( rOServiceManager->createInstance(
                                  OUString( RTL_CONSTASCII_USTRINGPARAM(
                                  "com.sun.star.beans.Introspection" ))), UNO_QUERY );
 
// ********* get all methods for the given object *********************
 
// N'oubliez pas d'ajouter : #include <com/sun/star/lang/XServiceInfo.hpp>
// N'oubliez pas d'ajouter "com.sun.star.lang.XServiceInfo \" in the makefile
	Reference< XServiceInfo > rServiceInfo(any,UNO_QUERY);
 
	Reference< XIntrospectionAccess > xIntrospec = xIntrospection->inspect(any);
 
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/MethodConcept.hpp>
// N'oubliez pas d'ajouter "com.sun.star.beans.MethodConcept \" in the makefile
	Sequence< Reference < XIdlMethod > > mMethods = xIntrospec -> 
												getMethods(MethodConcept::ALL);
	printf("******** methods : (%d)\n",mMethods.getLength());
	for (int i=0;i<mMethods.getLength();i++){
		OString params;
		params="";
		Sequence< ParamInfo > ParamInfos = mMethods[i]->getParameterInfos();
		if (ParamInfos.getLength() > 0) {
			for (int j=0;j<ParamInfos.getLength();j++){
				Reference< XIdlClass > xIdlClass = ParamInfos[j].aType;
				if (j == 0)
				// first parameter has no leading comma
				params += "[" + getParamMode(ParamInfos[j].aMode)+
				"]" + OUStringToOString(xIdlClass->getName(),RTL_TEXTENCODING_ASCII_US );
				else
				params += ",[" + getParamMode(ParamInfos[j].aMode)+
				"]"+OUStringToOString(xIdlClass->getName(),RTL_TEXTENCODING_ASCII_US );
			}
		}
		OString o = OUStringToOString( mMethods[i]->getName(),RTL_TEXTENCODING_ASCII_US )
						+ "(" + params + ")";
    		printf("%s\n", o.pData->buffer);
	}
 
// ********** get all Interfaces for the given object *********************
 
// N'oubliez pas d'ajouter : #include <com/sun/star/lang/XTypeProvider.hpp>
// N'oubliez pas d'ajouter "com.sun.star.lang.XTypeProvider \" in the makefile
	Reference< XTypeProvider > rTypeProvider(any,UNO_QUERY);
// N'oubliez pas d'ajouter : #include <com/sun/star/uno/Type.hxx>
// But nothing in MakeFile : this hxx file is provided by SDK
	Sequence< Type > types = rTypeProvider->getTypes();
	printf("******** interfaces : (%d)\n",types.getLength());
	for (int i=0;i<types.getLength();i++){
		OString o = OUStringToOString( types[i].getTypeName(),RTL_TEXTENCODING_ASCII_US );
    		printf("%s\n", o.pData->buffer );
	}
 
// ********** get all properties for the given object *********************
 
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/PropertyConcept.hpp>
// N'oubliez pas d'ajouter "com.sun.star.beans.PropertyConcept \" in the makefile
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/Property.hpp>
// N'oubliez pas d'ajouter "com.sun.star.beans.Property \" in the makefile
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/XPropertySet.hpp>
// N'oubliez pas d'ajouter "com.sun.star.beans.XPropertySet \" in the makefile
 
	Sequence< Property > Properties = xIntrospec -> getProperties(PropertyConcept::ALL);
	printf("******** properties : (%d)\n",Properties.getLength());
	for (int i=0;i<Properties.getLength();i++){
	//	Reference< XPropertySet > rPropertySet(any,UNO_QUERY);
	//	Any object;
	//	OUString ou;
	//	object <<= rPropertySet->getPropertyValue(Properties[i].Name);
	//	if (object.hasValue()) printf("Valeur trouvee : ");
	//	object >>= ou;
		OString o = OUStringToOString( Properties[i].Name,RTL_TEXTENCODING_ASCII_US ) +
		" = (" + 
		OUStringToOString(Properties[i].Type.getTypeName(),RTL_TEXTENCODING_ASCII_US ) + ") ";
    	printf("%s\n", o.pData->buffer );
	}
 
}

lequel est appelé par :

//Listing 141
// C++
	Any toInspect;
	toInspect <<= rDesktop;
	smallXRay(toInspect,rOfficeServiceManager);
Personal tools