SetWindowLong関数


LONG SetWindowLong(
 HWND hWnd,
 int nIndex,
 LONG dwNewLong
);

指定されたウィンドウの属性を変更します。
拡張ウィンドウメモリのデータも書き換えることができます。

hWndウィンドウのハンドルを指定します。
nIndexウィンドウに関するデータのうち、どのデータを書き換えるのかを指定します。
GWL_EXSTYLE拡張ウィンドウスタイルを書き換えます。
GWL_STYLEウィンドウスタイルを書き換えます。
GWL_WNDPROCウィンドウプロシージャのアドレスを書き換えます。
GWL_HINSTANCEアプリケーションのインスタンスハンドルを書き換えます。
GWL_IDウィンドウのIDを書き換えます。
dwNewLong新しく設定する値を32ビット値で指定します。
Windows > ウィンドウの作成 | comments (0) | trackbacks (0)

SetWindowPos関数


BOOL SetWindowPos(
 HWND hWnd,
 HWND hWndInsertAfter,
 int X,
 int Y,
 int cx,
 int cy,
 UINT uFlags
);

子ウィンドウ、ポップアップウィンドウ、トップレベルウィンドウにおいて、
そのサイズ、位置、Zオーダーを変更します。

hWndウィンドウのハンドルを指定します。
hWndInsertAfterhWndパラメータで指定したウィンドウに先行するウィンドウのハンドルを指定します。
HWND_BOTTOMウィンドウをZオーダーの最後(一番下)に置きます。
HWND_NOTOPMOSTウィンドウを最前面ウィンドウ(WS_EX_TOPMOST)以外のすべてのウィンドウの上位に置きます。
HWND_TOPウィンドウをZオーダーの最初(一番上)に置きます。
HWND_TOPMOSTウィンドウを最前面ウィンドウにします。
Xウィンドウの左上隅の新しいx座標を指定します。
Yウィンドウの左上隅の新しいy座標を指定します。
cxウィンドウの新しい幅をピクセル単位で指定します。
cyウィンドウの新しい高さをピクセル単位で指定します。
uFlagsウィンドウのサイズおよび位置の変更に関するフラグを指定します。
SWP_HIDEWINDOWウィンドウを非表示にします。
SWP_NOACTIVATEウィンドウをアクティブにしません。
SWP_NOMOVE現在の位置を維持します。(X,Yを無視します。)
SWP_NOOWNERZORDERオーナー・ウィンドウのZオーダーを変えません。
SWP_NOREDRAWウィンドウを再描画しない
SWP_NOSIZE現在のサイズを維持します。(cx,cyを無視します。)
SWP_NOZORDER現在のZオーダーを維持します。(hWndInsertAfterを無視します。)
SWP_SHOWWINDOWウィンドウを表示します。
Windows > ウィンドウの作成 | comments (0) | trackbacks (0)

CreateThread()関数


HANDLE CreateThread(
 LPSECURITY_ATTRIBUTES lpsa,
 DWORD dwStackSize,
 LPTHREAD_START_ROUTINE pfnThreadProc,
 void* pvParam,
 DWORD dwCreationFlags,
 DWORD* pdwThreadId
);

新規作成したスレッドへのハンドルを返します。
失敗した場合は NULL を返します。
スレッドは、呼び出し側プロセスのアドレス空間で実行されます。

lpsa新しいスレッドのセキュリティ属性。
取得したハンドルの子プロセスへの継承を許可するかどうかを決める、SECURITY_ATTRIBUTES構造体へのポインタを指定します。
NULLを指定すると、ハンドルは継承されません。
※特別な意図が無い限りNULLでいいでしょう。
dwStackSize新しいスレッドのスタックサイズ。
新しいスレッドが持つスタックのサイズを、バイト単位で指定します。
利用可能なメモリのサイズよりも大きなサイズを指定すると、CreateThread関数は失敗します。
0を指定すると、デフォルトのサイズになります。
※Windowsは必要に応じてスタックサイズを拡張するため、デフォルトサイズを表す0を指定します。
pfnThreadProc新しいスレッドのスレッドプロシージャ。
新しいスレッドの開始アドレスを指定します。
通常、WINAPI呼び出し規約で定義された関数のアドレスを指定します。
この関数の書式を次に示します。
DWORD WINAPI ThreadFunc( LPVOID );
pvParamスレッドプロシージャに渡されるパラメータ。
通常はポインタとして使います。
この引数を利用して何らかのデータを渡せば、スレッドごとに異なる処理をさせることができます。
受け渡すデータが多い場合は構造体にデータを格納し、そのポインタを渡します。
dwCreationFlags作成フラグ(0またはCREATE_SUSPENDED)。
CREATE_SUSPENDEDを指定するとスレッドを中断された状態で作成され、ResumeThread関数を呼び出すまでは動作しません。
※通常は0を指定して、作成と同時にスレッドを起動します。
pdwThreadId正常終了したときに、新しく作成されたスレッドのスレッドIDを受け取るDWORD型変数へのアドレス。


