特定のウィンドウにタスクバー ボタンがあるかどうかを確認する方法を探しています。つまり、ウィンドウへのハンドルが与えられた場合、ウィンドウがタスクバーにある場合は TRUE が必要であり、それ以外の場合は FALSE が必要です。
逆に、特定のタスクバー ボタンに属するウィンドウへのハンドルを取得する方法があるかどうか疑問に思っています。これには、タスクバー ボタンを列挙する方法が必要になると思います。
(最初の前者は私が必要な部分で、後者の部分はオプションです。)
どうもありがとう。
Windowsはヒューリスティックを使用して、ウィンドウにタスクバーボタンを与えるかどうかを決定します。また、決定するまでに遅延が発生する場合があるため、これを100%正確に行うことは非常に困難です。これがルールの大まかなスタートです。わかりやすくするモダンなスタイルのフラグがありますが、それらのスタイルが欠落している場合、タスクバーは推測になります。
まず、両方のウィンドウスタイルフラグが必要になります。
LONG Style = GetWindowLong(hwnd, GWL_STYLE);
LONG ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
今ルール、確かな3つのルールがあります。
ExStyle & WS_EX_APPWINDOW
、タスクバーExStyle & WS_EX_TOOLWINDOW
、NOT_TASKBARStyle & WS_CHILD
NOT_TASKBAR残りは推測です:
Style & WS_OVERLAPPED
タスクバーを提案しますStyle & WS_POPUP
特に次の場合にNOT_TASKBARを提案しますGetParent() != NULL
ExStyle & WS_EX_OVERLAPPEDWINDOW
タスクバーを提案しますExStyle & WS_EX_CLIENTEDGE
NOT_TASKBARを提案しますExStyle & WS_EX_DLGMODALFRAME
NOT_TASKBARを提案します推測には他にもルールがあると思いますが、実際、Windowsのバージョンごとに推測ルールが変更されています。
トップレベル ウィンドウ
WS_EX_APPWINDOW -> タスクバー、他のスタイルに関係なく!
OWNER は NULL でなければなりません (GetWindow(window, GW_OWNER))
いいえ: WS_EX_NOACTIVATE または WS_EX_TOOLWINDOW:
順序が重要です。
2 番目の質問: Windows XP/Vista では、タスクバーのプロセスに入り、すべてのウィンドウ ID を取得できました。
void EnumTasklistWindows()
{
int b2 = 0;
TBBUTTON tbButton;
DWORD dwProcessId = 0, dwThreadId = 0;
HWND hDesktop =::GetDesktopWindow();
HWND hTray =::FindWindowEx(hDesktop, 0, ("Shell_TrayWnd"), NULL);
HWND hReBar =::FindWindowEx(hTray, 0, ("ReBarWindow32"), NULL);
HWND hTask =::FindWindowEx(hReBar, 0, ("MSTaskSwWClass"), NULL);
HWND hToolbar =::FindWindowEx(hTask, 0, ("ToolbarWindow32"), NULL);
LRESULT count =::SendMessage(hToolbar, TB_BUTTONCOUNT, 0, 0);
dwThreadId = GetWindowThreadProcessId(hToolbar, &dwProcessId);
shared_ptr<void> hProcess (OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId), CloseHandle);
if (NULL == hProcess.get())
{
return;
}
memset(&tbButton, 0, sizeof(TBBUTTON));
for (int i = 0; i < count; i++)
{
memset(&tbButton, 0, sizeof(TBBUTTON));
shared_ptr<void> lpRemoteBuffer (
VirtualAllocEx(hProcess.get(), NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE),
bind<BOOL>(VirtualFreeEx, hProcess.get(), _1, 0, MEM_RELEASE));
if (NULL == lpRemoteBuffer.get())
{
return;
}
SendMessage(hToolbar, TB_GETBUTTON, i, (LPARAM) lpRemoteBuffer.get());
b2 = ReadProcessMemory(hProcess.get(), lpRemoteBuffer.get(),
(LPVOID) & tbButton, sizeof(TBBUTTON), NULL);
if (0 == b2)
{
continue;
}
BYTE localBuffer[0x1000];
BYTE *pLocalBuffer = localBuffer;
DWORD_PTR ipLocalBuffer = (DWORD_PTR) pLocalBuffer;
pLocalBuffer = localBuffer;
ipLocalBuffer = (DWORD_PTR) pLocalBuffer;
DWORD_PTR lpRemoteData = (DWORD_PTR) tbButton.dwData;
ReadProcessMemory(hProcess.get(), (LPVOID) lpRemoteData, (LPVOID) ipLocalBuffer,
sizeof(DWORD_PTR), NULL);
HWND windowHandle;
memcpy(&windowHandle, (void *) ipLocalBuffer, 4);
if (windowHandle != NULL)
{
trace ("adding button: %x\n", windowHandle);
}
}
}
これはWindows 7ではもう不可能です。したがって、すべてのトップレベル ウィンドウをループする必要があります。
この MSDN の記事には、シェルがウィンドウのタスクバー ボタンを作成することを決定するタイミングと理由に関するいくつかの良い情報があります。
シェルは、アプリケーションが所有されていないウィンドウを作成するたびに、タスク バーにボタンを作成します。ウィンドウ ボタンがタスク バーに確実に配置されるようにするには、所有されていないウィンドウを WS_EX_APPWINDOW 拡張スタイルで作成します。ウィンドウ ボタンがタスク バーに配置されないようにするには、所有されていないウィンドウを WS_EX_TOOLWINDOW 拡張スタイルで作成します。別の方法として、非表示のウィンドウを作成し、この非表示のウィンドウを可視ウィンドウの所有者にすることができます。