15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Как сохранить MDI окно всегда поверх остальных

Проблема в том, что не существует стилей для того, чтобы вновь создаваемое MDI окно было всегда поверх остальных MDI окон. Однако, существуют два способа решения данной задачи:

  • Обработать сообщение WM_WINDOWPOSCHANGED и вызвать SetWindowPos() чтобы изменить Z-порядок окна.

  • Создать таймер для MDI окон и сбросить Z-порядок окна при обработке сообщения WM_TIMER.

MDICREATESTRUCT имеет поле "style", которое может быть установлено со стилями для нового MDI окна. Расширенные стили, такие как WS_EX_TOPMOST, не доступны для MDI окон. Это поле в структуре MDICREATESTRUCT передаётся в CreateWindowEx() в параметре dwStyle. Поле dwExStyle установлено в 0L. Два метода, показанные ниже, не могут быть использованы в одно и тоже время в одном приложении.

Первый метод: Обрабатываем сообщение WM_WINDOWPOSCHANGED и вызываем SetWindowPos() чтобы изменить Z-порядок окна.

Пример кода

   LRESULT CALLBACK MdiWndProc (HWND hWnd, UINT message, WPARAM wParam,
                       LPARAM lParam)
   {
       static HWND hWndAlwaysOnTop = 0;
       switch (message)
        {
        case WM_CREATE :
            if (!hWndAlwaysOnTop)
             {
             SetWindowText (hWnd, "Always On Top Window");
             hWndAlwaysOnTop = hWnd;
             }
               break;
        case WM_WINDOWPOSCHANGED :
            if (hWndAlwaysOnTop)
             {
             WINDOWPOS FAR* pWP = (WINDOWPOS FAR*)lParam;
             if (pWP->hwnd != hWndAlwaysOnTop)
                 SetWindowPos (hWndAlwaysOnTop, HWND_TOP, 0, 0, 0, 0,
                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
             }
            break;
        // 
        // Здесь обрабатываются остальные сообщения.
        // 
        case WM_CLOSE :
            if (hWndAlwaysOnTop == hWnd)
             hWndAlwaysOnTop = NULL;
        default :
            return DefMDIChildProc (hWnd, message, wParam, lParam);
        }
       return 0L;
   } 

Второй метод: Устанавливаем таймер для MDI окон и сбрасываем Z-порядок окна при обработке сообщения WM_TIMER.

Пример кода

   LRESULT CALLBACK MdiWndProc (HWND hWnd, UINT message, WPARAM wParam,
                       LPARAM lParam)
   {
       static HWND hWndAlwaysOnTop = 0;
       switch (message)
        {
        case WM_CREATE :
            SetTimer (hWnd, 1, 200, NULL);
            if (!hWndAlwaysOnTop)
             {
             SetWindowText (hWnd, "Always On Top Window");
             hWndAlwaysOnTop = hWnd;
             }
               break;
        case WM_TIMER :
            if (hWndAlwaysOnTop)
             {
             SetWindowPos (hWndAlwaysOnTop, HWND_TOP, 0, 0, 0, 0,
                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
             }
            break;
        case WM_DESTROY:
            KillTimer (hWnd, 1) ;
            break;
        // 
        // Здесь обрабатываются остальные сообщения.
        // 
        case WM_CLOSE :
            if (hWndAlwaysOnTop == hWnd)
             hWndAlwaysOnTop = NULL;
        default :
            return DefMDIChildProc (hWnd, message, wParam, lParam);
        }
       return 0L;
   }