線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3458
推到 Plurk!
推到 Facebook!

Thread 中 GetMessage 的使用方式?

缺席
adonis
高階會員


發表:140
回覆:258
積分:159
註冊:2002-04-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-09-12 17:13:15 IP:210.201.xxx.xxx 訂閱

各位前輩 ~

我產生一個 Thread ,在其Execute中填入以下代碼 ~

var MEMsg: Msg;
Begin
while True do
begin
if DoneThread then Exit; //結束觸發
While GetMessage(MEMsg, RtnFrmHnd, 0, 0) do
begin
if MEMsg.message=WM_MOUSEMOVE then
begin
MoveWindow(RtnFrmHnd,MEMsg.pt.x-(WinW div 2),MEMsg.pt.y-(WinH div 2),WinW,WinH,True);
end;
DispatchMessage(MEMsg);
end;
end;
end;

其中RtnFrmHnd為主Form的Handle,於Thread Create 時傳入.....

但重點是只要執行至 GetMessage(MEMsg, RtnFrmHnd, 0, 0) 該行時不會進入至其裡頭的判斷區,請問,

該如何在自行Create的Thread 中透過GetMessage去取得主Form的訊息佇列中的訊息?

以上,謝謝 ~~~

------
我也在努力學習中,若有錯謬請見諒。
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-09-12 17:48:10 IP:211.23.xxx.xxx 未訂閱

1.一般在 Delphi 的 Form 裡必需定義要處理的訊息,才可能收到那個你要定義的訊息.至於怎麼定義,可參考 OnLine help 的 Overriding the handler method 章節(搜尋一下會找到的)

2.如果你是用 Thread 的話,建議你可以用呼叫 SetWindowLong 這個 API ,應該可以補捉到你要的訊息.

至於你用 Thread ,我不曉得用意為何,理論上你用 SetWindowLog ,應該是不可以用 Thread 才是,

尤其你又在 Thread 裡去更動 GUI ....
===================引 用 文 章===================

各位前輩 ~

我產生一個 Thread ,在其Execute中填入以下代碼 ~

var MEMsg: Msg;
Begin
while True do
begin
if DoneThread then Exit; //結束觸發
While GetMessage(MEMsg, RtnFrmHnd, 0, 0) do
begin
if MEMsg.message=WM_MOUSEMOVE then
begin
MoveWindow(RtnFrmHnd,MEMsg.pt.x-(WinW div 2),MEMsg.pt.y-(WinH div 2),WinW,WinH,True);
end;
DispatchMessage(MEMsg);
end;
end;
end;

其中RtnFrmHnd為主Form的Handle,於Thread Create 時傳入.....

但重點是只要執行至 GetMessage(MEMsg, RtnFrmHnd, 0, 0) 該行時不會進入至其裡頭的判斷區,請問,

該如何在自行Create的Thread 中透過GetMessage去取得主Form的訊息佇列中的訊息?

以上,謝謝 ~~~

aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-09-12 18:01:40 IP:61.229.xxx.xxx 未訂閱
你撈過河了! MainForm裡就有自己的GetMessage方法,你要和他搶可能是行不通的,而且一份Msg經過一次的GetMessage就會吃掉了,理論上輪不到你的thread。看了一下你的程式碼,覺得不需要thread來處理,在thread裡處理並不會比較快,許多人覺得thread好像是萬能的,好像會更快,事實上是更慢! 它只是產生幻覺讓你覺得二件事都在處理,但事實上是每一件事都變慢。還是在MainForm上處理你的事件吧! 不過我想你會想要放到thread中,大概是因為在MainForm上沒有你要的效能,但轉到thread裡只會更差! 若硬是要…那也只能在MainForm裡去攔,然後SendMessage給thread(我沒試看這方式)。但這樣脫褲子放屁…

若是效能的問題,應該要再想別的辦法,或者是用VC ,不是我覺得它好用,而是它的MFC是輕型的class library,跑起來一定是比較快的(與使用VCL來比)。

或者,你想要達成怎樣的功能? 可以post上來,也許有別的解決辦法!
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
adonis
高階會員


發表:140
回覆:258
積分:159
註冊:2002-04-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-09-12 19:17:16 IP:61.62.xxx.xxx 訂閱

謝謝兩位前輩的說明

之所以會想在 Thread 來處理,最主要的想法是由於我想控制一個視窗(大小為 400*200)當我的滑鼠移到哪時,視窗會以滑鼠為中心點的方式來定位,也就是所移到的位置可讓當下的游標正好是在視窗的正中間..

