為指定的父視窗枚舉子視窗、按鈕,以控制其操作。

來源:互聯網
上載者:User

為指定的父視窗枚舉子視窗、按鈕

 

  很早就寫過類似spy++和查看密碼視窗的東西,一直想給這個小東西再加點特別的。前段時間對軟體安裝註冊發生了興趣,有些軟體如果你不輸入正確註冊碼,那該死的“下一步”按鈕就一直disable。這次我就讓spy++徹底spy到底,把那個註冊用的按鈕置亮,讓我輕鬆進入“下一步”,呵呵...。
  我的想法是游標移到指定的視窗上後,探測這個視窗上到底有多少按鈕,如果有,就將它們都Enable。在這裡我不想討論怎樣具體實現這個功能,但你要知道的是想得到這些被disable視窗(按鈕)的控制代碼是根本無法通過WindowFromPoint這個API函數得到的,GetWindow也不要妄想了。順手查了下MSDN,看到EnumChildWindows可是個好東西,可以枚舉一個父視窗的所有子視窗:

  1. BOOL EnumChildWindows(
  2.   HWND hWndParent,         // handle to parent window // 父視窗控制代碼
  3.   WNDENUMPROC lpEnumFunc,  // callback function // 回呼函數的地址
  4.   LPARAM lParam            // application-defined value // 你自已定義的參數
  5. );

  就這麼簡單,讓我們再定義一個回呼函數,像下面這樣:

  1. BOOL CALLBACK EnumChildProc(
  2.   HWND hwnd,      // handle to child window
  3.   LPARAM lParam   // application-defined value
  4. );

  注意:這個回呼函數要麼是類的靜態函數,要麼就是一個全域的函數。
--------------------------------
  在調用EnumChildWindows 這個函數時,直到調用到最個一個子視窗被枚舉或回呼函數返回一個false,否則將一直枚舉下去。有了上面的知識,我想你應該知道怎麼做了。有了回呼函數的概念及上面的例子,我們可以繼續了。其實想要找到一個標題已知的視窗控制代碼,用一個API函數就可以了:FindWindow.其函數原形是:

  1. function FindWindow(lpClassName, lpWindowName: PChar): HWND; stdcall;
  2. lpClassName:視窗類別名.如果只知道標題,可以為空白.視窗類別名可以用很多工具獲得.如winsignt32.
    lpWindowName:視窗標題.

調用方式舉例:

  1. var wndhwnd:HWND;
  2. wndhwnd:=FindWindow(nil,'某視窗標題');
  3. if wndhwnd<>0 then  file://找到此視窗控制代碼.
  4. begin
  5.   xxxxx
  6. end
  7. else begin
  8.   MessageBox(self.handle,'沒找到該視窗控制代碼','提示',0);
  9. end;

  有了這個視窗控制代碼,就離我們的初始目的不遠了:控制其他表單上的視窗控制項.同樣,首先要得到其他表單上視窗控制項的控制代碼.我們用這個API函數:EnumChildWindows.其函數原形是:

  1. function EnumChildWindows(hWndParent: HWND; 
  2.     lpEnumFunc: TFNWndEnumProc;
  3.     lParam: LPARAM): BOOL; stdcall;

  這個函數和EnumWindow函數很有些想象.其作用也很相似.它的功能就是列舉視窗控制代碼為hWndParent的表單上所有的視窗控制項的控制代碼.同樣也是以回呼函數參數的形式給出的. 我們再舉一個實際的例子,來說明這個函數的用法.程式的功能是讓使用者輸入一個視窗標題,然後調用FindWindow函數找到此視窗控制代碼.通過這個控制代碼,我們在一個Memo裡顯示該視窗上所有的視窗控制項.同樣先編寫回呼函數.

  1. function  EnumChildWndProc(AhWnd:LongInt;
  2.   AlParam:lParam):boolean;stdcall;
  3. var
  4.   WndClassName: array[0..254] of Char;
  5.   WndCaption: array[0..254] of Char;
  6. begin
  7.   GetClassName(AhWnd,wndClassName,254);
  8.   GetWindowText(aHwnd,WndCaption,254);
  9.   with form1.memo1 do
  10.   begin
  11.     lines.add( string(wndClassName));
  12.     lines.add( string(wndCaption));
  13.     lines.add('-------');
  14.   end;
  15.   result:=true;
  16. end;

然後在一事件裡調用EnumChildWindows函數.

  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   hWnd:LongInt;
  4. begin
  5.   memo1.Lines.Clear;
  6.   Memo1.Lines.Add(Edit1.Text+' 有如下控制項類名稱');
  7.   hWnd:=FindWindow(nil,pchar(Edit1.Text));
  8.   if hWnd<>0 then
  9.   begin
  10.     EnumChildWindows(hWnd,@EnumChildWndProc,0);
  11.   end
  12.   else  MessageBox(self.handle,'沒找到該視窗控制代碼','提示',0);
  13. end;

程式清單如下:

  1. unit Unit1;
  2. interface
  3. uses
  4.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5.   Dialogs, StdCtrls;
  6. type
  7.   TForm1 = class(TForm)
  8.     Memo1: TMemo;  //用來顯示找到的控制項
  9.     Label1: TLabel; 
  10.     Edit1: TEdit;  //輸入標題.
  11.     Button1: TButton;  
  12.     procedure Button1Click(Sender: TObject);
  13.   private
  14.     { Private declarations }
  15.   public
  16.     { Public declarations }
  17.   end;
  18. var
  19.   Form1: TForm1;
  20.   function  EnumChildWndProc(AhWnd:LongInt;
  21.     AlParam:lParam):boolean;stdcall;
  22. implementation
  23. {$R *.dfm}
  24. function  EnumChildWndProc(AhWnd:LongInt;
  25.   AlParam:lParam):boolean;stdcall;
  26. var
  27.   WndClassName: array[0..254] of Char;
  28.   WndCaption: array[0..254] of Char;
  29. begin
  30.   GetClassName(AhWnd,wndClassName,254);
  31.   GetWindowText(aHwnd,WndCaption,254);
  32.   with form1.memo1 do
  33.   begin
  34.     lines.add( string(wndClassName));
  35.     lines.add( string(wndCaption));
  36.     lines.add('-------');
  37.   end;
  38.   result:=true;
  39. end;
  40. procedure TForm1.Button1Click(Sender: TObject);
  41. var
  42.   hWnd:LongInt;
  43. begin
  44.   memo1.Lines.Clear;
  45.   Memo1.Lines.Add(Edit1.Text+' 有如下控制項類名稱');
  46.   hWnd:=FindWindow(nil,pchar(Edit1.Text));
  47.   if hWnd<>0 then
  48.   begin
  49.     EnumChildWindows(hWnd,@EnumChildWndProc,0);
  50.   end
  51.   else  MessageBox(self.handle,'沒找到該視窗控制代碼','提示',0);
  52. end;
  53. end.

  有了控制項控制代碼,我們當然就可以隨心所欲了.比如:

  1. SendMessage(hWnd,WM_SETTEXT,0,LongInt(Pchar('sdafdsf')));

  就可以給控制項發送文本.其他還可以發送不同的訊息可以做很多事情.但是,有很大一個問題:假設一個表單上有很多相同的控制項,並且根本沒辦法區分他們,即使我們能找到所有的控制項控制代碼,我們又不能區分到底哪個是我們想要的,同樣是干著急.我想了很長時間,後來在大富翁裡找到了答案,只要用到一個小技巧,就可以解決了.

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=588250

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.