avpdnepr
@avpdnepr
Человек без любви опаснее тигра и акулы?

Как решить проблему с модальными окнами?

Здравствуйте.

У меня средняя по размерам программа. Она полностью закончена.
Есть большая проблема с модальными окнами. Они время от времени прячутся за основным окном. Спасает положение переключение на другое приложение через Alt+Tab, а потом переключение на мою программу.
Мне сказали, что есть такая проблема. Но как её решать к сожалению не сказали.
Возможно тут, на этом форуме, есть кто-то кто спасёт моё положение.
Напишет решение данной проблемы.

Компиляция на C++ Builder 2009
  • Вопрос задан
  • 1146 просмотров
Пригласить эксперта
Ответы на вопрос 3
xpert13
@xpert13
Full Stack Developer
Это проблема борладовского VCL. На Delphi тоже самое (что не странно, ведь VCL используется тот же).

Модальное окно прячется в момент сворачивания/разворачивания окна. Мне в своё время помог следующий рецепт: для модального окна добавить такой код (код на Delphi, думаю перевести сможете):

type
  TfrmModal = class(TForm)
  private
    procedure WMSYSCOMMAND(var Msg: TWMSYSCOMMAND); message WM_SYSCOMMAND;
  end;

...

procedure TfrmModal.WMSYSCOMMAND(var Msg: TWMSYSCOMMAND);
begin
  case (Msg.CmdType and $FFF0) of
    SC_MINIMIZE:
    begin
      Msg.Result := 0;
      EnableWindow(Application.Handle, True);
      Application.Minimize;
    end;

    else inherited;
  end;
end;


Эту процедуру можно добавить в каждое модальное окно, а можно создать класс с этим методом, от которого наследовать все модальные окна (вместо TForm).

----

UPD: Попробую перевести на C++, но проверить не могу:
header:
private: // of TForm1 class
  void __fastcall WMSysCommand(TMessage &Msg); 

BEGIN_MESSAGE_MAP 
    MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, WMSysCommand) 
END_MESSAGE_MAP(TForm)


cpp:
void __fastcall TForm1::WMSysCommand(TMessage &Msg)
{
    unsigned int const sys_code = Msg.WParam & 0xFFF0;
    switch (sys_code)
    {
        case SC_MINIMIZE:
        {
            Msg.Result = 0;
            EnableWindow(Application.Handle, True);
            Application.Minimize();
            return;
        }
    }
    TForm::Dispatch(&Msg);
}
Ответ написан
Adamos
@Adamos
Например, так: в классе родительского окна заведите член - указатель на модальный диалог. В нем должен быть NULL по умолчанию и при закрытии диалогов.
В методе обновления / отрисовки / idle (что там вы можете переопределить) проверяете, есть ли значение у этого члена. Если есть - посылаете ему ToTop или как оно там у Борланда называется.
Примерно так.

Можно еще поиграться с выставлением основному окну Enable(false) при открытии диалога, но это уже шаманство, и на другом компьютере поведение может отличаться.
У вас проблема-то, скорее всего, из-за чудес оконного менеджера Восьмерочки-Десяточки, не разобравшегося, что диалог модальный и рассматривать его, как отдельное окно, не нужно.
Ответ написан
Комментировать
@sitev_ru
sitev.ru - мой блог ...
Очень странно... По идее, они не могут прятаться, так как они модальные... Как Вы их вызываете? ShowModal?

Но если это так, можно попробывать следующие действия:

1. Для каждого окна перехватывать событие скрытия модального окна и выводить его поверх всех окон

2. Тоже самое делать по таймеру. Настроить, например, на 200 - 500 мсек. Конечно же, по таймеру делать, это от безисходности ))

3. Перейти на более-менее последнюю версию билдера
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы