こんにちは、武田です。
ジョークプログラムを作りました。
ランダムでプログラム内で指定した画像を30秒以内に表示します。
【実行例】

純粋なC言語ではありませんが、BorlandのC++コンパイラーでコンパイルできました。
bcc32 -W wa_bmp.c
でコンパイルします。
実行ファイルと同じフォルダにBMP形式の画像を置いて下さい。
画像ファイル名はプログラムから指定します。
WindowsAPIというWindowsの画像処理やウインドウ操作ができる関数を使っています。昔からある関数群ですが、面白いことができそうです。
ソースファイル【wa_bmp.c】
/* Wa! BMP version (c)Shuichi Takeda, 2014 */
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#define ID_TIMER 1
#define TIMER_MAX 30 // タイマーの秒数(1~30秒)
#define FILENAME TEXT("coolJapan.bmp") // 描画する画像ファイル
RECT rcDisplay; // デスクトップサイズ取得用
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR appName[] = TEXT("Wa!");
HWND hWnd, hDeskTopWnd;
MSG msg;
WNDCLASS wndclass;
// デスクトップのサイズを取得
hDeskTopWnd = GetDesktopWindow();
GetWindowRect(hDeskTopWnd, &rcDisplay);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = appName;
if(!RegisterClass(&wndclass)){
MessageBox(NULL, TEXT("ウインドウクラスの作成に失敗しました"),
NULL, MB_OK);
return 0;
}
hWnd = CreateWindow(appName, TEXT("Wa!"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if(hWnd == NULL){
MessageBox(NULL, TEXT("ウインドウの作成に失敗しました"), NULL, MB_OK);
return 0;
}
ShowWindow(hWnd, 0);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0)>0){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hb; // ビットマップハンドル
PAINTSTRUCT ps;
static BITMAP bp; // ビットマップ構造体
static HDC mhdc; // メモリデバイスコンテキスト
HDC hdc;
int timer;
int centerX, centerY;
srand((unsigned)time(NULL));
timer = (rand() % TIMER_MAX) + 1; // 何秒後に表示するか?
switch(message){
case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);
DeleteObject(hb); // ビットマップハンドルを削除
DeleteDC(mhdc); // メモリデバイスコンテキストを破棄
PostQuitMessage(0);
return 0;
case WM_CREATE:
hdc = GetDC(hwnd);
mhdc = CreateCompatibleDC(hdc);
ReleaseDC(hwnd, hdc);
// ファイル読み込み
hb = (HBITMAP)LoadImage(NULL, FILENAME, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
// メモリデバイスコンテキストにビットマップを設定
SelectObject(mhdc, hb);
// 画像サイズ取得
GetObject(hb, sizeof(BITMAP), &bp);
// 実行タイマーセット
SetTimer(hwnd, ID_TIMER, timer * 1000, NULL);
return 0;
case WM_TIMER:
MessageBeep(-1);
KillTimer(hwnd, ID_TIMER);
InvalidateRect(hwnd, NULL, FALSE);
ShowWindow(hwnd, 3); // ウインドウ最大化
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
// センター座標計算
centerX = rcDisplay.right / 2 - bp.bmWidth / 2;
centerY = rcDisplay.bottom / 2 - bp.bmHeight / 2;
// 画像が大きすぎる場合は、左上に表示
if(bp.bmWidth >= rcDisplay.right || bp.bmHeight >= rcDisplay.bottom) centerX = centerY = 0;
// 画像描画
BitBlt(hdc, centerX, centerY, bp.bmWidth, bp.bmHeight, mhdc, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}