2008-11-13 3 views
2

В Delphi 2006, я показываю модальную форму. Пользовательский ввод в этой форме может изменять данные, которые могут отображаться в настоящее время в родительской форме, которая является основной формой. Чтобы отразить эти изменения, мне нужно принудительно перекрасить некоторые компоненты, принадлежащие владельцу, на основную форму. Я попытался сделать это вот так из модальной формы:Как перерисовать родительскую форму, пока модальная форма активна?

MainForm := Application.MainForm; 
MainForm.Invalidate; 
MainForm.Update; 

Это не изменилось. Я всегда думал, что «обновление» на форме всегда будет перерисовывать его сразу - видимо, не так. Сам код картины должен быть в порядке, так как я могу перемещать модальную форму поверх этих компонентов ownerdraw, чтобы принудительно перерисовать вручную.

Но как я могу принудительно перекрасить при изменении данных?

Редактировать: Я попробую Application.ProcessMessages и Refresh на следующей неделе, спасибо за предложения.

Извините за то, что вы так долго отвечали и благодарили всех, кто ответил. Вызов Refresh() был частью решения, но он должен был выполняться на пользовательских компонентах рисования, а не на форме, в которой они были ... Теперь я хотел бы принять более одного ответа ;-)

ответ

2

Возможно, стоит упомянуть, что если вы используете библиотеку скиннинга, которая может повлиять и на вещи. Я обнаружил, что мне нужно было обновить библиотеку скиннинга, а не форму.

+0

Я не использую библиотеку скинов, но пользовательские компоненты рисования могут быть сопоставимы с этим. Мне пришлось найти эти компоненты «вручную» и обновить их явно. – 2009-02-10 11:31:16

0

Это возможно, что вы делаете что-то в дочерней форме для блокировки сообщений? Размещено:

Application.ProcessMessages; 

к вашему коду имеет значение?

1

Обновление отправляет сообщение WM_PAINT. Обновление заставляет перерисовать элемент управления, выполняя сообщение о краске. Вместо этого попробуйте .Refresh.

+0

Извините, что ответили на это поздно. К сожалению. Ошибка тоже не работала. Нет эффекта. Тем не менее данные меняются, и если я перемещаю модальный диалог спереди, я могу заставить его перерисовать. – 2009-02-10 11:19:27

1

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

Является ли родительская форма «белой» (т. Е. Перестает рисовать вместе), когда вы перемещаете над ней модальную форму? Если это так, то есть что-то еще не так с тем, как вы вызываете модальную форму, или как предлагалось Kluge, вы блокируете сообщения от отправки (возможно, проблема с потоками).

Я протестировал это, и это работает по умолчанию. Вам нужны две формы: одна с полем редактирования, другая - с кнопкой. Затем назначьте эти обработчики событий:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Form2.ShowModal; 
end; 

и

procedure TForm2.Edit1Change(Sender: TObject); 
begin 
    Form1.Button1.Caption := Edit1.Text; 
end; 

И как вы измените edit1 на второй форме он будет изменить заголовок кнопки на Form1.

+0

«Является ли родительская форма« белой »(т. Е. Перестает рисовать вместе), когда вы перемещаете над ней модальную форму?»: Нет, она не делает, вместо этого она рисует измененные данные - как я писал в вопросе. Работы по окраске, я просто не знаю, как вызвать это. – 2008-11-15 23:45:08

0

Я бы предположил, что ваша модальная форма, вероятно, блокирует сообщения. Если вы находитесь в каком-то цикле, делаете какую-то обработку, пытаясь обновить mainform с прогрессом. Application.ProcessMessages - это один из способов обработки этих сообщений, но imho не очень изящный. Когда у меня был такой тип проблемы, я реализовал обработку в событии Application.OnIdle. В основном, что вам нужно сделать, это разделить вашу обработку на небольшие куски. Итак, скажем, вы обрабатываете некоторый цикл. Сделайте одну итерацию цикла как одну часть задачи. поместите этот код в следующую форму:

procedure DoIdle(Sender: TObject; var Done: Boolean); 

Убедитесь, что для Done установлено значение False.Если код был ранее:

for i := 1 to ProcessCount do 
    DoProcess(i); 

это становится:

procedure MyDoIdle(Sender: TObject; var Done: Boolean); 
begin 
    Inc(TaskCount); 
    If TaskCount <= ProcessCount then 
    DoProcess(TaskCount); 
end; 

и множество вещей следующим образом:

TaskCount := 0; 
Application.Idle := MyDoIdle; 

Код затем запустить всякий раз, когда Приложение Idle, и цикл сообщения обрабатывается как обычно. Не забудьте установить значение параметра Application.OnIdle равным нулю.

Если DoProcess работает слишком быстро, вы можете выбрать, чтобы сказать 5 или 10 итераций за звонок в onidle.

+0

Спасибо - но это не касается некоторых фоновых задач/потоков. Пользователь просто изменил глобальные данные и вступает в силу немедленно, потому что у меня нет способа отменить его, когда модальная форма закрывается. Измененные глобальные данные должны перерисовать основную форму, которая в настоящее время отображает ее. – 2008-11-15 23:48:20

1

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

procedure UpdateApplication; 
// Updates (repaints where nesc) all windows of the app 
    function UpdateWindow(hWnd: HWND; LParam: longint): bool; stdcall; 
    begin 
    Result := True; 
    Windows.UpdateWindow(hWnd); 
    end; 
begin 
    EnumWindows(@UpdateWindow, 0); 
end; 
+1

Спасибо, я буду помнить об этом. На данный момент проблема была решена с помощью .Refresh (и мне пришлось выполнить его непосредственно на компоненте, который нужно обновить, а не на форме, содержащей компонент). – 2009-06-24 09:22:24

Смежные вопросы