開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 TestPlayer
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト
文字セット Unicode

参考

TestPlayer.cpp
// Unicode文字セット
#pragma comment(lib, "strmiids.lib")
 
#include <DShow.h>
#include <evr.h>
#include <CommCtrl.h>
#include "resource.h"
 
#define SAFE_RELEASE(x) { if (x) { x->Release(); x = NULL; } }
#define LTRB(rect) rect.left, rect.top, rect.right, rect.bottom
 
#define CLASS_NAME TEXT("TestPlayer")
#define WINDOW_NAME TEXT("TestPlayer")
#define PANEL_H 32	// パネルの高さ
#define THUMB_W 16	// つまみの幅
#define TIMER1 1	// シーク時間定期描画
#define TIMER2 2	// コントロール遅延描画
#define WM_GRAPHNOTIFY (WM_APP + 1)
 
enum Ctrl {VIDEO, PLAY, STOP, SEEK, MESSAGE, VOLUME, PANEL, CTRL_NUM};
enum State {NO_FILE, STOPPED, PAUSED, RUNNING};
 
// 関数プロトタイプ宣言
HWND CreateWnd(HINSTANCE hInstance, int nCmdShow);
void Trace(LPCTSTR format, ...);
 
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnTimer(HWND hWnd, WPARAM wParam);
void UpdateSeek(HWND hWnd);
void DrawSeek(HDC hdc);
BOOL OnCommand(HWND hWnd, WPARAM wParam);
void SeekFrame(HWND hWnd, WORD wID);
void OnGraphNotify(HWND hWnd);
void OnLButtonDown(HWND hWnd, LPARAM lParam);
void OnLButtonUp(HWND hWnd, LPARAM lParam);
int HitTest(POINT pt);
void OnPlay(HWND hWnd);
void OnStop(HWND hWnd);
void StartTimer(HWND hWnd);
void StopTimer(HWND hWnd);
void OnPaint(HWND hWnd);
void OnSize(HWND hWnd, WPARAM wParam, LPARAM lParam);
void OnDropFiles(HWND hWnd, WPARAM wParam);
void OnCreate(HWND hWnd);
void InitGraph(HWND hWnd);
void ReleaseGraph(HWND hWnd);
 
HRESULT OpenFile(HWND hWnd, LPCWSTR pszFileName);
HRESULT InitEvr(HWND hWnd);
void AdjustWnd(HWND hWnd, int nMode);
 
// 外部変数構造体
static struct {
	TCHAR szPath[MAX_PATH];	// 動画ファイルのフルパス
	TCHAR szFile[MAX_PATH];	// 動画ファイル名
	RECT rc[CTRL_NUM];	// コントロール領域
	BOOL bMouseCap;		// マウスキャプチャフラグ
	int nCtrl;		// クリックされたコントロール
	State state;		// 状態フラグ
	UINT_PTR uIDEvent;	// タイマID
	int nRange;		// シーク範囲
	LONGLONG llCurr;	// 動画の現在時間
	LONGLONG llEnd;		// 動画の終了時間
	TCHAR szEnd[11+1];	// 動画の終了時間 00:00:00.00
	SIZE size;		// 動画の幅と高さ
 
	IGraphBuilder *pGraph;
	IMediaControl *pControl;
	IMediaSeeking *pSeek;
	IMediaEventEx *pEvent;
	IMFVideoDisplayControl *pVideo;
} g;
 
//==============================================================================
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	HWND hWnd;
	MSG msg;
	HACCEL hAccTable;
	LPTSTR pszCmdLine;
	LPTSTR *argv;
	int argc;
	HRESULT hr;
 
	// COMライブラリの初期化
	hr = CoInitialize(NULL);
	if (FAILED(hr)) {
		return 0;
	}
 
	msg.wParam = 0;	// ウィンドウ作成失敗時の戻り値
	g.size.cx = 640;
	g.size.cy = 480;
 
	// コマンド引数の取得
	pszCmdLine = GetCommandLine();
	argv = CommandLineToArgvW(pszCmdLine, &argc);
	if (2 <= argc) {
		wcscpy_s(g.szPath, argv[1]);
	}
 
	// ウィンドウの作成
	hWnd = CreateWnd(hInstance, nCmdShow);
	if (hWnd == NULL) {
		goto Exit;
	}
 
	// メッセージループ
	hAccTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_MAIN));
	while (GetMessage(&msg, NULL, 0, 0)) {
		if (TranslateAccelerator(msg.hwnd, hAccTable, &msg) == 0) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
Exit:
	CoUninitialize();
	return msg.wParam;
}
 
