私の意見では、テンフォーの答えが最善ですが、彼/彼女は何をすべきかを伝えるだけでなく、それを行う方法も説明しなければならなかったので、今私はその方法を説明します:
注:私のソリューションの主なアイデアが必要な場合は、下の最後のステップ 9 にスキップできます (見つけるまで、下から上に検索を開始します)。
私の回答が大袈裟で、説明や詳細が多すぎて申し訳ありませんが、適切に読んでいただければ、理解して満足していただけることを約束します。
ステップ 1:新しいWNDCLASSEX
構造体を作成し、キーワードcbSize
を使用してそのメンバーをこの構造体のサイズ (バイト単位) に設定し、メンバーを任意の値に設定します。また、hbrBackground メンバーを、いずれかの関数の戻り値に設定して、黒、白、または灰色のブラシを取得するか、または任意の色のブラシを取得する関数を設定します。すべての図面でまったく使用されていない色を選択することが非常に重要です!!! そして、あなたの喜びのためだけではありません!sizeof
lpszClassName
GetStockObject
CreateSolidBrush
例えば:
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = "myNewClassName";
HBRUSH background_brush = GetStockObject(BLACK_BRUSH);
wcex.hbrBackground = background_brush;
手順 2:ウィンドウ プロシージャである新しい関数を定義し、その新しい関数ポインタを作成します。次に、のlpfnWndProc
メンバーwcex
をその関数ポインターに設定します。
手順 3:新しいウィンドウ プロシージャ関数の定義で、コードの最後の行でreturn 0;
ある which を追加します。
その上で uMsg パラメータを切り替え、少なくともWM_PAINT
ケースを追加します。その場合、 の新しい変数を定義し、および関数PAINTSTRUCT
を呼び出します。どちらの関数でも、 が変数の名前である場合、 のように変数を参照します。BeginPaint
EndPaint
&ps
ps
PAINTSTRUCT
関数を呼び出した後BeginPaint
、ターゲットウィンドウに必要なすべての描画関数を追加しますが、HDC
すべての描画関数がターゲットウィンドウに属していないことを確認しますが、ウィンドウの最初のパラメーターでハンドルを持つウィンドウに属していることを確認してください手順、すなわちhWnd
!!! または 関数を呼び出してGetDC
、 最初GetWindowDC
にhWnd の hDC を取得します。
注:ターゲット ウィンドウの hDc を取得する必要はまったくありません。
ステートメントdefault: return DefWindowProc(hWnd, uMsg, wParam, lParam);
のブロック内に次のコード行を追加することを忘れないでください。switch
ステップ 4:関数を使用してクラスを登録しRegisterClassEx
ます。
例えば:RegisterClassEx(&wcex);
ステップ 5:アプリケーションで、関数を使用して新しいレイヤードウィンドウを作成しCreateWindowEx
ます。この関数の最初のパラメーターを に設定して、作成する新しいウィンドウが階層化されていることを宣言することが非常に重要です。WS_EX_LAYERED
2番目"myNewClassName"
のパラメーターを新しく登録されたクラスの名前に設定します。NULL
WS_POPUP | WS_VISIBLE
注:は、境界線のないWS_POPUP
新しいウィンドウを作成します。これが、メンバーを無視した理由であり、代わりに
You can replace withに設定された3 番目のパラメーターも無視しました。結果は同じになりますが、クライアント領域全体に 1 ピクセルの厚さで薄く、アウトライン化された灰色の四角形も描画されます。とは対照的に何も描画せず、そのように境界線を削除するだけです。hIcon
wcex
NULL
WS_POPUP
WS_POPUPWINDOW
WS_POPUPWINDOW
WS_POPUP
WS_POPUPWINDOW
WS_VISIBLE
ウィンドウを表示するフラグも設定しました。このフラグを設定しない場合は、レイヤード ウィンドウを表示するために、 のShowWindow
後に関数を呼び出す必要があります。CreateWindowEx
ステップ 6:SetLayeredWindowAttributes
の後に関数を呼び出しますCreateWindowEx
。最初のパラメーターを、関数から返された新しく作成されたレイヤード ウィンドウのハンドルに設定しCreateWindowEx
ます。
2 番目のパラメーターをウィンドウのクライアントの背景色に設定します。つまりbackground_brush
、例の変数に格納されているソリッド ブラシの色に設定します。この変数は、タイプがWNDCLASSEX
.
このパラメータのデータ タイプはCOLORREF
であり、ではないことに注意HBRUSH
してください。つまり、ソリッド ブラシは受け入れず、単に色を受け入れます。
GetStockObject
関数で選択したソリッド ブラシの色がわかっている場合は、そのCOLORREF
構造を作成する方法がわかります。
代わりに関数を呼び出した場合は、関数を呼び出す前に、将来ソリッド ブラシの色と crKey を格納する構造体CreateSolidBrush
の新しい変数を定義します。COLORREF
後で、両方の関数で変数を使用できます:CreateSolidBrush
とSetLayeredWindowAttributes
(2 番目のパラメーター、すなわちcrKey
)。
上記の例に従って、wcex の hbrBackground メンバーのソリッド ブラシを格納するタイプの変数しかなく、パラメーターに適切な COLORREF がない場合:background_brush
HBRUSH
crKey
HBRUSH
タイプがCOLORREF
構造化されるソリッド ブラシの色を取得するには、次のようにします。
GetObject 関数を使用して、ブラシの LOGBRUSH 情報を取得できます。その lbColor コンポーネントは、COLORREF でカラー値を提供します。GetRValue、GetGValue、および GetBValue 関数を使用して、個々のカラー コンポーネントを取得することもできます。
ソリッド ブラシとしてCOLORREF
取得する方法を知らなければならなかった誰かへの Pravin の答え。HBRUSH
詳細については、次のリンクを参照してください。
http://forums.codeguru.com/showthread.php?423605-Color-of-HBRUSH
関数のパラメーターの適切なCOLORREF
構造を取得する別の方法が必要な場合は、最初に新しく作成されたレイヤード ウィンドウの
を取得した後で関数を試すことができます。または代わりに関数を呼び出します。最初のパラメーターを新しいレイヤード ウィンドウの dc に設定し、 2 番目のパラメーターをwcex または上記の例のメンバーに設定します。crKey
SetLayeredWindowAttributes
GetBkColor
hDc
SelectObject
hbrBackground
bakcground_brush
次に、関数を呼び出して、関数のパラメーターの構造GetDCBrushColor
を取得します。COLORREF
crKey
SetLayeredWindowAttributes
3 番目のパラメーターを無視し( に設定)、4 番目のパラメーターにはフラグのみを設定しますbAlpha
。crKey は hbrBackground の色です。階層化されたウィンドウのクライアント全体は描画されません。ただし、色が ではない他のピクセルは除きます。あとは、レイヤード ウィンドウをターゲット ウィンドウのクライアントにバインドするだけです。NULL
LWA_COLORKEY
crKey
手順 7:または 関数を呼び出して、ターゲット ウィンドウのハンドルを取得しますFindWindow
( FindWindowEx
まだ取得していない場合)。
ステップ 8:メッセージ ループを記述します (または、以下のコードを選択してコピーし、自分のコードに貼り付けます)。
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ステップ 9 (最後):メッセージ ループ (while ループのブロック内) のどこ (TranslateMessage の前、DispatchMessage の後、またはそれらの間) に関係なく、レイヤード ウィンドウをターゲット ウィンドウのウィンドウに常にバインドする別のコードを記述します。クライアント:
まず、新しい POINT 構造体を作成し、その座標を (0; 0) に設定します (x
およびy
メンバーを 0 に設定します)。
次に、関数を呼び出しClientToScreen
ます。最初のパラメーターをターゲット ウィンドウのハンドル (FindWindow
またはFindWindowEx
関数から返される) に設定し、2番目のパラメーターで、前に作成した POINT 構造体を参照します。
関数の呼び出し後、ClientToScreen
POINT 構造体は、ターゲット ウィンドウの最も左端の座標を格納します (画面座標で、ピクセル単位で測定されます)。
ここで、ターゲット ウィンドウのクライアントのサイズを取得する必要があります。そのためには、次に構造体型の新しい変数を定義します。RECT
次に、関数を呼び出しGetClientRect
ます。最初のパラメーターをターゲット ウィンドウのハンドルに設定し、 2 番目RECT
のパラメーターで型が構造体である変数を参照します。
GetClientRect
関数の呼び出し後、RECT
変数はターゲット ウィンドウのクライアントの幅と高さをピクセル単位で格納します。right
メンバーには幅が格納され、メンバーbottom
には高さが格納されます。型が構造体である変数のleft
およびtop
メンバーを無視します。RECT
これらは使用も設定もされず、常にデフォルト値、つまりこの場合のみ 0 になります。
ターゲット ウィンドウのクライアントの位置 (場所とサイズ) を取得したら、次のように、または関数 を呼び出して、レイヤード ウィンドウをターゲット ウィンドウのクライアントにバインドできます。MoveWindow
SetWindowPos
MoveWindow(hWnd, point.x, point.y, rect.right, rect.bottom, TRUE);
//If you want, you can set the last parameter to FALSE.
//OR
SetWindowPos(hWnd, hTargetWnd, point.x, point.y, rect.right, rect.bottom, NULL);
//If you want, you can specify some flags in the last parameter.
//Where hWnd is the handle of the layered window returned from CreateWindowEx function, and hTargetWnd is the handle of the target window returned from either FindWindow or FindWindowEx function.
この機能を使用することに決めたのにMoveWindow
、ターゲット ウィンドウにペイントが表示されないという問題がある場合、それはレイヤード ウィンドウがターゲット ウィンドウの下にあるためです。SetWindowPos
この問題を解決するには、代わりに関数の呼び出しを変更する必要があります。2 番目のパラメーターで、境界のあるレイヤード ウィンドウをターゲット ウィンドウの上に配置するシステムを呼び出しました。それでも機能しない場合は、このパラメーターを変更して、またはフラグのいずれかに設定できます。 HWND_TOP
HWND_TOPMOST
その後はうまくいくはずです。レイヤード ウィンドウを無効化、再描画、または更新して、ターゲット ウィンドウの描画を更新することを時々忘れないでください。または または関数を呼び出してそれを行うことができますInvalidateRect
。 RedrawWindow
UpdateWindow
例えば:
POINT point;
ClientToScreen(hTargetWnd, &point);
RECT rect;
GetClientRect(hTargetWnd, &rect);
MoveWindow(hWnd, point.x, point.y, rect.right, rect.bottom, TRUE);
//OR
SetWindowPos(hWnd, hTargetWnd, point.x, point.y, rect.right, rect.bottom, NULL);
InvalidateRect(hWnd, NULL, TRUE);
//If you want, you can set the third parameter to FALSE.
(上記のサンプル コードを選択してコピーし、自分のコードに貼り付けることもできます):
サンプル コードはメッセージ ループ内にある可能性があります。これは、階層化されたウィンドウがすべての瞬間にバインドされ、更新されることを意味します。メモ帳などのアプリケーションに属していない場合は、関数を呼び出す必要があります。この機能の詳細については、MSDN サイトおよび Web 上の他のサイトを参照してください。SetWindowsHookEx
メッセージループではなく、常に発生させたい場合は、他のスレッドの他のwhileループで実行できますが、そのための関数を作成して関数を呼び出す必要がありCreateThread
ます。繰り返しになりますが、MSDN サイトや Web 上の他のサイトでその機能に関する情報を入手することもできます。
アプリケーションのプロセスが終了または終了したときに、スレッドの while ループが終了していることを確認してください。
IsWindow
また、 while ループ条件でまたは関数を試してIsWindowVisible
、レイヤード ウィンドウまたはターゲット ウィンドウが破棄または閉じられている (終了、最小化またはアイコン化されていない)ときに停止することを決定することもできます。