CreateThread( NULL, 0, ThreadFunc, ( LPVOID )&param, 0, &dwThreadID );


・呼び出し側は、作成に成功したスレッドの関数の終了を待ちません。
・作成されたスレッドは、関数の終了をもって破棄されます。
・マルチスレッドは、複数のコードがばらばらのタイミングで動作するため、
複数のスレッドが同じグローバル変数を参照する場合などは、
プログラムの方法によってはデータの整合性が失われるなどの
問題が発生する事もあります。
・C言語のライブラリを利用する場合はCreateThread関数ではなく_beginthread()関数を使うようにします。
Windows > スレッド | comments (0) | trackbacks (0)

PeekMessage()関数


BOOL PeekMessage(
 LPMSG lpMsg,
 HWND hWnd,
 UINT wMsgFilterMin,
 UINT wMsgFilterMax,
 UINT wRemoveMsg
);


lpMsgメッセージを取得するMSG構造体へのポインタ
hWndメッセージを取得するウィンドウへのハンドル
wMsgFilterMin取得するメッセージの最小値。両方0にするとフィルタリングしない。
wMsgFilterMax取得するメッセージの最大値。両方0にするとフィルタリングしない。
wRemoveMsgPM_REMOVE メッセージをキューから削除する
PM_NOREMOVE メッセージをキューから削除しない。

メッセージを取得した時は、0以外の値が返ります。
メッセージを取得しなかった時は、0が返ります。

GetMessage関数と違い、PeekMessage関数は、キュー内にメッセージが置かれるまで待つことはありません。


while (1) {
 if ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) {
  // メッセージがある場合はそれを処理する
  if ( msg.message == WM_QUIT ) break;
  DispatchMessage( &msg );
 } else {
  // アイドル時の処理を行う
 }
}

Windows > メッセージループ | comments (0) | trackbacks (0)

子ウィンドウの作成1


#include <windows.h>
#define CLASSNAME "MyWindowClass"

// グローバル変数:
HINSTANCE hInst;
// このコード モジュールに含まれる関数の宣言を転送します:
ATOM MyRegisterClass( HINSTANCE );
BOOL InitInstance( HINSTANCE, int );
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
//----------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
 MSG msg;

 MyRegisterClass( hInstance );
 if ( !InitInstance( hInstance, nCmdShow ) ) return FALSE;

 // メイン メッセージ ループ:
 while ( GetMessage( &msg, NULL, 0, 0 ) ) {
  TranslateMessage( &msg );
  DispatchMessage( &msg );
 }

 return ( int )msg.wParam;
}
//----------------------------------------------------------------
ATOM MyRegisterClass( HINSTANCE hInstance ) {(省略)}
//----------------------------------------------------------------
BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
{
 HWND hWnd, hWndChild, hWndOwned;

 hInst = hInstance;

 // メインウィンドウ
 hWnd = CreateWindow( CLASSNAME, "Main Window",
  WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
  300, 200, NULL, NULL, hInstance, NULL );
 if ( !hWnd ) return FALSE;

 // 子ウィンドウ
 hWndChild = CreateWindow( CLASSNAME, "Child Window",
  WS_CHILD | WS_CAPTION | WS_VISIBLE,
  0, 0, 150, 100, hWnd, NULL, hInstance, NULL );
 if ( !hWndChild ) return FALSE;

 // 被所有ウィンドウ
 hWndOwned = CreateWindow( CLASSNAME, "Owned Window",
  WS_POPUP | WS_CAPTION | WS_VISIBLE,
  0, 0, 150, 100, hWnd, NULL, hInstance, NULL );
 if ( !hWndOwned ) return FALSE;

 // ウィンドウを表示する
 ShowWindow( hWnd, nCmdShow );
 UpdateWindow( hWnd );

 return TRUE;
}
//----------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) {(省略)}


<親子関係>
ウィンドウ・スタイルにWS_CHILDを指定して、hWndParentに親ウィンドウのハンドルを指定する。
・子ウィンドウは親ウィンドウのクライアント領域の外側に表示したり移動することができない。
・親ウィンドウを移動すると子ウィンドウも一緒に移動する。
・親ウィンドウを最小化すると子ウィンドウも見えなくなる。
・自由に親ウィンドウを変更することができる。

