全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3160
推到 Plurk!
推到 Facebook!

通過窗體Handle獲取窗體名稱

答題得分者是:RootKit
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-03-31 10:30:38 IP:218.104.xxx.xxx 訂閱
我有創建ProcessTHandle Function可以正確的獲取當前激活的窗體名稱.
目前是我們使用的主程式下面會包含五,六個可能更多的子窗口,我們希望能知道USER在這些子窗口中具體有使用到哪些窗口介面.
所以我想通過窗體的Handle來獲取當前激活的窗體名稱並將其名窗體名稱保存起來.

我現在的問題是:

我現在需要把這個Function放在程式的什麽位置來追蹤USER有激活某個子窗口時執行這個Function,
首先肯定不能放在各個子窗體中去,那樣的話就沒有使用意義了.
也不能使用Timer元件來處理,因這個會占用太多內存資源了.

希望有知道如何處理或有什麽好的建意的大大們幫忙.....
這個急呀......

type
PEnumInfo = ^TEnumInfo;
TEnumInfo = record
ProcessID: DWORD;
HWND: THandle;
end;

function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
var
PID: DWORD;
begin
GetWindowThreadProcessID(Wnd, @PID);
Result := (PID <> EI.ProcessID) or
(not IsWindowVisible(WND)) or
(not IsWindowEnabled(WND));
if not result then EI.HWND := WND;
end;
function FindMainWindow(PID: DWORD): DWORD;
var
EI: TEnumInfo;
begin
EI.ProcessID := PID;
EI.HWND := 0;
EnumWindows(@EnumWindowsProc, Integer(@EI));
Result := EI.HWND;
end;

function TTHandle_Frm.ProcessTHandle(out oName, oMsg: string): Boolean;
var
H: THandle;
begin
try
Result := False;
H := FindMainWindow(GetCurrentProcessId);
if H > 0 then
begin
SetLength(oStr, 255);
GetWindowText(H, PChar(oName), 255);
SetLength(oName, StrLen(PChar(oName)));
Result := True;
end
else
begin
oMsg := 'No Find!';
end;
except
on e: exception do
begin
oMsg := 'ProcessTHandle Exception:' e.Message;
end;
end;
end;
編輯記錄
crw_web 重新編輯於 2008-03-31 10:37:16, 註解 無‧
tcSweey
一般會員


發表:7
回覆:19
積分:15
註冊:2005-01-04

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-03-31 11:28:49 IP:60.249.xxx.xxx 訂閱
用thread應該可以吧。
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-03-31 11:55:23 IP:218.104.xxx.xxx 訂閱
用Thread怎麽做呢?能說具體點嗎?
感覺跟這Thread沒什麽聯系吧......


===================引 用 tcSweey 文 章===================
用thread應該可以吧。
RootKit
資深會員


發表:16
回覆:358
積分:419
註冊:2008-01-02

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-04-01 11:33:43 IP:61.222.xxx.xxx 訂閱
一般不會這樣處理。

處理過專案的老手,通常會為這個專案建立基礎的 BaseFrom 。
因此較正確的作法,是在BaseForm 中 Procedure WMACTIVATE(Var Msg:TMessage);Message WM_ACTIVATE
用訊息攔截就可得知 機活的是誰並配合參數。另外也可以統籌分配共用檢查機制。

另外一點也可透過 Screen.OnActiveFormChange 事件得知視窗焦點異動情形。

補充!不需要勞駕用到 EnumWindows ,因為這些視窗都是已知的。
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-04-01 16:36:36 IP:218.104.xxx.xxx 訂閱
謝謝RootKit 的講解,
確實通過建立基礎的BaseFrom的做法會很方更,
但目前我們的程式無法去這樣做,所以只有在這想別的辦法了.


===================引 用 RootKit 文 章===================
一般不會這樣處理。

處理過專案的老手,通常會為這個專案建立基礎的 BaseFrom 。
因此較正確的作法,是在BaseForm 中 Procedure WMACTIVATE(Var Msg:TMessage);Message WM_ACTIVATE
用訊息攔截就可得知 機活的是誰並配合參數。另外也可以統籌分配共用檢查機制。

另外一點也可透過 Screen.OnActiveFormChange 事件得知視窗焦點異動情形。

補充!不需要勞駕用到 EnumWindows ,因為這些視窗都是已知的。
RootKit
資深會員


發表:16
回覆:358
積分:419
註冊:2008-01-02

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-04-01 20:54:35 IP:61.222.xxx.xxx 訂閱
用 Screen.OnActiveFormChange 將 TFrom(Sender).Caption。

