Win32のダイアログプロシージャによるダイアログ画面の透明化処理の軽量化方法
■概要
ポップアップ系のダイアログの背景を透明化し、
特定の文字列だけをデバイスコンテキストを使用して描画させています。
これを実現するためにSetLayeredWindowAttributes()を使用しています。
しかし、調べたところによると上記APIを使用した場合、非力なマシンだと処理が
重くなる可能性があるとの情報があったので、より軽量で速度の早い方法が無いかを探しています。
■質問内容
SetLayeredWindowAttributes()を使用した背景色の透過処理以外で
より軽量になる方法は無いでしょうか?
※DirectXを使ったやり方の方が軽くなるなど、全く別のアプローチ掲示でも何でも構いません。
■制約や補足
Win32のDLLモジュールを作成し、そのDLLロードしたアプリケーション上で
ダイアログ用のスレッドを生成し、そのスレッド上でダイアログプロシージャを
動作させています。(そのため、直接アプリケーション側のウィンドウプロシージャを使用できないので直接描画ができません)
ダイアログ側は属性として「Layred(WS_EX_LAYERED)」を設定しています。
■現状のソースコード
DllMain(HINSTANCE hInstDLL, ...)
{
.
.
.
case DLL_PROCESS_ATTACH:
CreateThread(..., DlgThreadProc, hInstDLL, ...);
.
.
.
}
DWORD WINAPI DlgThreadProc( LPVOID lpParameter )
{
HWND hOwner;
HWND hDlg;
MSG tagMsg;
DWORD dwExitCode;
BOOL bRinf;
while (1)
{
// ロード対象のプロセスIDからウィンドウハンドル取得(内容は割愛)
hOwner = GetWindowHandle(GetCurrentProcessId());
if (hOwner != NULL)
{
break;
}
// タイムスライス譲渡
Sleep(0);
}
hDlg = CreateDialogParam( (HINSTANCE)lpParameter, MAKEINTRESOURCEA(IDD_DIALOGBAR), hOwner, (DLGPROC)DlgProc, 0L );
if ( hDlg == NULL )
{
dwExitCode = GetLastError();
goto ERROR_END;
}
ShowWindow( hDlg, SW_SHOWNORMAL );
while ( 1 )
{
bRinf = GetMessage( &tagMsg, NULL, 0, 0 );
switch ( bRinf )
{
case 0: // プログラム終了
dwExitCode = ERROR_SUCCESS;
break;
case -1: // イベントメッセージ取得エラー
dwExitCode = GetLastError();
break;
default:
if ( IsDialogMessage( hDlg, &tagMsg ) == FALSE )
{
TranslateMessage( &tagMsg );
DispatchMessage( &tagMsg );
}
break;
}
if ( bRinf == 0 || bRinf == -1 ) break;
}
ERROR_END:
ExitThread( dwExitCode );
}
INT_PTR CALLBACK DlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
INT iRet;
iRet = 0;
switch (uMsg)
{
case WM_INITDIALOG:
// カラーキー設定にて描画内容を排他
SetLayeredWindowAttributes(hwndDlg, GetSysColor(COLOR_BTNFACE), 0, LWA_COLORKEY);
iRet = 1;
break;
case WM_PAINT:
hdc = BeginPaint(hwndDlg, &ps);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(196, 163, 191));
// 透明化されたダイアログに文字列描画
TextOut(hdc, 20, 0, "テスト描画", sizeof("テスト描画"));
EndPaint(hwndDlg, &ps);
break;
case WM_CLOSE:
EndDialog( hwndDlg, 0 );
break;
default:;
}
return iRet;
}