<所有/被所有>
ウィンドウ・スタイルにWS_CHILDを指定せず、hWndParentにオーナー・ウィンドウのハンドルを指定する。
・被所有ウィンドウの移動や表示が、所有ウィンドウの内部に限定されない。
・所有ウィンドウを移動しても被所有ウィンドウは移動しない。
・所有ウィンドウを最小化すると被所有ウィンドウも見えなくなる。
・オーナー・ウィンドウはいったん設定すると、後から変更できない。

071210.jpg
Windows > ウィンドウの作成 | comments (0) | trackbacks (0)

子ウィンドウの作成2

アプリケーションのウィンドウの内部に配置するボタンなどのGUI部品も、
通常は子ウィンドウの形で作ります。


LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
 PAINTSTRUCT ps;
 HDC hdc;
 char str[256];

 static HWND hwButton0, hwButton1;
 static int iMode =0;

 switch (message) {
 case WM_CREATE:
  hwButton0 = CreateWindow( "Button", "Button0", WS_CHILD | WS_VISIBLE, 16, 8, 80, 24, hWnd, ( HMENU )0, hInst, NULL);
  hwButton1 = CreateWindow( "Button", "Button1", WS_CHILD | WS_VISIBLE, 108, 8, 80, 24, hWnd, ( HMENU )1, hInst, NULL);
  break;
 case WM_COMMAND:
  switch ( LOWORD( wParam ) ) { // クリックされたボタン判別
  case 0: // hwButton0
   iMode = 0;
   InvalidateRect( hWnd, NULL, TRUE );
   break;
  case 1: // hwButton1
   iMode = 1;
   InvalidateRect( hWnd, NULL, TRUE );
   break;
  }
  break;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: 描画コードをここに追加してください...
  wsprintf( str, "押されたボタンは%d", iMode );
  TextOut( hdc, 16, 40, str, ( int )strlen( str ) );
  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc( hWnd, message, wParam, lParam );
 }
 return 0;
}


ButtonなどWindowsに用意されているGUI部品のウィンドウを作る際には
Windowsにあらかじめ用意されているウィンドウクラスを使います。

追加されたボタンはWM_COMMANDメッセージを送ってきます。
hMenuの値がwParamの下位ワードに入っているので、
この値からクリックされたボタンを特定できます。

070403.jpg
Windows > ウィンドウの作成 | comments (0) | trackbacks (0)

CreateWindowEx関数


HWND CreateWindowEx(
 DWORD dwExStyle,
 LPCTSTR lpClassName,
 LPCTSTR lpWindowName,
 DWORD dwStyle,
 int x,
 int y,
 int nWidth,
 int nHeight,
 HWND hWndParent,
 HMENU hMenu,
 HINSTANCE hInstance,
 LPVOID lpParam
);

拡張ウィンドウ・スタイルを指定して、ウィンドウを作成する為には、CreateWindowの代わりに、その機能拡張版であるCreateWindowExを利用する。
CreateWindowExのプロトタイプは、先頭に拡張ウィンドウ・スタイルを指定するdwExStyleが追加されている点を除けばCreateWindowと同じである。