想一下!我覺得你的思考有些誤區。

crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-04-02 10:50:59 IP:218.104.xxx.xxx 訂閱
我有嘗試用創建一個基礎的 BaseFrom,再在這裏面加上Procedure CMACTIVATE(Var Msg:TMessage);Message CM_ACTIVATE
來攔截,目前我又碰到一個問題,就是當在主窗體的FormStyle:=fsMDIForm 子窗體的FormStyle:=fsMDIChild時,我想獲取到子窗體的名稱
可總是獲取到的是
主窗體的名稱,請問我該如何去獲取子窗體的名稱呢?

===================引 用 RootKit 文 章===================
一般不會這樣處理。

處理過專案的老手,通常會為這個專案建立基礎的 BaseFrom 。
因此較正確的作法,是在BaseForm 中 Procedure WMACTIVATE(Var Msg:TMessage);Message WM_ACTIVATE
用訊息攔截就可得知 機活的是誰並配合參數。另外也可以統籌分配共用檢查機制。

另外一點也可透過 Screen.OnActiveFormChange 事件得知視窗焦點異動情形。

補充!不需要勞駕用到 EnumWindows ,因為這些視窗都是已知的。
編輯記錄
crw_web 重新編輯於 2008-04-02 10:52:19, 註解 無‧
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-04-02 13:31:49 IP:218.104.xxx.xxx 訂閱
這個問題解決了.
但目前我們還是不能采用這種方法,工作量太大了.

===================引 用 crw_web 文 章===================
我有嘗試用創建一個基礎的 BaseFrom,再在這裏面加上Procedure CMACTIVATE(Var Msg:TMessage);Message CM_ACTIVATE
來攔截,目前我又碰到一個問題,就是當在主窗體的FormStyle:=fsMDIForm 子窗體的FormStyle:=fsMDIChild時,我想獲取到子窗體的名稱
可總是獲取到的是
主窗體的名稱,請問我該如何去獲取子窗體的名稱呢?

===================引 用 RootKit 文 章===================
一般不會這樣處理。

處理過專案的老手,通常會為這個專案建立基礎的 BaseFrom 。
因此較正確的作法,是在BaseForm 中 Procedure WMACTIVATE(Var Msg:TMessage);Message WM_ACTIVATE
用訊息攔截就可得知 機活的是誰並配合參數。另外也可以統籌分配共用檢查機制。

另外一點也可透過 Screen.OnActiveFormChange 事件得知視窗焦點異動情形。

補充!不需要勞駕用到 EnumWindows ,因為這些視窗都是已知的。
RootKit
資深會員


發表:16
回覆:358
積分:419
註冊:2008-01-02

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-04-02 15:23:33 IP:61.222.xxx.xxx 訂閱
範例:

procedure TForm1.ActiveFormChange(Sender: TObject);
var
ActForm : TForm;
begin
ActForm := TScreen(Sender).ActiveForm;
if ActForm <> Nil then Caption := '(' ActForm.Caption ')';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.OnActiveFormChange := ActiveFormChange;
end;

...........
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-04-07 12:20:40 IP:218.104.xxx.xxx 訂閱
謝謝 RootKit 的回複,
現在的想法是想能不能把這個Function寫到TForm裏面去......


===================引 用 RootKit 文 章===================
範例:

procedure TForm1.ActiveFormChange(Sender: TObject);
var
ActForm : TForm;
begin
ActForm := TScreen(Sender).ActiveForm;
if ActForm <> Nil then Caption := '(' ActForm.Caption ')';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.OnActiveFormChange := ActiveFormChange;
end;

...........
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#11 引用回覆 回覆 發表時間:2008-04-07 14:17:55 IP:218.211.xxx.xxx 訂閱
不知道你是否了解 Rootkit 大大的解法!!

EnumWindows 本來就是個耗時的 API,放在哪裡都一樣....

Screen本身是一個Global變數,用來給開發人員一個處理視窗變化的切入點,以下是 Delphi Help 裡的解說

TScreen introduces properties that keep track of
What forms and data modules have been instantiated by the application.
The active form, and the active control within that form.
The size and resolution of the screen.
The cursors and fonts available for the application to use.
The monitors on which the application forms can appear, including their dimensions.
There is a global variable, Screen, of type TScreen, which is already instantiated for use by GUI applications. Use Screen to obtain information about the current state of the screen in an application.

照您的需求來看只要在激活視窗轉換時去做個紀錄,這個就是Screen物件提供OnActiveFormChange事件的初衷。

