2013-07-12 67 views
1

我不能讓我的頭在使用自定義記錄的指針和製作記錄數組然後指向該記錄,特別是我想要實現的是爲每個頂級窗口創建一個記錄處理給定的類名,這意味着有超過1,爲每個窗口我使用EnumChildWindow來獲取處理與兒童窗口與英寸我想記錄每個這些並將其傳遞給與標題的組合框,並使記錄該項目的對象,所以我可以通過選擇它來訪問每個記錄。德爾菲指針,數組,手柄

我的問題是我對指針的處理,我不斷收到訪問被拒絕的第一個實例添加任何一個數組記錄。這裏

休息

Param[Form1.iEnumWin].MainHwnd:= aHwnd; 

這裏是我使用,使人們可以得到什麼,我試圖做一個更好的理解完整的代碼。

implementation 

{$R *.dfm} 
type 
    TMyEnumParam = record 
    sTitle: String; 
    MainHwnd: Hwnd; 
    InTxtHwnd: Hwnd; 
    OutTxtHwnd: Hwnd; 
    NickListHwnd: Hwnd; 
end; 
PMyEnumParam = ^TMyEnumParam; 

type 
ATMyEnumParam = Array[0..9] of PMyEnumParam; 
PATMyEnumParam = ^ATMyEnumParam; 

{ Get the window Title based on Hwnd } 
function GetWindowTitle(HWND: HWND): string; 
begin 
    SetLength(Result, 255); 
    SetLength(Result, GetWindowText(HWND, PChar(Result), 255)); 
end; 

{ Get the Classname based on Hwnd } 
function GetWindowClass(HWND: HWND): string; 
begin 
    SetLength(Result, 255); 
    SetLength(Result, GetClassName(HWND, PChar(Result), 255)); 
end; 

{ EnumChildWidows Callback Add to our records } 
Function EnumChildProc(aHwnd: Hwnd; Param: PMyEnumParam): Boolean; stdcall; 
begin 
    if ((GetDlgCtrlID(aHwnd) = 202) and (isWindowVisible(aHwnd) = True)) then 
     Param.InTxtHwnd:= aHwnd; 

    if ((GetDlgCtrlID(aHwnd) = 203) and (isWindowVisible(aHwnd) = True)) then 
     Param.OutTxtHwnd:= aHwnd; 

    if ((GetDlgCtrlID(aHwnd) = 1789) and (isWindowVisible(aHwnd) = True)) then 
     Param.NickListHwnd:= aHwnd; 

     Result:= True; 
end; 

{ EnumWindow fill our array of records for each window } 
function EnumWindowsProc(aHwnd: HWND; Param: PATMyEnumParam): BOOL; stdcall; 
begin 
    Result := True; 
    if GetWindowClass(aHwnd) = 'DlgGroupChat Window Class' then 
    begin 
    Param[Form1.iEnumWin].MainHwnd:= aHwnd; 
    Param[Form1.iEnumWin].sTitle:= GetWindowTitle(aHwnd); 
    EnumChildWindows(aHwnd, @EnumChildProc, LParam(@Param[Form1.iEnumWin])); 
    Form1.cbbRooms.AddItem(Param[Form1.iEnumWin].sTitle, TObject(Param[form1.iEnumWin])); 
    inc(Form1.iEnumWin); 
    end; 
end; 

{ On change display room Title for each item } 
procedure TForm1.cbbRoomsChange(Sender: TObject); 
var 
    i: Integer; 
    aHwnd: PMyEnumParam; 
begin 
    i := cbbRooms.ItemIndex; 
    if cbbRooms.ItemIndex <> -1 then 
    begin 
    aHwnd:= PMyEnumParam(cbbRooms.Items.Objects[i]); 
    if aHwnd.MainHwnd > 0 then 
    begin 
    ShowMessage(aHwnd.sTitle); 
    end; 
    end; 

end; 

{ Call EnumWindows and fill our array records } 
procedure TForm1.FormCreate(Sender: TObject); 
var 
arInfo: PATMyEnumParam; 
begin 
    iEnumWin:= 0; 
    EnumWindows(@EnumWindowsProc, LParam(@arInfo)); 
end; 

請如果有人可以指出(沒有雙關語意)我在正確的方向我將不勝感激。

+0

一個無恥的插件,但如果你迷失了指針,你可能想閱讀http://rvelthuis.de/articles/articles-pointers.html。 David已經告訴過你代碼有什麼問題。 –

回答

4

代碼有很多錯誤。這裏有一個非詳盡列表:

  1. 你不分配任何存儲空間來保存arrays.2
  2. 您傳遞^PATMyEnumParamEnumWindows然後您可以轉換爲PATMyEnumParam回調。
  3. 你的數組是固定長度的,你不會嘗試處理對數組的超出邊界的訪問。

但是你最大的問題是你的代碼試圖在你走之前運行。它具有完整的複雜性和所有你需要的功能。然而,您仍然無法成功撥打EnumWindows

我最大的一點建議不在細節中,而是解決問題的一般性。首先編寫一段簡單的代碼。明白它。然後加強它。

因此,在這種精神,這裏是如何撥打電話到EnumerateWindows

program EnumWindowsDemo_17620346; 

{$APPTYPE CONSOLE} 

uses 
    System.SysUtils, Winapi.Windows, Generics.Collections; 

type 
    TWindowInfo = record 
    Handle: HWND; 
    // expand with more fields in due course 
    end; 

function EnumWindowProc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; 
var 
    WindowList: TList<TWindowInfo>; 
    WindowInfo: TWindowInfo; 
begin 
    WindowList := TList<TWindowInfo>(lParam); 
    WindowInfo.Handle := hwnd; 
    WindowList.Add(WindowInfo); 
    Result := True; 
end; 

procedure Main; 
var 
    WindowList: TList<TWindowInfo>; 
    WindowInfo: TWindowInfo; 
begin 
    WindowList := TList<TWindowInfo>.Create; 
    try 
    EnumWindows(@EnumWindowProc, LPARAM(WindowList)); 
    for WindowInfo in WindowList do 
     Writeln(WindowInfo.Handle); 
    finally 
    WindowList.Free; 
    end; 
end; 

begin 
    Main; 
    Readln; 
end. 

從這裏開始,你可以擴展這個概念,因爲所有的棘手的部分已經照顧。具體來說就是指針,鑄造和內存管理。

+0

謝謝我很欣賞它,我知道我想要做什麼,但正如你所說的,指針和內存管理是我的故事,我通常嘗試並遠離這些,並使用Delphi以這種方式處理它,一個只有愛好者的程序員我在處理內存時仍有很多東西需要學習,我在處理EnumWindow和EnumChildWindows之前沒有問題,也沒有傳遞參數供它使用,所以不需要真正的內存管理。再次感謝,我將在此工作,現在看到你如何使用TList分配一個記錄使得它更加有趣。 – Departure

+0

TList 的好處是你不必擔心內存分配問題 –

+1

大衛是對的 - 你需要咀嚼小塊,所以你不要嗆... –