WS_EX_ACCEPTFILESこのスタイルで作成されたウィンドウでは、ファイルをドラッグ アンド ドロップできます。
WS_EX_APPWINDOW一番上にあるウィンドウを表示するときに、強制的にタスクバーに含みます。
WS_EX_CLIENTEDGEウィンドウを 3 次元で表示することを指定します。つまり、ウィンドウには、くぼんだ境界線が付きます。
WS_EX_CONTEXTHELPウィンドウのタイトル バーに疑問符 (?) を追加します。ユーザーが疑問符 (?) をクリックすると、カーソルがポインタの付いた疑問符 (?) に変わります。続いてユーザーが子ウィンドウをクリックすると、その子ウィンドウが WM_HELP メッセージを受け取ります。
WS_EX_CONTROLPARENTユーザーが、Tab キーを使ってウィンドウ内の子ウィンドウ間を移動できるようにします。
WS_EX_DLGMODALFRAME二重の境界を持つウィンドウを指定します。パラメータ dwStyle に WS_CAPTION スタイル フラグを指定することにより、タイトル バーを追加することもできます。
WS_EX_LEFTウィンドウに汎用左揃えプロパティを指定します。これは、既定の設定です。
WS_EX_LEFTSCROLLBARクライアント領域の左に垂直スクロール バーを配置します。
WS_EX_LTRREADING左から右への読み取り順序でウィンドウのテキストを表示します。これは、既定の設定です。
WS_EX_MDICHILDMDI 子ウィンドウを作成します。
WS_EX_NOPARENTNOTIFYこのスタイルを指定されている子ウィンドウは、作成または破棄されるときに親ウィンドウに WM_PARENTNOTIFY メッセージを送りません。
WS_EX_OVERLAPPEDWINDOWWS_EX_CLIENTEDGE スタイルと WS_EX_WINDOWEDGE スタイルを組み合わせます。
WS_EX_PALETTEWINDOWWS_EX_WINDOWEDGE スタイルと WS_EX_TOPMOST スタイルを組み合わせます。
WS_EX_RIGHTウィンドウに汎用右揃えプロパティを指定します。このスタイルは、ウィンドウ クラスに依存します。
WS_EX_RIGHTSCROLLBARクライアント領域の右に垂直スクロール バー (存在する場合) を配置します。これは、既定の設定です。
WS_EX_RTLREADING右から左への読み取り順序でウィンドウのテキストを表示します。
WS_EX_STATICEDGE3 次元の境界線スタイルを持つウィンドウを作成します。このウィンドウは、ユーザーの入力を受け付けない項目用に使用します。
WS_EX_TOOLWINDOWツール ウィンドウを作成します。このウィンドウは、フローティング ツール バーとして使用します。ツール ウィンドウのタイトル バーは通常よりも短く、ウィンドウのタイトルはより小さいフォントで描画されます。タスク バーや、ユーザーが Alt キーを押しながら Tab キーを押して表示したウィンドウには、ツール ウィンドウは表示されません。
WS_EX_TOPMOSTこのスタイルで作成されたウィンドウは、すべてのウィンドウの上に配置され、アクティブでなくなった場合でも、引き続きほかのウィンドウの上に表示されたままになります。アプリケーションは、SetWindowPos メンバ関数を使って、この属性を追加および削除できます。
WS_EX_TRANSPARENTこのスタイルで作成されたウィンドウは透明になります。つまり、このウィンドウの下にあるウィンドウが見えなくなることはありません。このスタイルで作成されたウィンドウは、そのウィンドウの下にある兄弟ウィンドウがすべて更新された後にだけ、WM_PAINT メッセージを受け取ります。
WS_EX_WINDOWEDGE縁の浮き出した境界線を持つウィンドウを指定します。

・ウィンドウの外見や振る舞いを指定するパラメータには、ウィンドウ・スタイルの他に拡張ウィンドウ・スタイルがある。
これは、Windows95が登場した際に新たに定義されたもので、クライアント領域をウィンドウ枠よりもへこませて立体的に見せるかどうかといった点を指定できる。
・CreateWindowを使ってウィンドウを作成するのは、CreateWindowExの引数dwExStyleに0を指定して呼び出すのと同じである。
Windows > ウィンドウの作成 | comments (0) | trackbacks (0)

CreateWindow()関数


HWND CreateWindow(
 LPCTSTR lpClassName,
 LPCTSTR lpWindowName,
 DWORD dwStyle,
 int x,
 int y,
 int nWidth,
 int nHeight,
 HWND hWndParent,
 HMENU hMenu,
 HINSTANCE hInstance,
 LPVOID lpParam
);

ウィンドウハンドルは個々のウィンドウを識別するために使われるもので、
ウィンドウを操作する関数を呼び出す時に必要となります。

lpClassName登録済みのウィンドウクラス名
lpWindowNameウィンドウの名前
dwStyleウィンドウの種類や状態を表すビットフラグ
xウィンドウの初期位置
yウィンドウの初期位置
nWidthウィンドウの幅
nHeightウィンドウの高さ
hWndParent親ウィンドウのハンドル
hMenuメニューのハンドル
hInstanceWinMain()関数から取得したインスタンスハンドル
lpParam拡張用のパラメータ

使用例

#define CLASSNAME "Project_Name"
#define WINDOWNAME "TEST"
(中略)

HWND hWnd;

hWnd = CreateWindow( CLASSNAME, WINDOWNAME, WS_OVERLAPPEDWINDOW,
 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL );

if ( !hWnd ) {
 return FALSE;
}