===================引 用 crw_web 文 章===================
謝謝 RootKit 的回複,
現在的想法是想能不能把這個Function寫到TForm裏面去...... ==> 看不出有何必要!


===================引 用 RootKit 文 章===================
範例:

procedure TForm1.ActiveFormChange(Sender: TObject);
var
ActForm : TForm;
begin
ActForm := TScreen(Sender).ActiveForm;
if ActForm <> Nil then Caption := '(' ActForm.Caption ')';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.OnActiveFormChange := ActiveFormChange;
end;

...........
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#12 引用回覆 回覆 發表時間:2008-04-09 10:10:32 IP:218.104.xxx.xxx 訂閱
謝謝Malanlk的回複,
我有明白Rootkit大大的意思,我現在可以使用Screen.ActiveForm.Caption來獲取窗體的名稱.
我想的是把這個保存窗體名稱的function寫到哪裏面去,因為之前Rootkit說的解法對我們來說更新程式的工作量會太大,
所以我才想可不可以把這樣的一個function寫到TForm裏面去,這樣的話我們就只要把這個修改後TForm複蓋掉之前的TForm,
再去編譯一下程式就好了.

不知道我這樣說Malanlk,Rootkit大大有明白嗎?

===================引 用 malanlk 文 章===================
不知道你是否了解 Rootkit 大大的解法!!

EnumWindows 本來就是個耗時的 API,放在哪裡都一樣....

Screen本身是一個Global變數,用來給開發人員一個處理視窗變化的切入點,以下是 Delphi Help 裡的解說

TScreen introduces properties that keep track of
What forms and data modules have been instantiated by the application.
The active form, and the active control within that form.
The size and resolution of the screen.
The cursors and fonts available for the application to use.
The monitors on which the application forms can appear, including their dimensions.
There is a global variable, Screen, of type TScreen, which is already instantiated for use by GUI applications. Use Screen to obtain information about the current state of the screen in an application.

照您的需求來看只要在激活視窗轉換時去做個紀錄,這個就是Screen物件提供OnActiveFormChange事件的初衷。

===================引 用 crw_web 文 章===================
謝謝 RootKit 的回複,
現在的想法是想能不能把這個Function寫到TForm裏面去...... ==> 看不出有何必要!


===================引 用 RootKit 文 章===================
範例:

procedure TForm1.ActiveFormChange(Sender: TObject);
var
ActForm : TForm;
begin
ActForm := TScreen(Sender).ActiveForm;
if ActForm <> Nil then Caption := '(' ActForm.Caption ')';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.OnActiveFormChange := ActiveFormChange;
end;

...........
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#13 引用回覆 回覆 發表時間:2008-04-09 18:14:12 IP:218.211.xxx.xxx 訂閱
看來你還是沒完全了解 Rootkit 大大的解法.. 我寫個範例..  範例中 有改寫 Create 建構式,以便在子視窗建立時就有指定的 Caption。 如果你的子視窗原來就有唯一的Caption 那就不必改寫建構式了。

www.newsclipping.url.tw/Test.rar
編輯記錄
malanlk 重新編輯於 2008-04-09 18:15:12, 註解 無‧
malanlk 重新編輯於 2008-04-09 18:28:22, 註解 無‧
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#14 引用回覆 回覆 發表時間:2008-04-10 16:31:51 IP:218.104.xxx.xxx 訂閱
謝謝Malanlk大大提供的Sample,現在明白了.

非常感謝malanlk and Rootkit兩位大大的幫忙和講解!

這Delphi還要好好的學習.

===================引 用 malanlk 文 章===================
看來你還是沒完全了解 Rootkit 大大的解法.. 我寫個範例.. 範例中 有改寫 Create 建構式,以便在子視窗建立時就有指定的 Caption。 如果你的子視窗原來就有唯一的Caption 那就不必改寫建構式了。

www.newsclipping.url.tw/Test.rar
crw_web
一般會員


發表:2
回覆:9
積分:2
註冊:2008-03-13

發送簡訊給我
#15 引用回覆 回覆 發表時間:2008-04-10 16:33:51 IP:218.104.xxx.xxx 訂閱
再次感謝malanlk大大,結案了,我就把分數就給Rootkit大大了喲.
繼續學習了......


===================引 用 malanlk 文 章===================
看來你還是沒完全了解 Rootkit 大大的解法.. 我寫個範例.. 範例中 有改寫 Create 建構式,以便在子視窗建立時就有指定的 Caption。 如果你的子視窗原來就有唯一的Caption 那就不必改寫建構式了。

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