所以很自然的會在 OnMouseMove 中來實現,但發現若滑鼠移動的速度太快時(因為移動時,該視窗的畫面會跟著異動)會發生跟不上的情形,所以才想用 Thread 來處理。

初時,只是在 Execute 中去判斷滑鼠當下的座標與前一次的座標是否相同,果然,不論滑鼠移的再快,視窗都不會有跟不上的情形。但卻發現工作管理員的效能約 50 % .. 所以才會開始思考,如果可以去捕捉到滑鼠移動的事件,再來作相對應的動作,這樣應該就不會造成效能上的浪費..

不知有何方法可以解決,謝謝 ~~

------
我也在努力學習中,若有錯謬請見諒。
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2006-09-13 00:54:23 IP:61.229.xxx.xxx 未訂閱
你好,確認一下,你的意思就是說若使用thread,配合一直loop不停的查mouse pos,然後再move window是很ok的?只是效能效cpu一直滿在50%的水位,所以想當有事件來時再執行thread中的code,這樣省資源是嗎? 還有,你的整個功能裡並不會一直用到mouse move? 只是在某情形下,或是某子功能下才會的是嗎?

若是,我可能有另一個解決的辦法。
===================引 用 文 章===================

謝謝兩位前輩的說明

之所以會想在 Thread 來處理,最主要的想法是由於我想控制一個視窗(大小為 400*200)當我的滑鼠移到哪時,視窗會以滑鼠為中心點的方式來定位,也就是所移到的位置可讓當下的游標正好是在視窗的正中間..

所以很自然的會在 OnMouseMove 中來實現,但發現若滑鼠移動的速度太快時(因為移動時,該視窗的畫面會跟著異動)會發生跟不上的情形,所以才想用 Thread 來處理。

初時,只是在 Execute 中去判斷滑鼠當下的座標與前一次的座標是否相同,果然,不論滑鼠移的再快,視窗都不會有跟不上的情形。但卻發現工作管理員的效能約 50 % .. 所以才會開始思考,如果可以去捕捉到滑鼠移動的事件,再來作相對應的動作,這樣應該就不會造成效能上的浪費..

不知有何方法可以解決,謝謝 ~~

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
adonis
高階會員


發表:140
回覆:258
積分:159
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2006-09-13 09:38:48 IP:210.201.xxx.xxx 訂閱


===================引 用 文 章===================
你好,確認一下,你的意思就是說若使用thread,配合一直loop不停的查mouse pos,然後再move window是很ok的?只是效能效cpu一直滿在50%的水位,所以想當有事件來時再執行thread中的code,這樣省資源是嗎? 還有,你的整個功能裡並不會一直用到mouse move? 只是在某情形下,或是某子功能下才會的是嗎?

若是,我可能有另一個解決的辦法。
===================引 用 文 章===================

嗯..是呀,初時的作法僅在thread中簡單的判斷mouse pos 是否異動,如果有就 move window 至相對位置,如此是沒問題的,不論滑鼠移動再快也都一定跟的上,沒掉過 ~ 只是效能 cpu 會一直定在 50% 左右.. 所以才會有接下來的想法,如果只有在滑鼠有 move event 時才來處理是否會更節省資源..... 整個功能中只要按 ESC 鍵該功能就不會生效 ~~

解決辦法?願聞其詳 ~~ 謝謝 ...

------
我也在努力學習中,若有錯謬請見諒。
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2006-09-13 11:43:06 IP:61.229.xxx.xxx 未訂閱

你好,先說明一下喔…我是多年不寫delphi了,但一直有使用BCB,所以delphi完整的程式碼我可能沒辦法寫出,加上我的系統沒有安裝delphi來為你測式。但昨天我才發表了一個有關thread的程式,雖然你也許也沒裝bcb,或是不太了解,但可以用notepad打開看cpp檔裡關於thread的部份。

http://delphi.ktop.com.tw/board.php?cid=168&fid=912&tid=84144

除了程式讓你參考,我還是把重要的關念和api和你說: (若你不看上面的例子),下面的delphi語法也許有錯,我忘得差不多了…請自己修正。

1/ 先建立一個全域的Event Handler,那是用來告知thread是否要先暫停(不會cost資源),或是繼續。那是個win32 API.
type
......
var
mDoWorkFlag : HANDEL;