●ウィンドウの構成要素に関するウィンドウ・スタイル
WS_CAPTIONタイトルバーを持つウィンドウを作成します。このスタイルを指定する場合は、WS_BORDERスタイルも指定する必要もあります。WS_DLGFRAMEスタイルと一緒に使うことはできません。
WS_BORDER境界線を持つウィンドウを作成します。細い(サイズ変更可能な)ウィンドウ枠です。
WS_DLGFRAME二重の境界線を持ち、タイトルは持たないウィンドウを作成します。ダイアログボックスで使用するウィンドウ枠です。
WS_THICKFRAME
WS_SIZEBOX
サイズ変更境界を持つウィンドウを作成します。太い(サイズ変更可能な)ウィンドウ枠です。
WS_HSCROLL水平スクロールバーを持つウィンドウを作成します。
WS_VSCROLL垂直スクロールバーを持つウィンドウを作成します。
WS_SYSMENUタイトルバーにコントロールメニューボックスを持つウィンドウを作成します。タイトルバーを持つウィンドウだけに指定します。WS_CAPTIONスタイルも指定する必要があります。
WS_MAXIMIZEBOX最大化ボタンを持つウィンドウを作成します。WS_SYSMENUと同時に指定する。
WS_MINIMIZEBOX最小化ボタンを持つウィンドウを作成します。WS_SYSMENUと同時に指定する。

●ウィンドウの種類に関するウィンドウ・スタイル
WS_OVERLAPPED
WS_TILED
オーバラップウィンドウを作成します。オーバラップウィンドウには、タイトルバーと境界線があります。
WS_POPUPポップアップウィンドウを作成します。WS_CHILDスタイルと一緒に使うことはできません。
WS_CHILD子ウィンドウを作成します。WS_POPUPスタイルと一緒に使うことはできません。
WS_OVERLAPPEDWINDOW
WS_TILEDWINDOW
WS_OVERLAPPED、WS_CAPTION、WS_SYSMENU、WS_THICKFRAME、WS_MINIMIZEBOX、WS_MAXIMIZEBOXスタイルを持つオーバラップウィンドウを作成します。
WS_POPUPWINDOWWS_BORDER、WS_POPUP、およびWS_SYSMENUスタイルを持つポップアップウィンドウを作成します。コントロールメニューを表示するには、WS_CAPTIONスタイルとWS_POPUPWINDOWスタイルを組み合わせて指定する必要があります。
WS_CHILDWINDOWWS_CHILDと同じ

●その他
WS_MINIMIZE
WS_ICONIC
初期状態で最小化されたウィンドウを作成します。必ずWS_OVERLAPPEDスタイルと一緒に使います。
WS_MAXIMIZE最大化されたウィンドウを作成します。
WS_VISIBLE初期状態で表示されるウィンドウを作成します。
WS_DISABLED初期状態で無効になっているウィンドウを作成します。
WS_TABSTOPダイアログボックスでTABキーを押した時に、コントロールが入力フォーカスを取得できるようにする。
WS_GROUPダイアログボックスでコントロールをグループ化する際に指定する。
WS_CLIPCHILDRENクライアント領域内の子ウィンドウのある部分を描画対象から除外する。
WS_CLIPSIBLINGS同じ親ウィンドウの子ウィンドウ同士で重なっている部分を描画対象から除外する。

ウィンドウ・スタイルはビット・フィールドとして定義されており、winuser.hなどのヘッダー・ファイルが定義する「WS_」で始まる定数を必要なだけ論理ORで組み合わせて指定する。

設定例
160_80_1.jpgWS_OVERLAPPEDWINDOW
サイズ変更可
160_80_2.jpgWS_POPUPWINDOW | WS_CAPTION
サイズ変更不可
160_80_3.jpgWS_POPUP | WS_BORDER | WS_CAPTION
サイズ変更不可
160_80_4.jpgWS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX
サイズ変更不可
Windows > ウィンドウの作成 | comments (0) | trackbacks (0)

カーソル位置の取得

BOOL GetCursorPos( LPPOINT lpPoint );

マウスカーソルの現在の位置を、スクリーン座標で取得します。

lpPointカーソル位置をスクリーン座標で受け取るPOINT構造体を指すポインタ

マウスカーソルの位置は常にスクリーンスクリーン座標で与えられます。
マウスカーソルが表示されているウィンドウのマッピングモードには影響されません。
スクリーン座標をクライアント座標に変換するには、ScreenToClient()関数を使います。

BOOL ScreenToClient(
HWND hWnd,
LPPOINT lpPoint
);

hWndウィンドウのハンドルを指定します。このウィンドウのクライアント座標が変換に利用されます。
lpPoint変換されるスクリーン座標が入ったPOINT構造体へのポインタを指定します。関数が成功すると、この構造体にクライアント座標が格納されます。

クライアント座標は、ウィンドウのクライアント領域の左上隅を(0,0)とする座標系です。


POINT point;
GetCursorPos( &point );
ScreenToClient( hWnd, &point );