//------------------------------------------------------------------------------
HWND CreateWnd(HINSTANCE hInstance, int nCmdShow)
{
	WNDCLASSEX wcx;
	HWND hWnd;
 
	// ウィンドウクラスの登録
	ZeroMemory(&wcx, sizeof wcx);
	wcx.cbSize		= sizeof wcx;
	wcx.style		= CS_HREDRAW | CS_VREDRAW;
	wcx.lpfnWndProc		= MainWndProc;
	wcx.hInstance		= hInstance;
	wcx.hCursor		= LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	wcx.hbrBackground	= (HBRUSH)(COLOR_BTNFACE + 1);
	wcx.lpszClassName	= CLASS_NAME;
	if (RegisterClassEx(&wcx) == 0) {
		return NULL;
	}
 
	// ウィンドウの作成
	hWnd = CreateWindowEx(
		WS_EX_ACCEPTFILES,
		CLASS_NAME, WINDOW_NAME,
		WS_OVERLAPPEDWINDOW,
//		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
		100, 100, g.size.cx, g.size.cy,
		NULL, NULL, hInstance, NULL);
	if (hWnd) {
		ShowWindow(hWnd, nCmdShow);
		UpdateWindow(hWnd);
	}
	return hWnd;
}
 
//------------------------------------------------------------------------------
void Trace(LPCTSTR format, ...)
{
	va_list arg_ptr;
	TCHAR buffer[256];
	int size;
 
	va_start(arg_ptr, format);
	size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr);
	va_end(arg_ptr);
	OutputDebugString(buffer);
	if (size < 0) {
		OutputDebugString(L"...\n");
	}
}
 
//==============================================================================
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {
	case WM_TIMER:
		OnTimer(hWnd, wParam);
		break;
	case WM_COMMAND:
		if (OnCommand(hWnd, wParam) == FALSE) {
			return DefWindowProc(hWnd, uMsg, wParam, lParam);
		}
		break;
	case WM_GRAPHNOTIFY:
		OnGraphNotify(hWnd);
		break;
	case WM_LBUTTONDOWN:
		OnLButtonDown(hWnd, lParam);
		break;
	case WM_LBUTTONUP:
		OnLButtonUp(hWnd, lParam);
		break;
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_SIZE:
		OnSize(hWnd, wParam, lParam);
		break;
	case WM_DROPFILES:
		OnDropFiles(hWnd, wParam);
		DragFinish((HDROP)wParam);
		break;
	case WM_CREATE:
		OnCreate(hWnd);
		break;
	case WM_DESTROY:
		ReleaseGraph(hWnd);
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	return 0;
}
 
//------------------------------------------------------------------------------
void OnTimer(HWND hWnd, WPARAM wParam)
{
	switch (wParam) {
	case TIMER1:
		if (g.pSeek) {
			g.pSeek->GetCurrentPosition(&g.llCurr);
			UpdateSeek(hWnd);
		}
		break;
	case TIMER2:
		InvalidateRect(hWnd, &g.rc[PANEL], TRUE);
		KillTimer(hWnd, wParam);
		break;
	}
}
 
//------------------------------------------------------------------------------
void UpdateSeek(HWND hWnd)
{
	HDC hdc;
 
	hdc = GetDC(hWnd);
	DrawSeek(hdc);
	ReleaseDC(hWnd, hdc);
}
 
//------------------------------------------------------------------------------
void DrawSeek(HDC hdc)
{
	HBRUSH hBrush;
	RECT rc;
	int nPos;
 
	hBrush = GetSysColorBrush(COLOR_BTNFACE);
	SelectObject(hdc, hBrush);
	SetBkMode(hdc, TRANSPARENT);
 
	Rectangle(hdc, LTRB(g.rc[SEEK]));
	Rectangle(hdc, LTRB(g.rc[MESSAGE]));
	if (g.state == NO_FILE) {
		return;
	}
 
	// シークバー
	nPos = (int)(g.nRange * g.llCurr / g.llEnd);
	nPos += g.rc[SEEK].left;
	SetRect(&rc, nPos, g.rc[SEEK].top, nPos + THUMB_W, g.rc[SEEK].bottom);
	Rectangle(hdc, LTRB(rc));
 
	// メッセージ
	TCHAR szBuf[26+1];
	int nCurr;
	nCurr = (int)(g.llCurr / 100000LL);
	swprintf_s(szBuf, L" %02d:%02d:%02d.%02d / %s",
		nCurr / 360000, (nCurr / 6000) % 60, (nCurr / 100) % 60, nCurr % 100, g.szEnd);
	DrawText(hdc, szBuf, -1, &g.rc[MESSAGE], DT_SINGLELINE | DT_VCENTER);
}
 