mDoWorkFlag := CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is signaled
"NotifyWork" // object name
); //此例假設存放在mDoWorkFlag 變數中,可放在Form OnCreate事件中
2/ 在thread 中的開頭改寫成
while (!Terminated && WaitForSingleObject(mDoWorkFlag,INFINITE)==0L)
begin
//這否有差異,若有則移動…
..........
..........
ResetEvent(mDoWorkFlag); //要在thread這個unit中use 那個全域變數喔! 這是放最後一行,表示回到while中會停住
end

3/ 在form1的OnMouseOver 中加入
SetEvent(mDoWorkFlag); //這樣就會觸發thread去跑

4/ 在form 的OnDestory裡加入
CloseHandle(mDoWorkFlag); // 把event 的資源還給windows

PS。有個小小請求,就是可以把試的結果和我講嗎? 無論成功與否… 謝謝。當然還有cpu資源的情形。

蕭沖 qs.xiao@gmail.com
http://aftcast.blogspot.com/
生有涯,知無涯

===================引 用 文 章===================

嗯..是呀,初時的作法僅在thread中簡單的判斷mouse pos 是否異動,如果有就 move window 至相對位置,如此是沒問題的,不論滑鼠移動再快也都一定跟的上,沒掉過 ~ 只是效能 cpu 會一直定在 50% 左右.. 所以才會有接下來的想法,如果只有在滑鼠有 move event 時才來處理是否會更節省資源..... 整個功能中只要按 ESC 鍵該功能就不會生效 ~~

解決辦法?願聞其詳 ~~ 謝謝 ...

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2006-09-13 11:44:21 IP:61.229.xxx.xxx 未訂閱

你好,先說明一下喔…我是多年不寫delphi了,但一直有使用BCB,所以delphi完整的程式碼我可能沒辦法寫出,加上我的系統沒有安裝delphi來為你測式。但昨天我才發表了一個有關thread的程式,雖然你也許也沒裝bcb,或是不太了解,但可以用notepad打開看cpp檔裡關於thread的部份。

http://delphi.ktop.com.tw/board.php?cid=168&fid=912&tid=84144

除了程式讓你參考,我還是把重要的關念和api和你說: (若你不看上面的例子),下面的delphi語法也許有錯,我忘得差不多了…請自己修正。

1/ 先建立一個全域的Event Handler,那是用來告知thread是否要先暫停(不會cost資源),或是繼續。那是個win32 API.
type
......
var
mDoWorkFlag : HANDEL;

mDoWorkFlag := CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is signaled
"NotifyWork" // object name
); //此例假設存放在mDoWorkFlag 變數中,可放在Form OnCreate事件中
//是為了配合WaitForSingleObject這個api用的
2/ 在thread 中的開頭改寫成
while (!Terminated And WaitForSingleObject(mDoWorkFlag,INFINITE)=0)
begin
//這否有差異,若有則移動…
..........
..........
ResetEvent(mDoWorkFlag); //要在thread這個unit中use 那個全域變數喔! 這是放最後一行,表示回到while中會停住
end

3/ 在form1的OnMouseOver 中加入
SetEvent(mDoWorkFlag); //這樣就會觸發thread去跑

4/ 在form 的OnDestory裡加入
CloseHandle(mDoWorkFlag); // 把event 的資源還給windows

PS。有個小小請求,就是可以把試的結果和我講嗎? 無論成功與否… 謝謝。當然還有cpu資源的情形。

蕭沖 qs.xiao@gmail.com
http://aftcast.blogspot.com/
生有涯,知無涯

===================引 用 文 章===================

嗯..是呀,初時的作法僅在thread中簡單的判斷mouse pos 是否異動,如果有就 move window 至相對位置,如此是沒問題的,不論滑鼠移動再快也都一定跟的上,沒掉過 ~ 只是效能 cpu 會一直定在 50% 左右.. 所以才會有接下來的想法,如果只有在滑鼠有 move event 時才來處理是否會更節省資源..... 整個功能中只要按 ESC 鍵該功能就不會生效 ~~

解決辦法?願聞其詳 ~~ 謝謝 ...

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
adonis
高階會員


發表:140
回覆:258
積分:159
註冊:2002-04-15

發送簡訊給我
#9 引用回覆 回覆 發表時間:2006-09-13 11:56:29 IP:210.201.xxx.xxx 訂閱

aftcast 謝謝您熱心的回應 ~ 待測試結果完後定會回應相關情況,先謝了,若有操作使用上的疑惑,還要請您多協助,謝謝。

