2013-07-12 4 views
1

Я не могу опустить голову вокруг указателей, используя собственную запись, и сделать массив записей, а затем указатель на эту запись, в частности, что я хочу достичь, - сделать запись для каждого окна верхнего уровня дескриптор с указанным именем класса, то есть для каждого окна используется более 1, я использую EnumChildWindow для получения дескрипторов дочерних окон с помощью. Мне хотелось сделать запись каждого из них и передать его в поле со списком с заголовком и сделать запись объект этого элемента, поэтому я могу получить доступ к каждому записанному позже, выбрав его.Указатели Delphi, массивы, ручки

Моя проблема заключается в том, что я обрабатываю указатели, я все время получаю доступ к первому экземпляру, добавляя какие-либо из записей массива.

Перерывы здесь

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. Дэвид уже рассказал вам, что не так с вашим кодом. –

ответ

4

В коде есть много чего не так. Вот неполный список:

  1. Вы не выделяете какое-либо хранилище для arrays.2
  2. Проходите ^PATMyEnumParam к EnumWindows который затем приводится к 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

Дэвид прав - вам нужно жевать небольшие кусочки, чтобы вы не задохнулись ... –