//------------------------------------------------------------------------------
BOOL OnCommand(HWND hWnd, WPARAM wParam)
{
	WORD wID = LOWORD(wParam);
 
	switch (wID) {
	case ID_ENTER:
		ShowWindow(hWnd, IsZoomed(hWnd) ? SW_SHOWNOACTIVATE : SW_MAXIMIZE);
		break;
	case ID_ESCAPE:
		DestroyWindow(hWnd);
		break;
	case ID_PLAY:
		OnPlay(hWnd);
		break;
	case ID_LEFT: case ID_LEFT_CTRL: case ID_LEFT_SHIFT:
	case ID_RIGHT: case ID_RIGHT_CTRL: case ID_RIGHT_SHIFT:
		SeekFrame(hWnd, wID);
		break;
	case ID_NUM1: case ID_NUM2: case ID_NUM3: case ID_NUM4:
		AdjustWnd(hWnd, (wID - ID_NUM1) + 1);
		break;
	case ID_STOP:
		OnStop(hWnd);
		break;
	default:
		return FALSE;
	}
	return TRUE;
}
 
//------------------------------------------------------------------------------
// ポーズ: 3f Ctrl:1f Shift: 1s
// 再生時:10s Ctrl:5s Shift:60s
void SeekFrame(HWND hWnd, WORD wID)
{
	static const LONGLONG llRunning[] = {
		-100000000LL, -50000000LL, -600000000LL, 100000000LL, 50000000LL, 600000000LL
	};
	LONGLONG llFrame;
 
	switch (g.state) {
	case PAUSED:
		switch (wID) {
		case ID_LEFT:
			llFrame = -3000000000LL / 2997LL;	// 3f = 0.1001001s
			break;
		case ID_LEFT_CTRL:
			llFrame = -1000000000LL / 2997LL;	// 1s / 29.97f = 0.0333667s
			break;
		case ID_LEFT_SHIFT:
			llFrame = -10000000LL;
			break;
		case ID_RIGHT:
			llFrame = 3000000000LL / 2997LL;
			break;
		case ID_RIGHT_CTRL:
			llFrame = 1000000000LL / 2997LL;
			break;
		case ID_RIGHT_SHIFT:
			llFrame = 10000000LL;
			break;
		}
		break;
	case RUNNING:
		llFrame = llRunning[wID - ID_LEFT];
		break;
	default:
		return;
	}
	g.llCurr += llFrame;
	g.llCurr = max(g.llCurr, 0LL);
	g.llCurr = min(g.llCurr, g.llEnd);
	g.pSeek->SetPositions(&g.llCurr, AM_SEEKING_AbsolutePositioning, NULL, 0);
	UpdateSeek(hWnd);
}
 
//------------------------------------------------------------------------------
void OnGraphNotify(HWND hWnd)
{
	long lEvCode, lParam1, lParam2;
 
	Trace(L"OnGraphNotify\n");
	if (g.pEvent == NULL) {
		return;
	}
	while (SUCCEEDED(g.pEvent->GetEvent(&lEvCode, &lParam1, &lParam2, 0))) {
		g.pEvent->FreeEventParams(lEvCode, lParam1, lParam2);
		Trace(L"lEvCode=%#x\n", lEvCode);
		switch (lEvCode) {
		case EC_COMPLETE:
			OnPlay(hWnd);
			break;
		}
	}
}
 
//------------------------------------------------------------------------------
void OnLButtonDown(HWND hWnd, LPARAM lParam)
{
	POINT pt;
 
	SetCapture(hWnd);
	g.bMouseCap = TRUE;
	POINTSTOPOINT(pt, lParam);
	g.nCtrl = HitTest(pt);
}
 