Windows > 入力処理 | comments (0) | trackbacks (0)

ムービーの再生

動画ファイルの再生も、MCI_OPENコマンドで動画ファイルを
MCIデバイスとしてオープンし、MCI_PLAYで再生します。
しかし、音楽データとは異なり、動画を再生するには
映像を画面に表示させる必要があります。

アニメーションデバイスを開く場合はMCI_OPEN_PARMS構造体を
拡張したMCI_ANIM_OPEN_PARMS構造体を指定する事ができます。
dwStyleメンバにWS_CHILDスタイルを指定すれば、hWndParentの
クライアント領域に子ウィンドウとして動画が表示されます。
ただし、MCI_OPENコマンドでウィンドウスタイルを指定するには、
フラグにMCI_ANIM_OPEN_WSを指定しなければなりません。
同様に、親ウィンドウを指定する場合はMCI_ANIM_OPEN_PARENT
指定します。
デバイスタイプは省略してもWindowsが適切なデバイスタイプを
判断してくれます。

要所のみ抜粋

static MCI_ANIM_OPEN_PARMS maop;
static MCI_PLAY_PARMS mpp;
char strErr[256];

case WM_CREATE:
 maop.dwCallback = ( DWORD )hWnd;
 maop.lpstrElementName = "test.mpg";
 maop.dwStyle = WS_CHILD | WS_VISIBLE;
 maop.hWndParent = hWnd;

 iErr = mciSendCommand( 0, MCI_OPEN,
  MCI_OPEN_ELEMENT | MCI_ANIM_OPEN_PARENT | MCI_ANIM_OPEN_WS,
  ( DWORD )&maop );
 if ( iErr ) {
  mciGetErrorString( iErr, strErr, sizeof( strErr ) );
  MessageBox( hWnd, strErr, NULL, MB_OK | MB_ICONERROR );
  return -1;
 }
 mpp.dwCallback = ( DWORD )hWnd;
 break;

case WM_LBUTTONDOWN:
 mciSendCommand( maop.wDeviceID, MCI_PLAY, 0, ( DWORD )&mpp );
 break;

case WM_DESTROY:
 mciSendCommand( maop.wDeviceID, MCI_CLOSE, 0, 0 );
 PostQuitMessage(0);
 break;


※リファレンスで検索してもMCI_ANIM_OPEN_PARMS
がヒットしないのが気になります。ビルドはできますが
古い仕様で推奨されていないのかも知れません。
MCI_DGV_OPEN_PARMSかMCI_OVLY_OPEN_PARMSを使うべき
なんだろうか…。
Windows > マルチメディア | comments (0) | trackbacks (0)

mciGetErrorString()関数


BOOL mciGetErrorString(
 DWORD fdwError,
 LPTSTR lpszErrorText,
 UINT cchErrorText
);

指定されたMCIエラーコードについて説明するストリングを検索します。

fdwErrorError code returned by the mciSendCommand or mciSendString function.
lpszErrorTextPointer to a buffer that receives a null-terminated string describing the specified error.
cchErrorTextLength of the buffer, in characters, pointed to by the lpszErrorText parameter.

エラーコードに対応した文字列の文字数はエラーの内容によって異なりますが
最大で128文字になる可能性があると定められています。
Unicodeへの対応も考えれば256バイト以上のバッファを確保すれば十分でしょう。
Windows > マルチメディア | comments (0) | trackbacks (0)

mciSendCommand()関数


MCIERROR mciSendCommand(
 MCIDEVICEID IDDevice,
 UINT uMsg,
 DWORD fdwCommand,
 DWORD_PTR dwParam
);

IDDeviceコマンドを送信するMCIデバイスの識別子を指定します。アプリケーションは、最初にメディアデバイスを開いてこの識別子を取得する必要があります。
uMsgMCIデバイスに送信するコマンドを表す定数を指定します。
fdwCommandコマンドの追加情報となるフラグ
dwParamコマンドの情報を格納した構造体へのポインタ


MCI_OPENコマンド


static MCI_OPEN_PARMS mop;
(略)
case WM_CREATE:
 mop.dwCallback = ( DWORD )hWnd;
 mop.lpstrDeviceType = ( LPCSTR )MCI_DEVTYPE_WAVEFORM_AUDIO;
 mop.lpstrElementName = "test.wav";

 iErr = mciSendCommand( 0, MCI_OPEN,
  MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT,
  ( DWORD )&mop );
 if ( iErr ) {
  mciGetErrorString( iErr, strErr, sizeof( strErr ) );
  MessageBox( hWnd, strErr, NULL, MB_OK | MB_ICONERROR );
  return -1;
 }
 break;


