2008-11-13 44 views
2

在Delphi 2006中,我展示了一種模態形式。該表單中的用戶輸入可以更改當前在作爲mainform的父表單上顯示的數據。爲了反映這些變化,我需要強制重繪mainform上的一些ownerdraw組件。我試圖做這樣的模式形式:如何在模態窗體處於活動狀態時重新繪製父窗體?

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

這並沒有改變一點。我一直認爲表單上的「更新」會一直重新繪製 - 顯然不是這樣。繪畫代碼本身應該是可以的,因爲我可以通過這些ownerdraw組件移動模態窗體來強制手動重畫。

但是,如何在數據更改時以編程方式強制重繪?

編輯:我會嘗試Application.ProcessMessages和刷新下週,感謝您的建議。

對不起,花了這麼長的時間來回答,並感謝所有誰迴應。調用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 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); 

確保完成設置爲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; 

然後將代碼運行時應用程序處於空閒狀態,和消息循環被正常處理。請記住在完成時將Application.OnIdle設置爲零。

如果DoProcess有點太快,你可以選擇每次調用onidle做5或10次迭代。

+0

謝謝 - 但這不是關於一些後臺任務/線程。用戶只是改變了全局數據,並立即生效,因爲當模態表單關閉時我無法取消它。更改後的全局數據應該重新繪製當前顯示它的mainform。 – 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

相關問題