こんにちは、武田です。
ジョークプログラムを作りました。
ランダムでプログラム内で指定した画像を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); }