文字列でデバイスの種類を指定する場合は、フラグにMCI_OPEN_TYPEを組み合わさなければなりません。
定数を使ってデバイスの種類を指定する場合は、MCI_OPEN_TYPEに加えてMCI_OPEN_TYPE_IDフラグを組み合わせます。
基本的には、文字列よりも定数の方がオーバーヘッドが少なく高速な動作を期待することができます。
MCI_OPEN_ELEMENTは所定の構造体のlpstrElementNameメンバに、ファイル名が格納されている事を表します。

MCI_PLAYコマンド


case WM_LBUTTONDOWN:
 mciSendCommand( mop.wDeviceID, MCI_PLAY, 0, 0 );
 break;


正しくMCIデバイスをオープンすることができれば、MCI_PLAYコマンドをデバイスに送信する事で、コンテンツを再生する事ができます。
MCI_PLAYコマンドもデバイスの種類でさまざまなフラグや構造体を指定する事ができますが、特殊な再生方法を望まない限りは必要無いでしょう。

MCI_STOP、MCI_PAUSE、MCI_SEEKコマンド


case WM_RBUTTONDOWN:
 PlaySound( NULL, NULL, SND_PURGE );
 mciSendCommand( mop.wDeviceID, MCI_STOP, 0, 0 );
 mciSendCommand( mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0 );
 break;


再生を一時停止するにはMCI_PAUSE
停止するにはMCI_STOPコマンドを送信します。
これらのコマンドは独自のフラグや構造体を持ちません。
MCI_PAUSE、MCI_STOPの意味は対象デバイスによって異なります。
コンテンツの再生位置はMCI_SEEKコマンドで変更する事ができます。
フラグにMCI_SEEK_TO_STARTを指定すればコンテンツの先頭に移動します。
フラグと専用の構造体を指定すれば任意の位置も指定できます。

※WAVEの再生で試してみると、PlaySound関数では再生後、先頭に自動で巻き戻されるようですが
MCIコマンドでは再生後巻き戻らない(もしくは再生しっぱなし)のようで、
MCI_SEEKで再生位置を設定し直す必要があるようです。


MCI_CLOSEコマンド


case WM_DESTROY:
 mciSendCommand( mop.wDeviceID, MCI_CLOSE, 0, 0 );
 PostQuitMessage(0);
 break;


MCIデバイスの利用が終了し、デバイスが不要になれば解放しなければなりません。
デバイスを解放するにはMCI_CLOSEコマンドを送信して下さい。
MCI_CLOSEコマンドは独自のフラグや構造体を持ちません。

MCI_NOTIFYフラグ

MCI_NOTIFYフラグを使用すると、
デバイスはアクションを完了すると親ウィンドウに
MM_MCINOTIFYメッセージをポストします。
このメッセージは、コマンドが処理を終了した時に送られてきます。

MCI_PLAYコマンドにMCI_NOTIFYフラグを指定すれば、
MCIはトラックの再生が終了すると親ウィンドウに
MM_MCINOTIFYコマンドをポストするので、
このタイミングで再びトラックの先頭から再生するようにすれば
ループ再生ができます。


static MCI_OPEN_PARMS mop;
static MCI_PLAY_PARMS mpp;
(略)
case WM_CREATE:
 (デバイスのオープンの記述。上記参照)
 mpp.dwCallback = ( DWORD )hWnd;
 mpp.dwFrom = 0; // 演奏開始位置の設定、0ならば曲の先頭からになる
case WM_LBUTTONDOWN:
 mciSendCommand( mop.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, ( DWORD )&mpp );
 break;
case WM_RBUTTONDOWN:
 mciSendCommand( mop.wDeviceID, MCI_STOP, 0, 0 );
 //mciSendCommand( mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0 );
 break;
case MM_MCINOTIFY:
 if ( wParam == MCI_NOTIFY_SUCCESSFUL )
  mciSendCommand( mop.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, ( DWORD )&mpp );
 break;
(略)


※最初から再生開始位置を指定して再生してやれば
MCI_SEEKコマンドを使う必要も無さそうです。
Windows > マルチメディア | comments (0) | trackbacks (0)

MCI_PLAY_PARMS構造体


typedef struct {
 DWORD_PTR dwCallback;
 DWORD dwFrom;
 DWORD dwTo;
} MCI_PLAY_PARMS;

MCI_PLAY_PARMS構造体は、MCI_PLAYコマンドのための位置情報を含んでいます。