------
我也在努力學習中,若有錯謬請見諒。
adonis
高階會員


發表:140
回覆:258
積分:159
註冊:2002-04-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2006-09-14 09:56:03 IP:210.201.xxx.xxx 訂閱

aftcast ~

我已完成測試,結果是不可行的.. 我在想,是否為當滑鼠移動的太快時,會造成訊息的捕捉上來不及,倒致於沒有攔截到該訊息,以致無法在 OnMouseMove 中觸發事件,先前簡單的判斷其實就是放在 OnMouseMove 中,但就因為當滑鼠移動的太快時會有視窗跟掉的情形,才會有後續的想法。

而今天的 SetEvent 也是放在 OnMouseMove 中,所以可想見測試結果會是一樣的..

目前用一個雖簡單但可以解決問題的作法,但總覺得不太正統似的.. 我在 Thread 的迴圈中加了一個 sleep(10) .. 沒想到原先的cpu效能約 50% 的資源浪費就不見了,回到原本的 1%-2% 之間.. 真是太神奇了.. 對人類而言,那 10 雖算不得什麼,但對於計算機的處理速度而言卻是相當漫長的..

不知是否還有更何適的做法??

------
我也在努力學習中,若有錯謬請見諒。
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#11 引用回覆 回覆 發表時間:2006-09-14 10:52:47 IP:61.229.xxx.xxx 未訂閱
謝謝你的回應!

我想你最後的這個方法應該是最好的了! 我剛想了一想… MouseMove是一連串的的事件,經過windows的queue,然後再通知我們的AP,我們的AP在去針對超多個msg做repaint,這應該會花超多的時間和資源。

而你所謂的在thread中,我想應該是直接用api去get mouse cursor的位置吧? 這個api很單統也很快,沒所謂的queue問題,若不在意要極端的快,再sleep幾ms應該會更省cpu的資源。

程式沒什麼正統與否,最好的方案就應該是「正統」,而且也沒什麼副作用,不是嗎? 在我們交換心得的過程中,我也學習到一些。這算是教學相長吧!

方便提供一下你thread中的exec的程式碼嗎? 我想有許多人也有這樣的需求,至少前些日子我也看到有人問什麼圖追不上,或是window追不上的…

謝謝你!
===================引 用 文 章===================

aftcast ~

我已完成測試,結果是不可行的.. 我在想,是否為當滑鼠移動的太快時,會造成訊息的捕捉上來不及,倒致於沒有攔截到該訊息,以致無法在 OnMouseMove 中觸發事件,先前簡單的判斷其實就是放在 OnMouseMove 中,但就因為當滑鼠移動的太快時會有視窗跟掉的情形,才會有後續的想法。

而今天的 SetEvent 也是放在 OnMouseMove 中,所以可想見測試結果會是一樣的..

目前用一個雖簡單但可以解決問題的作法,但總覺得不太正統似的.. 我在 Thread 的迴圈中加了一個 sleep(10) .. 沒想到原先的cpu效能約 50% 的資源浪費就不見了,回到原本的 1%-2% 之間.. 真是太神奇了.. 對人類而言,那 10 雖算不得什麼,但對於計算機的處理速度而言卻是相當漫長的..

不知是否還有更何適的做法??

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
adonis
高階會員


發表:140
回覆:258
積分:159
註冊:2002-04-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2006-09-14 11:09:07 IP:210.201.xxx.xxx 訂閱

謝謝您熱心的回應

當你提到用 Create Event 時,我就想起先前用這方法來同步抓 COM Port 的 Data.. 那時也是用這方式來同步 ~~

哦,我的想法很簡單,所以 Code 的想法也很單純 ~

procedure TCurPos.Execute;
var nPos: TPoint;
Begin
while True do
begin
if DoneThread then Exit;

sleep(10); //避免資源被消耗
GetCursorPos(nPos);
if (prePos.x<>nPos.x) or (prePos.y<>nPos.y) then
begin
prePos.x:=nPos.x;
prePos.y:=nPos.y;
MoveWindow(RtnFrmHnd,nPos.x-(WinW div 2),nPos.y-(WinH div 2),WinW,WinH,True);
end;
end;
end;

prePos 是一個全域變數,而RtnFrmHnd為所要追蹤的視窗。

以上,謝謝 ~~

------
我也在努力學習中,若有錯謬請見諒。
系統時間:2024-04-24 1:03:28
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!