Определение того, есть ли в окне кнопка панели задач - PullRequest
9 голосов
/ 14 февраля 2010

Я ищу способ проверить, есть ли в данном окне кнопка панели задач. То есть, учитывая дескриптор окна, мне нужно ИСТИНА, если окно находится на панели задач, и ЛОЖЬ в противном случае.

И наоборот, мне интересно, есть ли способ получить дескриптор окна, принадлежащего данной кнопке панели задач, который, я полагаю, потребовал бы способа перечисления с помощью кнопок панели задач.

(Первая часть - это та часть, которая мне нужна, а вторая часть необязательна.)

Большое спасибо.

Ответы [ 3 ]

11 голосов
/ 15 февраля 2010

Windows использует эвристику, чтобы решить, следует ли отдавать кнопку панели задач окну, и иногда существует задержка, прежде чем она может принять решение, поэтому сделать это на 100% точно будет довольно сложно. Вот грубое начало по правилам. Существуют современные флаги стилей, которые легко узнать, но когда эти стили отсутствуют, панель задач сводится к угадыванию.

Во-первых, вам понадобятся оба флага стиля окна.

LONG Style = GetWindowLong(hwnd, GWL_STYLE);
LONG ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);

Теперь правила, есть три правила, которые являются определенными.

  • если ExStyle & WS_EX_APPWINDOW, то ТАСКБАР
  • если ExStyle & WS_EX_TOOLWINDOW, то NOT_TASKBAR
  • если Style & WS_CHILD, то NOT_TASKBAR

Остальные догадки:

  • Style & WS_OVERLAPPED предлагает TASKBAR
  • Style & WS_POPUP предлагает NOT_TASKBAR, особенно если GetParent() != NULL
  • ExStyle & WS_EX_OVERLAPPEDWINDOW предлагает TASKBAR
  • ExStyle & WS_EX_CLIENTEDGE предлагает NOT_TASKBAR
  • ExStyle & WS_EX_DLGMODALFRAME предлагает NOT_TASKBAR

Я уверен, что существуют другие правила угадывания, и на самом деле правила угадывания меняются от версии к версии Windows.

7 голосов
/ 15 февраля 2010
  1. Окно верхнего уровня

  2. WS_EX_APPWINDOW -> панель задач, независимо от других стилей!

  3. ВЛАДЕЛЕЦ должен быть НЕДЕЙСТВИТЕЛЕН (GetWindow (окно, GW_OWNER))

  4. нет: WS_EX_NOACTIVATE или WS_EX_TOOLWINDOW:

порядок важен.

Второй вопрос: в Windows XP / Vista можно было войти в процесс панели задач и получить все идентификаторы окна:

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. поэтому вам нужно перебрать все окна верхнего уровня.

1 голос
/ 27 сентября 2011

Эта статья MSDN содержит полезную информацию о том, когда и почему Shell решает создать кнопку панели задач для окна:

Оболочка создает кнопку на панели задач всякий раз, когда приложение создает окно, которое не принадлежит. Чтобы убедиться, что кнопка окна находится на панели задач, создайте неизвестное окно с расширенным стилем WS_EX_APPWINDOW. Чтобы кнопка окна не помещалась на панель задач, создайте неиспользуемое окно с расширенным стилем WS_EX_TOOLWINDOW. В качестве альтернативы вы можете создать скрытое окно и сделать его скрытым владельцем видимого окна.

...