dwCallbackThe low-order word specifies a window handle used for the MCI_NOTIFY flag.
dwFromPosition to play from.
dwToPosition to play to.
Windows > マルチメディア | comments (0) | trackbacks (0)

MCI_OPEN_PARMS構造体


typedef struct {
 DWORD_PTR dwCallback;
 MCIDEVICEID wDeviceID;
 LPCSTR lpstrDeviceType;
 LPCSTR lpstrElementName;
 LPCSTR lpstrAlias;
} MCI_OPEN_PARMS;


wDeviceID開いたMCIデバイスの識別子が格納されます。開いたデバイスにMCIコマンドを送信するには、このデバイス識別子を利用します。
lpstrDeviceTypeデバイスのタイプ名を保存した文字列へのポインタ、または定数を指定します。
lpstrElementName開くMCIデバイスのコンテンツを参照するパスを指定します。
lpstrAlias開くデバイスに割り当てる別名を指定します。(任意)

MCI Device Types
MCI_ALL_DEVICE_IDAny device
MCI_DEVTYPE_ANIMATIONAnimation-playback device
MCI_DEVTYPE_CD_AUDIOCD audio device
MCI_DEVTYPE_DATDigital-audio tape device
MCI_DEVTYPE_DIGITAL_VIDEODigital-video playback device
MCI_DEVTYPE_OTHERUndefined device
MCI_DEVTYPE_OVERLAYVideo-overlay device
MCI_DEVTYPE_SCANNERScanner device
MCI_DEVTYPE_SEQUENCERMIDI sequencer device
MCI_DEVTYPE_VCRVideo-cassette recorder
MCI_DEVTYPE_VIDEODISCVideodisc player
MCI_DEVTYPE_WAVEFORM_AUDIOWaveform-audio device
Windows > マルチメディア | comments (0) | trackbacks (0)

PlaySound()関数


BOOL PlaySound(
 LPCSTR pszSound,
 HMODULE hmod,
 DWORD fdwSound
);

WAVEフォームサウンドを再生します。

pszSound再生するサウンドをNULLで終わる文字列で指定します。ただしfdwSoundパラメータでSND_MEMORYを指定した時は、メモリ内に読み込まれたサウンドイメージへのポインタを指定します。NULLを指定すると、現在再生中のWAVEフォームサウンドが停止します。
hmodfdwSoundパラメータでSND_RESOURCEを指定した場合は、ロードするリソースが入った実行可能ファイルのインスタンスハンドルを指定します。そうでない場合は、NULLを指定します。
fdwSound再生フラグヲ指定します。

フラグ抜粋
SND_ASYNCサウンドを非同期的に再生します。PlaySound関数は即座に制御を返します。非同期的に再生されているサウンドを止めるには、pszSoundパラメータにNULLを指定してPlaySound関数を呼び出します。
SND_FILENAMEpszSoundパラメータは、ファイル名です。
SND_LOOPサウンドを繰り返し再生します。SND_ASYNCと同時に指定します。サウンドの再生を止めるにはpszSoundパラメータにNULLを指定してPlaySound関数を呼び出します。
SND_MEMORYpszSoundパラメータは、メモリ内に読み込まれたサウンドイメージへのポインタです。
SND_NODEFAULT指定されたサウンドが見つからなかった場合、PlaySound関数はデフォルトのサウンド(一般の警告音)を再生することなく無音で制御を返します。
SND_NOSTOP既にほかのサウンドが再生されていた場合、指定されたサウンドを再生することなく即座に制御を返します。
SND_NOWAITドライバがビジー状態であれば、サウンドを再生することなく即座に制御を返します。
SND_PURGEサウンドの再生を停止します。pszSoundパラメータがNULL以外のときは、指定したサウンドの全てのインスタンスが停止します。pszSoundパラメータがNULLの時は、呼び出し側タスクのすべてのサウンドが停止します。SND_RESOURCE指定時は、インスタンスハンドルも指定します。
SND_RESOURCEpszSoundパラメータはリソースIDです。hmodパラメータには、リソースが入った実行可能ファイルのインスタンスハンドルを指定します。
SND_SYNCサウンドを同期的に再生します。PlaySound関数は、サウンドの再生が完了した後に制御を返します。



case WM_LBUTTONDOWN:
 PlaySound( "test.wav", NULL, SND_ASYNC | SND_FILENAME );
 break;
case WM_RBUTTONDOWN:
 PlaySound( NULL, NULL, SND_PURGE );
 break;


この関数で音声データを再生するには必ずその音声データを保存できるだけの物理メモリが必要になります。
Windows > マルチメディア | comments (0) | trackbacks (0)