//------------------------------------------------------------------------------
void OnLButtonUp(HWND hWnd, LPARAM lParam)
{
	POINT pt;
 
	if (g.bMouseCap == FALSE) {
		return;
	}
	ReleaseCapture();
	g.bMouseCap = FALSE;
 
	POINTSTOPOINT(pt, lParam);
	if (HitTest(pt) != g.nCtrl) {
		return;
	}
	switch (g.nCtrl) {
	case PLAY:
		OnPlay(hWnd);
		break;
	case STOP:
		OnStop(hWnd);
		break;
	case SEEK:
		{
			int nPos;
 
			if (g.state <= STOPPED) {
				break;
			}
			nPos = (pt.x - g.rc[SEEK].left) - THUMB_W / 2;
			nPos = max(nPos, 0);
			nPos = min(nPos, g.nRange);
			g.llCurr = g.llEnd * nPos / g.nRange;
			g.pSeek->SetPositions(&g.llCurr, AM_SEEKING_AbsolutePositioning, NULL, 0);
			UpdateSeek(hWnd);
		}
		break;
	}
}
 
//------------------------------------------------------------------------------
int HitTest(POINT pt)
{
	int n;
 
	for (n = 0; n < CTRL_NUM; n++) {
		if (PtInRect(g.rc + n, pt)) {
			return n;
		}
	}
	return -1;
}
 
//------------------------------------------------------------------------------
void OnPlay(HWND hWnd)
{
	switch (g.state) {
	case NO_FILE:
		break;
	case STOPPED:
	case PAUSED:
		g.pControl->Run();
		g.state = RUNNING;
		StartTimer(hWnd);
		break;
	case RUNNING:
		g.pControl->Pause();
		g.state = PAUSED;
		StopTimer(hWnd);
		g.pSeek->GetCurrentPosition(&g.llCurr);
		break;
	}
}
 
//------------------------------------------------------------------------------
void OnStop(HWND hWnd)
{
	if (g.state <= STOPPED) {
		return;
	}
	g.pControl->Stop();
	g.state = STOPPED;
	StopTimer(hWnd);
	g.llCurr = 0LL;
	g.pSeek->SetPositions(&g.llCurr, AM_SEEKING_AbsolutePositioning, NULL, 0);
	UpdateSeek(hWnd);
}
 
//------------------------------------------------------------------------------
void StartTimer(HWND hWnd)
{
	g.uIDEvent = SetTimer(hWnd, TIMER1, 1000, NULL);
}
 
//------------------------------------------------------------------------------
void StopTimer(HWND hWnd)
{
	if (g.uIDEvent == 0) {
		return;
	}
	KillTimer(hWnd, TIMER1);
	g.uIDEvent = 0;
}
 
//------------------------------------------------------------------------------
void OnPaint(HWND hWnd)
{
	HDC hdc;
	PAINTSTRUCT ps;
 
	Trace(L"OnPaint\n");
	if (g.pVideo) {
		g.pVideo->RepaintVideo();
	}
	hdc = BeginPaint(hWnd, &ps);
	DrawSeek(hdc);
	Rectangle(hdc, LTRB(g.rc[PLAY]));
	DrawText(hdc, L"Play", -1, &g.rc[PLAY], DT_SINGLELINE | DT_VCENTER | DT_CENTER);
	Rectangle(hdc, LTRB(g.rc[STOP]));
	DrawText(hdc, L"Stop", -1, &g.rc[STOP], DT_SINGLELINE | DT_VCENTER | DT_CENTER);
	Rectangle(hdc, LTRB(g.rc[VOLUME]));
	DrawText(hdc, L"Volume", -1, &g.rc[VOLUME], DT_SINGLELINE | DT_VCENTER | DT_CENTER);
	EndPaint(hWnd, &ps);
}
 
