必要なライブラリと環境:
- vcpkgパッケージマネージャー
- libcurl(HTTP通信用)
- cJSON(JSON解析用)
- Visual Studio 2022
実装の流れ
Bingの毎日更新される壁紙を自動で取得し、Windowsのデスクトップ背景に設定するプログラムを作成する。まず、Bingが提供している画像取得APIにアクセスする。
APIエンドポイント: https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN
このAPIにリクエストを送ると、画像のメタデータを含むJSONが返される。JSONの中からimages配列の最初の要素にあるurlフィールドを抽出し、ホスト名と結合すれば画像の完全URLが得られる。例: https://bing.com/th?id=OHR.HummingThistle_ZH-CN5057589905_1920x1080.jpg
その後、画像URLへリクエストを送りバイナリデータをファイルに保存し、最後にWindows APIを用いてデスクトップ壁紙を変更する。
実装コード
#include <iostream>
#include <string>
#include <ctime>
#include <curl/curl.h>
#include <cJSON/cJSON.h>
#include <Windows.h>
#include <direct.h>
#include <io.h>
// JSONレスポンスを収集するコールバック
size_t collectJsonData(void* contents, size_t elementSize, size_t elementCount, void* userData) {
std::string* collectedStr = static_cast<std::string*>(userData);
collectedStr->append(static_cast<char*>(contents), elementSize * elementCount);
return elementSize * elementCount;
}
// 画像データをファイルに書き込むコールバック
size_t saveImageData(void* contents, size_t elementSize, size_t elementCount, void* fileHandle) {
FILE* output = static_cast<FILE*>(fileHandle);
fwrite(contents, elementSize, elementCount, output);
return elementSize * elementCount;
}
// Bing APIから画像URLを抽出
std::string fetchWallpaperUrl() {
const std::string apiEndpoint = "https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&uhd=1&uhdwidth=3840&uhdheight=2160&mkt=zh-CN";
std::string jsonResponse;
CURL* session = curl_easy_init();
if (!session) return "";
curl_easy_setopt(session, CURLOPT_URL, apiEndpoint.c_str());
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, collectJsonData);
curl_easy_setopt(session, CURLOPT_WRITEDATA, &jsonResponse);
curl_easy_perform(session);
curl_easy_cleanup(session);
cJSON* root = cJSON_Parse(jsonResponse.c_str());
cJSON* imageArr = cJSON_GetObjectItem(root, "images");
cJSON* firstItem = cJSON_GetArrayItem(imageArr, 0);
cJSON* urlField = cJSON_GetObjectItem(firstItem, "url");
std::string fullUrl = "https://bing.com" + std::string(urlField->valuestring);
cJSON_Delete(root);
return fullUrl;
}
// 日付ベースのファイルパス生成
std::string generateFilePath() {
time_t currentTime;
time(¤tTime);
struct tm localTime;
localtime_s(&localTime, ¤tTime);
std::string fileName = "wallpapers/bing-"
+ std::to_string(localTime.tm_year + 1900) + "-"
+ std::to_string(localTime.tm_mon + 1) + "-"
+ std::to_string(localTime.tm_mday) + ".jpg";
return fileName;
}
// 保存ディレクトリの準備とファイルオープン
FILE* prepareOutputFile() {
std::string filePath = generateFilePath();
if (_access("wallpapers", 0) == -1) {
_mkdir("wallpapers");
std::cout << "wallpapersディレクトリを作成しました" << std::endl;
}
FILE* filePtr;
if (fopen_s(&filePtr, filePath.c_str(), "wb") != 0) {
std::cout << "ファイルオープン失敗" << std::endl;
return nullptr;
}
std::cout << "ファイルオープン成功、ダウンロード開始" << std::endl;
return filePtr;
}
// 壁紙画像のダウンロード
bool downloadWallpaper(const std::string& imageUrl) {
FILE* targetFile = prepareOutputFile();
if (!targetFile) return false;
CURL* session = curl_easy_init();
curl_easy_setopt(session, CURLOPT_URL, imageUrl.c_str());
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, saveImageData);
curl_easy_setopt(session, CURLOPT_WRITEDATA, targetFile);
curl_easy_perform(session);
curl_easy_cleanup(session);
fclose(targetFile);
std::cout << "ダウンロード完了、壁紙設定開始" << std::endl;
return true;
}
// デスクトップ壁紙の変更
void applyDesktopWallpaper() {
char currentPath[MAX_PATH];
getcwd(currentPath, MAX_PATH);
std::string imagePath = std::string(currentPath) + "\\" + generateFilePath();
std::cout << "画像パス: " << imagePath << std::endl;
SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0,
(PVOID)imagePath.c_str(), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
std::cout << "壁紙設定完了" << std::endl;
}
int main() {
std::string imgUrl = fetchWallpaperUrl();
if (downloadWallpaper(imgUrl)) {
applyDesktopWallpaper();
}
return 0;
}