Win32 SetForegroundWindow ненадежный - PullRequest
14 голосов
/ 22 сентября 2010

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

Моя проблема заключается в том, что каждые 5 или 6 раз при переключении приложений на переднем плане просто не получаетсяподать заявку.GetLastError не сообщает о каких-либо проблемах.Часто я на мгновение вижу правильное приложение на переднем плане, затем видно предыдущее приложение.

У меня есть приложение Manager, для которого у меня есть источник, оно порождает и контролирует около 4 приложений, которых у меня нетисточник для.одно из приложений, которое он порождает / контролирует, - это также менеджер, который порождает / контролирует около 5 приложений.

Это своего рода дизайн киоска, поэтому у пользователя даже не будет клавиатуры или мыши, только сенсорный экран.

Я пробовал каждую комбинацию вызовов Win32, чтобы контролировать их. У меня просто нет идей.

Моя первая попытка была:

SetWindowPos(hApp, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(hApp, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);

Моя вторая попытка была:

SetForegroundWindow(hApp);
SetActiveWindow(hApp);
SetFocus(hApp);

моя третья попытка: DWORD dwThreadID = GetWindowThreadProcessId (hApp, NULL);AttachThreadInput (dwThreadID, GetCurrentThreadId (), true);

SetForegroundWindow(hApp);
SetActiveWindow(hApp);
SetFocus(hApp);

AttachThreadInput( dwThreadID, GetCurrentThreadId(), false);

моя четвертая попытка:

DWORD dwThreadID = GetWindowThreadProcessId(hApp, NULL);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), true);

SetWindowPos(hApp, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(hApp, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);

SetForegroundWindow(hApp);
SetActiveWindow(hApp);
SetFocus(hApp);

AttachThreadInput( dwThreadID, GetCurrentThreadId(), false);

Мне кажется, что я упускаю важный момент, когда дело доходит до переключения окон.Я знаю, что только процесс переднего плана может переключать окна, но поскольку моя главная программа Manager порождает и запускает все другие процессы, которые мне нужно контролировать, я чувствую, что она должна быть способна перемещать эти окна.Любые предложения или советы приветствуются.

Ответы [ 7 ]

10 голосов
/ 24 августа 2012

У меня была та же проблема, и я не хотел связываться с потоками.При экспериментировании я наблюдал простой взлом, чтобы заставить SetForegroundWindow () работать ожидаемым образом.Вот что я сделал:

  1. Сверните окно, если оно еще не свернуто
  2. Восстановите свернутое окно
  3. Вызовите SetForegroundWindow (), и ваше окно будет включеноtop
5 голосов
/ 22 сентября 2010

Ваш хак AttachThreadInput () - это (я думаю) известный способ победить противодействие фальсификации в Windows. Вы используете неправильный дескриптор, вы хотите присоединиться к потоку, который в данный момент имеет фокус. Что не будет hApp, в противном случае вам не понадобится этот код.

Используйте GetForegroundWindow (), чтобы получить дескриптор окна с фокусом.

AttachThreadInput(
    GetWindowThreadProcessId(GetForegroundWindow(), NULL),
    GetCurrentThreadId(), TRUE
);

Хотя я думаю, что вторым аргументом должен быть идентификатор потока hApp. Потому что ты не хочешь запихивать свое окно, если я правильно понял. Не уверен, что это может сработать.

2 голосов
/ 06 октября 2015

Самое простое решение в C #, чтобы вывести окно на передний план:

Если у вас есть ручка для окна, вы можете просто позвонить:

    SetWindowPos(handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
    ShowWindow(handle, 5);
    SetForegroundWindow(handle);

    // If it is minimized, show the window
    if (IsIconic(handle))
    {
      ShowWindow(handle, 3);
    }

, где

const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const int SWP_SHOWWINDOW = 0x0040;
2 голосов
/ 17 октября 2011

Некоторые окна заблокированы с помощью setforeground (...), Вы должны разблокировать их. Эта последовательность полезна для любого окна:

HWND needTopWindow=FindWindow(TEXT("classname"), TEXT("window name"));

имя класса и имя окна, которое вы можете получить с помощью ranorexspy, например, nanoware.cz

if(!::IsWindow(needTopWindow)) return;

BYTE keyState[256] = {0};
//to unlock SetForegroundWindow we need to imitate Alt pressing
if(::GetKeyboardState((LPBYTE)&keyState))
    {
    if(!(keyState[VK_MENU] & 0x80))
        {
        ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
        }
    }

    ::SetForegroundWindow(needTopWindow);

if(::GetKeyboardState((LPBYTE)&keyState))
    {
        if(!(keyState[VK_MENU] & 0x80))
        {
            ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
        }
    }


        DWORD dwThreadID = GetWindowThreadProcessId(needTopWindow, NULL);
        AttachThreadInput( dwThreadID, GetCurrentThreadId(), true);

        SetWindowPos(needTopWindow, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
        SetWindowPos(needTopWindow, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);

        SetForegroundWindow(needTopWindow);
        SetActiveWindow(needTopWindow);
        SetFocus(needTopWindow);

        AttachThreadInput( dwThreadID, GetCurrentThreadId(), false);
1 голос
/ 23 сентября 2010

У нас была похожая проблема пару лет назад. Мы могли бы решить это следующим вызовом функции:

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_UPDATEINIFILE);

Дай ему попробовать. Смотри документацию здесь .

0 голосов
/ 24 июля 2015

Вы также должны учитывать вероятность того, что окно будет свернуто. Если окно или другое приложение свернуто, SetForegroundWindow (hApp) не будет работать. Для безопасности используйте ShowWindow (hApp, 9); Я предпочитаю значение 9. Посмотрите его документацию и выберите то, что вам подходит.

0 голосов
/ 22 сентября 2010

Попробуйте сначала переместить другие окна приложения в фоновый режим.

Также немного странно, что вы используете SetWindowPos (SWP), чтобы выдвинуть окно на передний план, а затем вытолкнуть его из заброшенного объекта перед использованием SetForegroundWindow, чтобыверни его назадЛично я всегда использовал метод SWP без каких-либо проблем ... но я всегда сдвигал и другие окна вниз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...