Qutlook 예제(ActiveQt)
Qutlook 예제는 ActiveQt를 사용하여 Outlook을 자동화하는 방법을 보여줍니다. 이 예제에서는 dumpcpp 도구를 사용하여 Outlook 개체 모델을 설명하는 유형 라이브러리에 대한 C++ 네임스페이스를 생성합니다.
이 예제의 프로젝트 파일은 다음과 같습니다:
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 }
프로젝트 파일은 dumpcpp
도구를 사용하여 프로젝트에 MS Outlook 유형 라이브러리를 추가합니다. 이 작업이 실패하면 생성된 메이크파일은 오류 메시지를 인쇄하고, 그렇지 않으면 빌드 단계에서 유형 라이브러리에서 dumpcpp 도구를 실행하여 헤더와 cpp 파일(이 경우 msoutl.h
및 msoutl.cpp
)을 생성하여 Outlook 객체에 사용하기 쉬운 API를 선언하고 구현합니다.
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; };
AddressView 클래스는 사용자 인터페이스를 위한 QWidget 서브클래스입니다. QTreeView 위젯은 model
에서 제공하는 대로 Outlook의 연락처 폴더의 콘텐츠를 표시합니다.
#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; };
AddressBookModel 클래스는 QAbstractListModel 하위 클래스로, 캐싱을 위해 QHash 을 사용하여 Outlook과 직접 통신합니다.
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; } }
생성자는 Outlook을 초기화합니다. Outlook에서 콘텐츠 변경 사항을 알리기 위해 제공하는 다양한 신호는 updateOutlook()
슬롯에 연결됩니다.
AddressBookModel::~AddressBookModel() { delete folderItems; if (!outlook.isNull()) Outlook::NameSpace(outlook.Session()).Logoff(); }
소멸자는 세션에서 로그오프합니다.
int AddressBookModel::rowCount(const QModelIndex &) const { return folderItems ? folderItems->Count() : 0; } int AddressBookModel::columnCount(const QModelIndex & /*parent*/) const { return 4; }
rowCount()
구현은 Outlook에서 보고한 항목 수를 반환합니다. columnCount
및 headerData
구현은 트리 보기에 4개의 열을 표시하도록 구현됩니다.
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(); }
headerData()
구현은 하드코딩된 문자열을 반환합니다.
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(); }
data()
구현은 모델의 핵심입니다. 요청된 데이터가 캐시에 있으면 캐시된 값이 사용되며, 그렇지 않으면 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); }
changeItem()
슬롯은 사용자가 사용자 인터페이스를 사용하여 현재 항목을 변경할 때 호출됩니다. Outlook 항목은 Outlook API를 사용하여 액세스하고 속성 설정자를 사용하여 수정합니다. 마지막으로 항목이 Outlook에 저장되고 캐시에서 제거됩니다. Outlook에서 자체적으로 신호를 보내므로 모델에서는 데이터 변경 보기에 대한 신호를 보내지 않습니다.
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(); } }
addItem()
슬롯은 Outlook의 CreateItem 메서드를 호출하여 새 연락처 항목을 만들고, 새 항목의 속성을 사용자가 입력한 값으로 설정한 다음 항목을 저장합니다.
void AddressBookModel::update() { beginResetModel(); cache.clear(); endResetModel(); }
update()
슬롯은 캐시를 지우고, 내용을 다시 그려야 하는 데이터 변경을 뷰에 알리기 위해 reset() 신호를 내보냅니다.
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()); }
나머지 파일은 Outlook과 직접 통신하지 않고 Qt API만을 사용하여 사용자 인터페이스를 구현합니다.
#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(); }
main()
진입점 함수는 최종적으로 사용자 인터페이스를 인스턴스화하고 이벤트 루프로 들어갑니다.
이 예제를 빌드하려면 먼저 QAxContainer 라이브러리를 빌드해야 합니다. 그런 다음 examples/activeqt/qutlook
에서 make 도구를 실행하고 결과물인 qutlook.exe
을 실행합니다.
© 2025 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.