Exemple Qutlook (ActiveQt)
L'exemple Qutlook illustre l'utilisation d'ActiveQt pour automatiser Outlook. Cet exemple utilise l'outil dumpcpp pour générer un espace de noms C++ pour la bibliothèque de types décrivant le modèle objet d'Outlook.
Le fichier de projet de cet exemple se présente comme suit :
TEMPLATE = app
TARGET = qutlook
QT += widgets axcontainer
TYPELIBS = $$system(dumpcpp -getfile {00062FFF-0000-0000-C000-000000000046})
isEmpty(TYPELIBS) {
message("Microsoft Outlook type library not found!")
REQUIRES += Outlook
} else {
HEADERS = addressview.h
SOURCES = addressview.cpp main.cpp
}Le fichier de projet utilise l'outil dumpcpp pour ajouter une bibliothèque de types MS Outlook au projet. En cas d'échec, le fichier makefile généré affichera simplement un message d'erreur ; dans le cas contraire, l'étape de compilation exécutera l'outil dumpcpp sur la bibliothèque de types et générera un fichier d'en-tête et un fichier cpp (dans ce cas, msoutl.h et msoutl.cpp) qui déclarent et implémentent une API facile à utiliser pour les objets Outlook.
class AddressView : public QWidget
{
Q_OBJECT
public:
explicit AddressView(QWidget *parent = nullptr);
protected slots:
void addEntry();
void changeEntry();
void itemSelected(const QModelIndex &index);
void updateOutlook();
protected:
AddressBookModel *model;
QTreeView *m_treeView;
QPushButton *m_addButton;
QPushButton *m_changeButton;
QLineEdit *m_firstName;
QLineEdit *m_lastName;
QLineEdit *m_address;
QLineEdit *m_email;
};La classe `AddressView` est une sous-classe de ` QWidget ` destinée à l’interface utilisateur. Le widget ` QTreeView ` affichera le contenu du dossier « Contacts » d’Outlook tel qu’il est fourni par le fichier ` model`.
#include "addressview.h"
#include "msoutl.h"
#include <QtWidgets>
class AddressBookModel : public QAbstractListModel
{
public:
explicit AddressBookModel(AddressView *parent);
virtual ~AddressBookModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role) const;
void changeItem(const QModelIndex &index, const QString &firstName, const QString &lastName, const QString &address, const QString &email);
void addItem(const QString &firstName, const QString &lastName, const QString &address, const QString &email);
void update();
private:
Outlook::Application outlook;
Outlook::Items *folderItems = nullptr;
mutable QHash<QModelIndex, QStringList> cache;
};La classe `AddressBookModel` est une sous-classe de ` QAbstractListModel ` qui communique directement avec Outlook, en utilisant un ` QHash ` pour la mise en cache.
AddressBookModel::AddressBookModel(AddressView *parent)
: QAbstractListModel(parent)
{
if (!outlook.isNull()) {
Outlook::NameSpace session(outlook.Session());
session.Logon();
Outlook::MAPIFolder *folder = session.GetDefaultFolder(Outlook::olFolderContacts);
folderItems = new Outlook::Items(folder->Items());
connect(folderItems, SIGNAL(ItemAdd(IDispatch*)), parent, SLOT(updateOutlook()));
connect(folderItems, SIGNAL(ItemChange(IDispatch*)), parent, SLOT(updateOutlook()));
connect(folderItems, SIGNAL(ItemRemove()), parent, SLOT(updateOutlook()));
delete folder;
}
}Le constructeur initialise Outlook. Les différents signaux fournis par Outlook pour signaler les modifications de contenu sont connectés au slot updateOutlook().
AddressBookModel::~AddressBookModel()
{
delete folderItems;
if (!outlook.isNull())
Outlook::NameSpace(outlook.Session()).Logoff();
}Le destructeur se déconnecte de la session.
int AddressBookModel::rowCount(const QModelIndex &) const
{
return folderItems ? folderItems->Count() : 0;
}
int AddressBookModel::columnCount(const QModelIndex & /*parent*/) const
{
return 4;
}L’implémentation de ` rowCount() ` renvoie le nombre d’entrées tel que signalé par Outlook. Les méthodes ` columnCount ` et ` headerData ` sont implémentées pour afficher quatre colonnes dans l’arborescence.
QVariant AddressBookModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
switch (section) {
case 0:
return tr("First Name");
case 1:
return tr("Last Name");
case 2:
return tr("Address");
case 3:
return tr("Email");
default:
break;
}
return QVariant();
}L’implémentation de ` headerData() ` renvoie des chaînes de caractères codées en dur.
QVariant AddressBookModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || role != Qt::DisplayRole)
return QVariant();
QStringList data;
if (cache.contains(index)) {
data = cache.value(index);
} else {
Outlook::ContactItem contact(folderItems->Item(index.row() + 1));
if (contact.Class() == Outlook::OlObjectClass::olContact)
data << contact.FirstName() << contact.LastName() << contact.HomeAddress() << contact.Email1Address();
cache.insert(index, data);
}
if (index.column() < data.size())
return data.at(index.column());
return QVariant();
}L’implémentation de la méthode ` data() ` constitue le cœur du modèle. Si les données demandées se trouvent dans le cache, la valeur mise en cache est utilisée ; sinon, les données sont récupérées depuis Outlook.
void AddressBookModel::changeItem(const QModelIndex &index, const QString &firstName, const QString &lastName, const QString &address, const QString &email)
{
Outlook::ContactItem item(folderItems->Item(index.row() + 1));
if (item.Class() != Outlook::OlObjectClass::olContact)
return; // Not a contact
item.SetFirstName(firstName);
item.SetLastName(lastName);
item.SetHomeAddress(address);
item.SetEmail1Address(email);
item.Save();
cache.take(index);
}Le slot ` changeItem() ` est appelé lorsque l’utilisateur modifie l’entrée actuelle via l’interface utilisateur. L’élément Outlook est accédé via l’API Outlook, puis modifié à l’aide des accesseurs de propriétés. Enfin, l’élément est enregistré dans Outlook et supprimé du cache. Notez que le modèle ne signale pas la modification des données à la vue, car Outlook émet lui-même un signal.
void AddressBookModel::addItem(const QString &firstName, const QString &lastName, const QString &address, const QString &email)
{
Outlook::ContactItem item(outlook.CreateItem(Outlook::olContactItem));
if (!item.isNull()) {
item.SetFirstName(firstName);
item.SetLastName(lastName);
item.SetHomeAddress(address);
item.SetEmail1Address(email);
item.Save();
}
}Le slot « addItem() » appelle la méthode CreateItem d’Outlook pour créer un nouvel élément de contact, définit les propriétés du nouvel élément selon les valeurs saisies par l’utilisateur et enregistre l’élément.
void AddressBookModel::update()
{
beginResetModel();
cache.clear();
endResetModel();
}Le slot ` update() ` vide le cache et émet le signal `reset()` pour informer la vue que la modification des données nécessite un rafraîchissement du contenu.
AddressView::AddressView(QWidget *parent)
: QWidget(parent)
{
QGridLayout *mainGrid = new QGridLayout(this);
QLabel *firstNameLabel = new QLabel(tr("First &Name"), this);
firstNameLabel->resize(firstNameLabel->sizeHint());
mainGrid->addWidget(firstNameLabel, 0, 0);
QLabel *lastNameLabel = new QLabel(tr("&Last Name"), this);
lastNameLabel->resize(lastNameLabel->sizeHint());
mainGrid->addWidget(lastNameLabel, 0, 1);
QLabel *addressLabel = new QLabel(tr("Add&ress"), this);
addressLabel->resize(addressLabel->sizeHint());
mainGrid->addWidget(addressLabel, 0, 2);
QLabel *emailLabel = new QLabel(tr("&E-Mail"), this);
emailLabel->resize(emailLabel->sizeHint());
mainGrid->addWidget(emailLabel, 0, 3);
m_addButton = new QPushButton(tr("A&dd"), this);
m_addButton->resize(m_addButton->sizeHint());
mainGrid->addWidget(m_addButton, 0, 4);
connect(m_addButton, &QPushButton::clicked, this, &AddressView::addEntry);
m_firstName = new QLineEdit(this);
m_firstName->resize(m_firstName->sizeHint());
mainGrid->addWidget(m_firstName, 1, 0);
firstNameLabel->setBuddy(m_firstName);
m_lastName = new QLineEdit(this);
m_lastName->resize(m_lastName->sizeHint());
mainGrid->addWidget(m_lastName, 1, 1);
lastNameLabel->setBuddy(m_lastName);
m_address = new QLineEdit(this);
m_address->resize(m_address->sizeHint());
mainGrid->addWidget(m_address, 1, 2);
addressLabel->setBuddy(m_address);
m_email = new QLineEdit(this);
m_email->resize(m_email->sizeHint());
mainGrid->addWidget(m_email, 1, 3);
emailLabel->setBuddy(m_email);
m_changeButton = new QPushButton(tr("&Change"), this);
m_changeButton->resize(m_changeButton->sizeHint());
mainGrid->addWidget(m_changeButton, 1, 4);
connect(m_changeButton, &QPushButton::clicked, this, &AddressView::changeEntry);
m_treeView = new QTreeView(this);
m_treeView->setSelectionMode(QTreeView::SingleSelection);
m_treeView->setRootIsDecorated(false);
model = new AddressBookModel(this);
m_treeView->setModel(model);
connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &AddressView::itemSelected);
mainGrid->addWidget(m_treeView, 2, 0, 1, 5);
}
void AddressView::updateOutlook()
{
model->update();
}
void AddressView::addEntry()
{
if (!m_firstName->text().isEmpty() || !m_lastName->text().isEmpty() ||
!m_address->text().isEmpty() || !m_email->text().isEmpty()) {
model->addItem(m_firstName->text(), m_lastName->text(), m_address->text(), m_email->text());
}
m_firstName->clear();
m_lastName->clear();
m_address->clear();
m_email->clear();
}
void AddressView::changeEntry()
{
QModelIndex current = m_treeView->currentIndex();
if (current.isValid())
model->changeItem(current, m_firstName->text(), m_lastName->text(), m_address->text(), m_email->text());
}
void AddressView::itemSelected(const QModelIndex &index)
{
if (!index.isValid())
return;
QAbstractItemModel *model = m_treeView->model();
m_firstName->setText(model->data(model->index(index.row(), 0)).toString());
m_lastName->setText(model->data(model->index(index.row(), 1)).toString());
m_address->setText(model->data(model->index(index.row(), 2)).toString());
m_email->setText(model->data(model->index(index.row(), 3)).toString());
}Le reste du fichier met en œuvre l'interface utilisateur en utilisant uniquement les API Qt, c'est-à-dire sans communiquer directement avec Outlook.
#include "addressview.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
AddressView view;
view.setWindowTitle(QObject::tr("Qt Example - Looking at Outlook"));
view.show();
return a.exec();
}La fonction d'entrée main() instancie enfin l'interface utilisateur et entre dans la boucle d'événements.
Pour compiler l'exemple, vous devez d'abord compiler la bibliothèque QAxContainer. Exécutez ensuite votre outil make dans le répertoire examples/activeqt/qutlook, puis lancez le fichier qutlook.exe ainsi généré.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.