标签:
#include <QApplication> #include <QFileDialog> #include <QLineEdit> #include <QPushButton> #include <QLabel> #include <QGridLayout> #include <QThread> #include <QPointer> #include <QStateMachine> #include <windows.h> static QString getLastErrorMsg() { LPWSTR bufPtr = NULL; DWORD err = GetLastError(); FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPWSTR)&bufPtr, 0, NULL); const QString result = (bufPtr) ? QString::fromUtf16((const ushort*)bufPtr).trimmed() : QString("Unknown Error %1").arg(err); LocalFree(bufPtr); return result; } class CopierWorker : public QThread { // only to be used by the Copier object BOOL m_stop; QString m_src, m_dst; QPointer<QObject> m_object; static DWORD CALLBACK copyProgress( LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred, DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst, LPVOID data) { Q_UNUSED(streamSize) Q_UNUSED(streamTransferred) Q_UNUSED(streamNo) Q_UNUSED(callbackReason) Q_UNUSED(src) Q_UNUSED(dst) QObject * object = static_cast<QObject*>(data); const QString text = QString("Transferred %1 of %2 bytes"). arg(totalTransferred.QuadPart).arg(totalSize.QuadPart); QMetaObject::invokeMethod(object, "newStatus", Qt::QueuedConnection, Q_ARG(QString, text)); return PROGRESS_CONTINUE; } void run() { m_stop = FALSE; BOOL rc = CopyFileExW((LPCWSTR)m_src.utf16(), (LPCWSTR)m_dst.utf16(), ©Progress, m_object, &m_stop, 0); if (!rc) { QMetaObject::invokeMethod(m_object, "newStatus", Qt::QueuedConnection, Q_ARG(QString, getLastErrorMsg())); } } CopierWorker(const QString & src, const QString & dst, QObject * obj) : m_src(src), m_dst(dst), m_object(obj) {} void stop() { m_stop = TRUE; } friend class Copier; }; class Copier : public QObject { Q_OBJECT QPointer<CopierWorker> m_worker; public: Copier(const QString & src, const QString & dst) : m_worker(new CopierWorker(src, dst, this)) { connect(m_worker, SIGNAL(finished()), SIGNAL(finished())); connect(m_worker, SIGNAL(finished()), m_worker, SLOT(deleteLater())); } ~Copier() { if (!m_worker) return; m_worker->stop(); if (!m_worker->isRunning()) delete m_worker; } Q_SIGNAL void newStatus(const QString &); Q_SIGNAL void finished(); Q_SLOT void stop() { m_worker->stop(); } void copy() { m_worker->start(); } }; class Widget : public QWidget { Q_OBJECT QLabel * m_status; QLineEdit * m_src, * m_dst; Q_SIGNAL void stopCopy(); Q_SLOT void startCopy() { Copier * copier = new Copier(m_src->text(), m_dst->text()); connect(copier, SIGNAL(newStatus(QString)), m_status, SLOT(setText(QString))); connect(copier, SIGNAL(finished()), SIGNAL(copyFinished())); connect(this, SIGNAL(stopCopy()), copier, SLOT(stop())); copier->copy(); } Q_SIGNAL void copyFinished(); public: Widget(QWidget * parent = 0) : QWidget(parent) { QGridLayout * layout = new QGridLayout(this); m_src = new QLineEdit; m_dst = new QLineEdit; QPushButton * srcButton = new QPushButton("..."); QPushButton * dstButton = new QPushButton("..."); QPushButton * copy = new QPushButton("Copy"); QPushButton * cancel = new QPushButton("Cancel"); QFileDialog * getSrc = new QFileDialog(this, "Source File"); QFileDialog * getDst = new QFileDialog(this, "Source File"); m_status = new QLabel; layout->addWidget(new QLabel("From:"), 0, 0, 1, 1, Qt::AlignRight); layout->addWidget(m_src, 0, 1, 1, 1); layout->addWidget(srcButton, 0, 2, 1, 1); layout->addWidget(new QLabel("To:"), 1, 0, 1, 1, Qt::AlignRight); layout->addWidget(m_dst, 1, 1, 1, 1); layout->addWidget(dstButton, 1, 2, 1, 1); layout->addWidget(m_status, 2, 0, 1, 3); layout->addWidget(copy, 3, 0, 1, 3, Qt::AlignCenter); layout->addWidget(cancel, 4, 0, 1, 3, Qt::AlignCenter); getSrc->setFileMode(QFileDialog::ExistingFile); getDst->setAcceptMode(QFileDialog::AcceptSave); connect(srcButton, SIGNAL(clicked()), getSrc, SLOT(show())); connect(dstButton, SIGNAL(clicked()), getDst, SLOT(show())); connect(getSrc, SIGNAL(fileSelected(QString)), m_src, SLOT(setText(QString))); connect(getDst, SIGNAL(fileSelected(QString)), m_dst, SLOT(setText(QString))); QStateMachine * machine = new QStateMachine(this); QState * stopped = new QState(machine); QState * copying = new QState(machine); machine->setInitialState(stopped); stopped->addTransition(copy, SIGNAL(clicked()), copying); stopped->assignProperty(copy, "enabled", true); stopped->assignProperty(cancel, "enabled", false); copying->addTransition(cancel, SIGNAL(clicked()), stopped); copying->addTransition(this, SIGNAL(copyFinished()), stopped); connect(copying, SIGNAL(entered()), SLOT(startCopy())); connect(copying, SIGNAL(exited()), SIGNAL(stopCopy())); copying->assignProperty(copy, "enabled", false); copying->assignProperty(cancel, "enabled", true); machine->start(); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); } #include "main.moc"
get progress Using CopyFileExW in Qt
标签:
原文地址:http://my.oschina.net/leon0407/blog/395531