2016-05-19 3 views
0

Я создал MCV этой проблемы, и я счастлив ее загрузить. Сначала я попытаюсь описать проблему.Сетка сетки за модальным окном

  1. Создайте главное окно и поместите TDBGrid, подключенный к таблице, через любую доступную базу данных. OnShow окна подключиться к базе данных и открыть таблицу.

  2. Создайте кнопку в главном окне, которое запускает немодальное окно.

  3. В немодальном окне создайте кнопку, которая запускает модальное окно.

Выполните следующие действия, чтобы воспроизвести проблему.

  1. Запуск приложения.

  2. Поместите фокус в сетку и используйте колесико мыши, чтобы прокручивать вверх и вниз.

  3. Нажмите кнопку, чтобы запустить немодальное окно.

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

  5. Пока все еще сфокусировано в сетке, нажмите кнопку в немодальном окне, чтобы запустить модальное окно.

  6. Пока модальное окно открыто, наведите указатель мыши на сетку и используйте колесо мыши. Вы увидите, что сетка прокручивается вверх и вниз.

Это не происходит на Windows 7, но на Windows, 10. Это может показаться безобидным, но это особенно опасно, когда у вас есть несколько слоев родитель потомок, построенных через 3 окна.

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

Следует отметить, что между шагами 4 и 5, если вы не ставите фокус в сетку перед запуском модального окна, эта проблема не возникает. Я попытался настроить фокус программно на элемент управления в немодальном окне, прежде чем показывать модальное окно без успеха.

+1

ли правильно отключить главное окно, когда модальное окно показывает? –

+0

Я не уверен, как проверить это? Я предполагаю, что он не отключен должным образом, но только на Windows 10. – FLDelphi

+1

Он делает. AAMOF Я могу дублировать его с помощью сетки строк на W7. –

ответ

3

Это ошибка в коде VCL. Чтобы дублировать проблему в обычном приложении, как отмечено в комментариях, необходимо включить включенную функцию прокрутки окна Windows 10 или программное обеспечение, обеспечивающее аналогичную функциональность в более ранних ОС.

Однако можно продемонстрировать проблему без особых требований. Это было бы более простое воспроизведение, чем в вопросе.

Бросьте StringGrid и кнопки на форме кнопки, имеющая следующий код в обработчик щелчка:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    StringGrid1.Enabled := False; 
    SetFocusedControl(StringGrid1); 
end; 

Нажмите кнопку и наведите курсор на сетку и прокрутки. Отключено как есть, сетка не должна прокручиваться, но это так.

Ниже приведено более подходящее описание проблемы. Это потому, что модальное окно отключает форму, содержащую сетку, которая затем отправляется сообщением колеса мыши. Сообщение колеса синтезируется для сред, которые не имеют указанных требований.

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Pt: TPoint; 
begin 
    Enabled := False; 
    Pt := Point(1, 1); 
    MapWindowPoints(StringGrid1.Handle, HWND_DESKTOP, Pt, 1); 
    SetFocusedControl(StringGrid1); 
    Perform(WM_MOUSEWHEEL, MakeWParam(0, WORD(-120)), MakeLParam(Pt.X, Pt.Y)); 
end; 

Нажмите Ctrl + F2 после того, как увидите, что сетка прокручивается.


Основной причиной проблемы является то, что VCL не заботится о том, включен ли элемент управления или нет, когда он решает, является ли это сфокусированным элементом управления, и при этом он выполняет сообщение колеса мыши. Мутировав сообщение колеса мыши на CM_MOUSEWHEEL и полностью обойдя процедуру окна по умолчанию, VCL должен был выполнять эти проверки.

Для решения проблемы, вы можете установить целенаправленный контроль на другой контроль перед запуском модальной формы:

MainForm.SetFocusedControl(MainForm); 
OtherForm.ShowModal; 

Вы не можете установить ActiveControl здесь, потому что один имеют необходимое видимость/проверку состояния в место.

Если вы не хотите быть связаны с основной формой, вы можете поставить обработчик сообщений колеса мыши на главную форму:

type 
    TMainForm = class(TForm) 
    ... 
    protected 
    procedure WMMouseWheel(var Message: TWMMouseWheel); message WM_MOUSEWHEEL; 

... 

procedure TMainForm.WMMouseWheel(var Message: TWMMouseWheel); 
begin 
    if IsWindowEnabled(Handle) then 
    inherited; 
end; 
Смежные вопросы