// Visual Studio 2022 C++报时程序(语音闹钟)
#define _WIN32_WINNT 0x0A00 // 指定Windows版本(Windows 10),用于启用对应版本的API
#include <windows.h> // 包含Windows API的头文件
#include <mmsystem.h> // 包含Windows多媒体系统功能(如声音播放)
#include <ctime> // 时间处理函数的标准库头文件
#include <string> // C++字符串库
#include <sapi.h> // Microsoft语音API接口头文件
#pragma comment(lib, "sapi.lib") // 链接SAPI语音库
#pragma comment(lib, "Winmm.lib") // 链接Windows多媒体库
// 定义定时器标识符
#define TIMER_MINUTE 1 // 每分钟报时的定时器
#define TIMER_SECOND 2 // 每10秒报秒数的定时器
#define TIMER_SOUND 3 // 播放提示音的定时器
ISpVoice* g_pVoice = nullptr; // 全局语音接口指针
// 播放指定路径的声音文件
void PlaySoundFile(const char* file) {
PlaySoundA(file, nullptr, SND_FILENAME | SND_ASYNC); // 异步播放声音文件
}
// 使用SAPI朗读文本(宽字符串)
void Speak(const std::wstring& text) {
if (g_pVoice && !text.empty()) { // 检查语音接口是否有效且文本不为空
g_pVoice->Speak(text.c_str(), SPF_ASYNC, nullptr); // 异步朗读指定文本
}
}
// 获取当前时间(可包含日期)
std::wstring GetCurrentTimeText(bool withDate = false) {
time_t now = time(nullptr); // 获取当前系统时间
tm t;
localtime_s(&t, &now); // 将系统时间转换为本地时间
wchar_t buffer[128];
if (withDate)
swprintf_s(buffer, L"%d月%d日,%d点%d分", t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min); // 含日期的格式
else
swprintf_s(buffer, L"%d点%d分", t.tm_hour, t.tm_min); // 不含日期的格式
return buffer; // 返回格式化后的时间字符串
}
// 获取当前秒数
std::wstring GetCurrentSecondText() {
time_t now = time(nullptr); // 获取当前系统时间
tm t;
localtime_s(&t, &now); // 转换为本地时间
wchar_t buffer[32];
// swprintf_s(buffer, L"%d秒", t.tm_sec); // 格式化秒数
swprintf_s(buffer, L"%d", t.tm_sec); // 格式化秒数
return buffer; // 返回秒数字符串
}
// 窗口过程回调函数,处理窗口消息
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_CREATE:
// 创建“报时”按钮
CreateWindow(L"BUTTON", L"报时", WS_VISIBLE | WS_CHILD,
20, 20, 100, 30, hwnd, (HMENU)101, nullptr, nullptr);
// 创建“报日期”按钮
CreateWindow(L"BUTTON", L"报日期", WS_VISIBLE | WS_CHILD,
140, 20, 100, 30, hwnd, (HMENU)102, nullptr, nullptr);
// 设置定时器
SetTimer(hwnd, TIMER_MINUTE, 60000, nullptr); // 每分钟报时
// SetTimer(hwnd, TIMER_SECOND, 10000, nullptr); // 每10秒报秒数
// SetTimer(hwnd, TIMER_SOUND, 10000, nullptr); // 每10秒播放声音文件
SetTimer(hwnd, 4, 1000, nullptr); // 每秒触发一次(可选)
break;
case WM_COMMAND:
// 按钮点击事件处理
if (LOWORD(wp) == 101) Speak(GetCurrentTimeText()); // 点击报时按钮
if (LOWORD(wp) == 102) Speak(GetCurrentTimeText(true)); // 点击报日期按钮
break;
case WM_TIMER:
// 定时器触发事件
if (wp == TIMER_MINUTE) Speak(GetCurrentTimeText()); // 每分钟报时
// if (wp == TIMER_SECOND) Speak(GetCurrentSecondText()); // 每10秒报秒数
// if (wp == TIMER_SOUND) PlaySoundFile("e:\\xm3624.wav"); // 每10秒播放声音文件
if (wp == 4) { //if1100 每秒触发一次
// 可以在这里添加每秒需要执行的操作
//检查当前秒数是否为整秒,比如00,10,20,30,40,50
//如果是整秒,则执行相应操作
time_t now = time(nullptr); // 获取当前系统时间
tm t;
localtime_s(&t, &now); // 转换为本地时间
//例如:Speak(L"整秒到达");
if (0 == t.tm_sec % 10) { // 如果当前秒数是整秒
Speak(GetCurrentSecondText()); // 每秒报秒数
// Speak(L"整秒到达"); // 每秒报整秒到达
}
}//if1100
break;
case WM_DESTROY:
// 窗口关闭时销毁定时器并退出程序
KillTimer(hwnd, TIMER_MINUTE);
KillTimer(hwnd, TIMER_SECOND);
KillTimer(hwnd, TIMER_SOUND);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wp, lp); // 默认处理其他消息
}
return 0;
}
// 程序主入口函数
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) {
CoInitialize(nullptr); // 初始化COM库
// 创建语音接口
if (FAILED(CoCreateInstance(CLSID_SpVoice, nullptr, CLSCTX_ALL, IID_ISpVoice, (void**)&g_pVoice))) {
MessageBox(nullptr, L"初始化语音失败", L"错误", MB_OK);
return -1;
}
// 注册窗口类
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc; // 指定窗口过程函数
wc.hInstance = hInst; // 程序实例句柄
wc.lpszClassName = L"VoiceClock"; // 窗口类名称
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 窗口背景颜色
RegisterClass(&wc); // 注册窗口类
// 创建主窗口
HWND hwnd = CreateWindow(L"VoiceClock", L"语音报时程序", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 280, 150, nullptr, nullptr, hInst, nullptr);
ShowWindow(hwnd, nCmdShow); // 显示窗口
UpdateWindow(hwnd); // 更新窗口
// 消息循环
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg); // 转换消息
DispatchMessage(&msg); // 分派消息
}
// 释放语音接口资源
if (g_pVoice) g_pVoice->Release();
CoUninitialize(); // 反初始化COM库
return (int)msg.wParam; // 返回消息循环结果
}