//------------------------------------------------------------------------------
void OnSize(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	POINTS pts;
	RECT rc;
	LONG lPanelT;
	LONG lSeekB;
 
	pts = MAKEPOINTS(lParam);
	Trace(L"OnSize(%u, %d, %d)\n", wParam, pts.x, pts.y);
	if (wParam == SIZE_MINIMIZED) {
		return;
	}
 
	lPanelT = pts.y - PANEL_H;
	SetRect(&g.rc[VIDEO], 0, 0, pts.x, lPanelT);
	SetRect(&rc, 0, lPanelT, pts.x, pts.y);
	lSeekB = rc.top + 12;
	g.rc[PANEL] = rc;
	SetRect(&g.rc[PLAY], 0, rc.top, 40, rc.bottom);
	SetRect(&g.rc[STOP], 40, rc.top, 80, rc.bottom);
	SetRect(&g.rc[SEEK], 80, rc.top, rc.right, lSeekB);
	SetRect(&g.rc[MESSAGE], 80, lSeekB, rc.right - 80, rc.bottom);
	SetRect(&g.rc[VOLUME], rc.right - 80, lSeekB, rc.right, rc.bottom);
	g.nRange = (g.rc[SEEK].right - g.rc[SEEK].left) - THUMB_W;
 
	// ビデオ出力位置のセット
	if (g.pVideo) {
		MFVideoNormalizedRect mvnr = {0.0f, 0.0f, 1.0f, 1.0f};
		g.pVideo->SetVideoPosition(&mvnr, &g.rc[VIDEO]);
	}
 
	if (g.state == RUNNING) {
		SetTimer(hWnd, TIMER2, 100, NULL);
	}
}
 
//------------------------------------------------------------------------------
void OnDropFiles(HWND hWnd, WPARAM wParam)
{
	HDROP hDrop = (HDROP)wParam;
 
	ReleaseGraph(hWnd);
	DragQueryFile(hDrop, 0, g.szPath, _countof(g.szPath));
	InitGraph(hWnd);
}
 
//------------------------------------------------------------------------------
void OnCreate(HWND hWnd)
{
	Trace(L"OnCreate\n");
	if (g.szPath[0]) {
		InitGraph(hWnd);
	}
}
 
//------------------------------------------------------------------------------
void InitGraph(HWND hWnd)
{
	TCHAR szBuf[280];
	TCHAR szDrive	[_MAX_DRIVE];
	TCHAR szDir	[_MAX_DIR];
	TCHAR szFName	[_MAX_FNAME];
	TCHAR szExt	[_MAX_EXT];
	int nEnd;
	HRESULT hr;
 
	// DirectShowフィルタの準備
	hr = OpenFile(hWnd, g.szPath);
	if (FAILED(hr)) {
		return;
	}
	g.state = STOPPED;
 
	// タイトルバー
	_wsplitpath_s(g.szPath, szDrive, szDir, szFName, szExt);
	_wmakepath_s(g.szFile, NULL, NULL, szFName, szExt);
	swprintf_s(szBuf, L"%s - %s", g.szFile, WINDOW_NAME);
	SetWindowText(hWnd, szBuf);
 
	// 停止タイムの取得
	hr = g.pSeek->GetStopPosition(&g.llEnd);
	nEnd = (int)(g.llEnd / 100000LL);
	swprintf_s(g.szEnd, L"%02d:%02d:%02d.%02d",
		nEnd / 360000, (nEnd / 6000) % 60, (nEnd / 100) % 60, nEnd % 100);
 
	// 動画再生
	OnPlay(hWnd);
}
 
//------------------------------------------------------------------------------
void ReleaseGraph(HWND hWnd)
{
	StopTimer(hWnd);
	if (g.pControl) {
		g.pControl->Stop();
		g.state = NO_FILE;
		Sleep(500);
	}
	if (g.pEvent) {
		g.pEvent->SetNotifyWindow(NULL, 0, 0);
	}
	SAFE_RELEASE(g.pVideo);
	SAFE_RELEASE(g.pEvent);
	SAFE_RELEASE(g.pSeek);
	SAFE_RELEASE(g.pControl);
	SAFE_RELEASE(g.pGraph);
}
 
