スクリーンセーバーとして動作するアプリケーションには scrnsave.h をインクルードして、scrnsavw.lib をリンクしておきます。
(マルチバイト文字セットでコンパイル場合は scrnsave.lib をリンクしてください)
ScreenSaverProc がスクリーンセーバーのメイン関数になります。
コンパイル後の出力ファイルの拡張子は scr にします。
#include <windows.h>
#include <scrnsave.h>
#ifdef UNICODE
#pragma comment(lib, "scrnsavw.lib")
#else
#pragma comment(lib, "scrnsave.lib")
#endif
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "comctl32.lib")
#define WM_USER_TIMER WM_USER + 1
void CALLBACK TimeProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
LONG timerFlag = 0;
//スクリーンセーバーメイン関数
LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static UINT timer;
switch (message) {
case WM_CREATE:
{
//タイマー設定
timeBeginPeriod(1);
timer = timeSetEvent(100, 1, TimeProc, reinterpret_cast<DWORD_PTR>(hWnd), TIME_PERIODIC);
}
break;
case WM_ERASEBKGND:
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
//TODO: ここに描画処理を記述します。
EndPaint(hWnd, &ps);
}
break;
case WM_USER_TIMER:
{
//TODO: ここにタイマー処理を記述します。
//再描画
InvalidateRect(hWnd, NULL, FALSE);
InterlockedExchange(&timerFlag, 0);
}
break;
case WM_DESTROY:
{
//タイマー破棄
timeKillEvent(timer);
timeEndPeriod(1);
}
break;
default:
return DefScreenSaverProc(hWnd, message, wParam, lParam);
}
return 0;
}
void CALLBACK TimeProc(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR)
{
if(InterlockedExchange(&timerFlag, 1) == 0) {
PostMessage(reinterpret_cast<HWND>(dwUser), WM_USER_TIMER, static_cast<WPARAM>(uTimerID), 0);
}
}
BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
UNREFERENCED_PARAMETER(hInst);
return TRUE;
}
//スクリーンセーバー設定ダイアログボックス
//(ダイアログの ID は scrnsave.h の DLG_SCRNSAVECONFIGURE)
BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message) {
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hWnd, IDOK);
break;
case IDCANCEL:
EndDialog(hWnd, IDCANCEL);
break;
default:
return FALSE;
break;
}
}
break;
default:
return FALSE;
break;
}
return TRUE;
}