項目需要實現程序自動更新功能。經調研,libcurl 作為成熟的跨平台網絡傳輸庫,支持 HTTP/HTTPS/FTP 等協議,API 靈活,適合嵌入 C++ 應用。結合 wxWidgets GUI 框架,可構建跨平台的下載對話框與進度顯示。
wxTimer 定時觸發下載邏輯,實現「後台下載 + 前台刷新進度」的並發模型。CURLOPT_PROGRESSFUNCTION 回調,實時傳遞已下載/總大小,映射到 wxGauge 進度條。CURLOPT_WRITEFUNCTION,將數據直接寫入本地文件,避免內存緩衝大文件。class downloadDialog : public GUIDialog {
public:
downloadDialog(wxDialog* dlg);
~downloadDialog();
void OnTimer(wxTimerEvent& event); // 定時器事件處理
private:
virtual void OnClose(wxCloseEvent& event);
virtual void OnQuit(wxCommandEvent& event);
virtual void OnAbout(wxCommandEvent& event);
void downloadfile(); // 核心下載邏輯
wxTimer* m_timerdown; // 定時器對象
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(downloadDialog, GUIDialog)
EVT_TIMER(TIMER_ID, downloadDialog::OnTimer)
END_EVENT_TABLE()
downloadDialog::downloadDialog(wxDialog* dlg) : GUIDialog(dlg) {
m_timerdown = new wxTimer(this, TIMER_ID);
m_timerdown->Start(100); // 100ms 觸發一次
}
struct FtpFile {
const char* filename;
FILE* stream;
};
int my_fwrite(void* buffer, size_t size, size_t nmemb, void* stream) {
FtpFile* out = (FtpFile*)stream;
if (out && !out->stream) {
out->stream = fopen(out->filename, "wb");
if (!out->stream) return -1;
}
return fwrite(buffer, size, nmemb, out->stream);
}
int wxcurldav_dl_progress_func(void* ptr, double total, double now, double, double) {
wxGauge* gauge = (wxGauge*)ptr;
if (gauge && total > 0) {
gauge->SetValue(int(100.0 * now / total));
}
return 0; // 返回非 0 可取消傳輸
}
void downloadDialog::downloadfile() {
CURL* curl = curl_easy_init();
if (!curl) return;
FtpFile ftpfile = {"tmp.exe", NULL};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/update.exe");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, wxcurldav_dl_progress_func);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, m_gauge1); // wxGauge 控件指針
m_gauge1->SetValue(0);
CURLcode res = curl_easy_perform(curl);
m_gauge1->SetValue(100);
curl_easy_cleanup(curl);
if (ftpfile.stream) fclose(ftpfile.stream);
curl_global_cleanup();
m_timerdown->Stop(); // 關鍵:停止定時器防止重複執行
if (res == CURLE_OK) {
wxExecute("tmp.exe"); // 啟動安裝程序
wxMessageBox("下載完成,啟動更新程序...");
}
}

libcurl、wxWidgets,Windows 下注意 DLL 部署。wxThread 替代 wxTimer 實現真正的後台下載線程,配合 wxPostEvent 更新 UI。CURLOPT_RESUME_FROM_LARGE)與多線程分段下載。Downloader 類,解耦業務邏輯與 UI 框架。