//==============================================================================
HRESULT OpenFile(HWND hWnd, LPCWSTR pszFile)
{
	// フィルタグラフの作成
	HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
		IID_PPV_ARGS(&g.pGraph));
 
	// メディアコントロールインターフェイスの取得
	if (SUCCEEDED(hr)) {
		hr = g.pGraph->QueryInterface(IID_PPV_ARGS(&g.pControl));
	}
 
	// ビデオの作成
	if (SUCCEEDED(hr)) {
		hr = InitEvr(hWnd);
	}
	// グラフを作成する
	if (SUCCEEDED(hr)) {
		hr = g.pGraph->RenderFile(pszFile, NULL);
	}
 
	// シークインターフェイス
	DWORD dwCaps;
	if (SUCCEEDED(hr)) {
		hr = g.pGraph->QueryInterface(IID_PPV_ARGS(&g.pSeek));
	}
	if (SUCCEEDED(hr)) {
		hr = g.pSeek->GetCapabilities(&dwCaps);	// 55 0x37 0011.0111
		AM_SEEKING_CanSeekAbsolute;
	}
	if (SUCCEEDED(hr)) {
		hr = g.pSeek->IsFormatSupported(&TIME_FORMAT_MEDIA_TIME);
		// frame=false
	}
 
	// イベント
	if (SUCCEEDED(hr)) {
		hr = g.pGraph->QueryInterface(IID_PPV_ARGS(&g.pEvent));
	}
	if (SUCCEEDED(hr)) {
		hr = g.pEvent->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0);
	}
 
	// 描画領域の設定
	if (SUCCEEDED(hr)) {
		g.pVideo->GetNativeVideoSize(&g.size, NULL);
	}
	if (SUCCEEDED(hr)) {
		AdjustWnd(hWnd, 2);
	}
	return hr;
}
 
//------------------------------------------------------------------------------
HRESULT InitEvr(HWND hWnd)
{
	IBaseFilter *pEvr = NULL;
 
	// EVRの作成
	HRESULT hr = CoCreateInstance(CLSID_EnhancedVideoRenderer, NULL, CLSCTX_INPROC_SERVER,
		IID_PPV_ARGS(&pEvr));
 
	// フィルタグラフにEVRを追加
	if (SUCCEEDED(hr)) {
		hr = g.pGraph->AddFilter(pEvr, L"EVR");
	}
 
	IMFGetService *pService = NULL;
	if (SUCCEEDED(hr)) {
		hr = pEvr->QueryInterface(IID_PPV_ARGS(&pService));
	}
	if (SUCCEEDED(hr)) {
		hr = pService->GetService(MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&g.pVideo));
	}
	SAFE_RELEASE(pService);
 
	if (SUCCEEDED(hr)) {
		hr = g.pVideo->SetVideoWindow(hWnd);
	}
	SAFE_RELEASE(pEvr);
	return hr;
}
 
//------------------------------------------------------------------------------
void AdjustWnd(HWND hWnd, int nMode)
{
	RECT rc;
 
	SetRect(&rc, 0, 0, g.size.cx * nMode / 2, g.size.cy * nMode / 2 + PANEL_H);
	AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
	SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
		SWP_NOZORDER | SWP_NOMOVE);
}
 

resource.h
#define IDR_MAIN	128
#define ID_ENTER	129
#define ID_ESCAPE	130
#define ID_PLAY		131
#define ID_LEFT		132
#define ID_LEFT_CTRL	133
#define ID_LEFT_SHIFT	134
#define ID_RIGHT	135
#define ID_RIGHT_CTRL	136
#define ID_RIGHT_SHIFT	137
#define ID_NUM1		138
#define ID_NUM2		139
#define ID_NUM3		140
#define ID_NUM4		141
#define ID_STOP		142
 

TestPlayer.rc
// resource script
#include <windows.h>
#include "resource.h"
 
//------------------------------------------------------------------------------
// アクセラレータ
IDR_MAIN ACCELERATORS
BEGIN
	VK_RETURN,	ID_ENTER,	VIRTKEY			// 0x0D
	VK_ESCAPE,	ID_ESCAPE,	VIRTKEY			// 0x1B
	VK_SPACE,	ID_PLAY,	VIRTKEY			// 0x20
	VK_LEFT,	ID_LEFT,	VIRTKEY			// 0x25
	VK_LEFT,	ID_LEFT_CTRL,	VIRTKEY, CONTROL
	VK_LEFT,	ID_LEFT_SHIFT,	VIRTKEY, SHIFT
	VK_RIGHT,	ID_RIGHT,	VIRTKEY			// 0x27
	VK_RIGHT,	ID_RIGHT_CTRL,	VIRTKEY, CONTROL
	VK_RIGHT,	ID_RIGHT_SHIFT,	VIRTKEY, SHIFT
	"1",		ID_NUM1,	VIRTKEY
	"2",		ID_NUM2,	VIRTKEY
	"3",		ID_NUM3,	VIRTKEY
	"4",		ID_NUM4,	VIRTKEY
	"S",		ID_STOP,	VIRTKEY
END
 
最終更新:2012年10月22日 05:53