ショートカットキーやホットキー、それからゲーム操作のカスタマイズ時にキー名を表示する事があると思いますが、キーコードからキー名を取得する方法をご紹介。

TCHAR szBuf[128];
UINT nScanCode = MapVirtualKey(btKeyCode, 0);
if (nScanCode) {
	switch (btKeyCode) { 
	case VK_LEFT:
	case VK_UP:
	case VK_RIGHT:
	case VK_DOWN:
	case VK_PRIOR:
	case VK_NEXT:
	case VK_END:
	case VK_HOME: 
	case VK_INSERT:
	case VK_DELETE: 
	case VK_DIVIDE:
	case VK_NUMLOCK: 
		nScanCode |= 0x100;
		break; 
	}
	if (GetKeyNameText(nScanCode << 16, szBuf, sizeof(szBuf))) {
		// szBufにキー名が入る
	}
}

日本のサイトで方法を紹介されているページも有ったのですが、Homeキー等一部のキー名の取得がうまく行っていませんでした。
海外のサイトに解決策が載っていたので、そこから一部拝借してみました。
たぶんこれで良いと思います。

音量(パンポット)はmidiOutSetVolumeを使えばあっという間に設定できるのですが、
これだとミュートチェックは外してくれません。

というわけでこちら(http://www.terra.dti.ne.jp/~vivas/delphi/mixerapi.html)のサイト様の説明を参考にさせて頂きながらミキサーAPIを使ってミュートを解除するコードを書いてみました。

MIXERLINE MixerLine = {sizeof(MIXERLINE)};
MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
if (mixerGetLineInfo((HMIXEROBJ)nDevID, &amp;MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE | MIXER_OBJECTF_MIDIOUT) == MMSYSERR_NOERROR) {
	MIXERCONTROL Ctrl;
	MIXERLINECONTROLS Ctrls = {sizeof(MIXERLINECONTROLS), MixerLine.dwLineID};
	Ctrls.cControls = 1;
	Ctrls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; 
	Ctrls.cbmxctrl = sizeof(MIXERCONTROL);
	Ctrls.pamxctrl = &amp;Ctrl;
	if (mixerGetLineControls((HMIXEROBJ)nDevID, &amp;Ctrls, MIXER_GETLINECONTROLSF_ONEBYTYPE | MIXER_OBJECTF_MIDIOUT) == MMSYSERR_NOERROR) {
		MIXERCONTROLDETAILS Details = {sizeof(MIXERCONTROLDETAILS)};
		Details.dwControlID = Ctrl.dwControlID;
		Details.cChannels = 1;	// 決めうちで良いらしい
		MIXERCONTROLDETAILS_BOOLEAN Boolean = {0};
		Details.paDetails = &amp;Boolean;
		Details.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
		if (mixerSetControlDetails((HMIXEROBJ)nDevID, &amp;Details, MIXER_SETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_MIDIOUT) == MMSYSERR_NOERROR) {
			// 成功
		}
	}
}

この制御をDominoに組み込めば「音が鳴らない!」と助けを求める方が激減する予感。

DirectShowの動画編集機能(DES)を使っていろいろ実験していたところ、
アルファブレンディングがどうにも上手く行かなかった。

http://msdn.microsoft.com/ja-jp/library/cc352035.aspx

ちゃんとやったつもりが、動画プレビュー時に何故かアプリが何事もなかったかのように終了してしまう(例外なども無し)。
各関数のエラー値を見たりエラーログ出力機能を使ったりしても原因を特定できず・・・。

ふと、コンパイルしたEXEをエクスプローラ上から起動してみたら上手く起動できましたorz
なんですかこれ、Vsual Studioの「デバッグの停止」が誤爆してるんだろうか??

GradientFill APIのラッパー関数を作ってみました。
と言っても縦のグラデしか対応させていませんが。

void FillGrad(CDC* pDC, CRect rc, COLORREF colBegin, COLORREF colEnd)
{
	TRIVERTEX av[2] = {
		rc.left, rc.top, GetRValue(colBegin) << 8, GetGValue(colBegin) << 8, GetBValue(colBegin) << 8, 0xff00,
		rc.right, rc.bottom, GetRValue(colEnd) << 8, GetGValue(colEnd) << 8, GetBValue(colEnd) << 8, 0xff00,
	};
	GRADIENT_RECT gr = {0, 1};
	GradientFill(pDC->GetSafeHdc(), av, 2, &gr, 1, GRADIENT_FILL_RECT_V);
}

GradientFill APIは古いOSでは動きませんのでご注意ください。

Microsoftは設定データなどをレジストリへ保存する事を推奨しているぽいですが、結構嫌がるユーザーさんが多いので私のソフトではiniファイルへ書き出すことが多いわけなのですが、久々にWritePrivateProfileString APIを調べていたら、やれば出来る子という事が判明しました。

APIの名前から機能を「文字列をiniファイルに書き出す」だけだと勝手に思いこんでいたのですが、引数の渡し方によってはキーを削除したり、セクションを削除したりできるようです。
(こういうのは削除専用のAPIを別途作った方が使い手は判りやすいと思うんですが。)

また、ユニコード版(WritePrivateProfileStringW)は、ユニコードのまま文字列を書き出せるという事も判明。
ただし、iniファイルがユニコードファイルである必要があります。
なので、iniファイルが存在していなかったら、BOM(バイトオーダーマーク)だけのファイルを生成した上でWritePrivateProfileStringWを実行すれば良さそうです(ファイルが無い状態でWritePrivateProfileStringWを呼ぶとShiftJisに変換されてしまうようです)。

こんな感じかな。

CString strIniPath = iniファイルのパス
if (!::PathFileExists(strIniPath)) {
	CFile file;
	if (file.Open(strIniPath, CFile::modeWrite | CFile::modeCreate | CFile::shareExclusive)) {
		BYTE bom[2] = {0xff, 0xfe};
		file.Write(bom, 2);
		file.Close();
	}
}
::WritePrivateProfileString(_T("Test"), _T("Test"), strUnicode, strIniPath);

記事検索

アーカイブ