突然画像ウインドウを表示するプログラム

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

【実行例】
wa_bmp

純粋な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);
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です