function enumproc(wnd:hwnd; lparam:lparam):BOOL; stdcall; var s,ss:array [1..30] of char; s1:string [30]; begin GetClassName(wnd,@s,20); GetWindowText(wnd,@ss,20); form3.Memo1.Lines.Add(ss); Result:=true; end;
procedure TForm3.Button1Click(Sender: TObject); var wnd,wnd1,wnd2:hwnd; s: array [1..30] of char; begin Memo1.Clear; EnumWindows(@enumproc,0) end;
Выводит очень большой список, а мне нужно только список тех окон, которые открыты. Мне надо найти окно по части имени, вот и решил перебрать все окна
Client, вот для кого я писал, "Как не нужно писать программы"? Я ж там объяснял, что лишние операторы @ - зло, и от них надо избавляться. А ты опять делаешь "это" А почему тебе понадобился @? Потому, что если массив начинается НЕ с нулевого элемента, а с первого, как у тебя, то его уже нельзя привести к PChar/PWideChar автоматически, и тебе приходится "затыкать компилятору рот".
И еще. Зачем в коллбек-функции ты должен обращаться к элементу формы? Не надо этого делать. Ты ж все равно не используешь второй параметр, передаешь туда 0? Так используй... Все просто:
function EnumProc(wnd: HWND; myLParam: LPARAM): BOOL; stdcall; const maxLen = 30; var s, ss: array[0 .. maxLen] of char; begin if IsWindowVisible(wnd) and (GetWindow(Wnd, GW_OWNER) = 0) then begin GetClassName(wnd, s, maxLen); GetWindowText(wnd, ss, maxLen); if ss <> '' then TStrings(myLParam).Add(ss); end; Result := true; end;
procedure TForm3.Button1Click(Sender: TObject); begin Memo1.Clear; EnumWindows(@enumproc, LPARAM(Memo1.Lines)) end;
Помню, что это как поинтер и с ним компилятор успакаивается Это было в примере, если неправильный прототип функции был (вроде enum...). А про массив и PChar даже не знал, как увидел такой пример, так и делал по-нему. Про "чудо-параметр". тип LParam вроде тот же Integer. Но через него передается целый массив строк Это указатель что-ли? по описанию
Цитата
Устанавливает 32-разрядное, определяемое программой значение, которое будет передано в функцию повторного вызова.
LParam вроде тот же Integer. Но через него передается целый массив строк
Стоп, стоп, стоп. Во-первых, не массив строк, а TStrings, то есть дельфийский класс. То есть, указатель на него. Который имеет ту же длину, что и LPARAM. Так что никакой магии - только ловкость рук
Во вторых:
Цитата
А про массив и PChar даже не знал, как увидел такой пример, так и делал по-нему.
А к первоисточнику обратиться не пробовал? Вот описание функции MSDN -> GetClassName. Что видим?
Цитата
int WINAPI GetClassName( __in HWND hWnd, __out LPTSTR lpClassName, // <--- Вот то, что нужно !!! __in int nMaxCount );
LPTSTR видел? А что это такое, расскажешь мне? Напечатай в IDE Delphi и подведи мышь. Мне, например, показывается вот такое сообщение: "LPTSTR - System.PWideChar". Это в 2009-ой, в ранних версиях будет PChar. Опять магия?
Увидел. только мало о чем говорило а зачем столько "типов" LPSTR, LPCSTR, LPTSTR и еще много )) И что значат __out и __in в описании? это же СИ -шное описание, т.е. это зарезервированые слова? или только для информативности?
Цитата
Опять магия?
Определенно магия, только вот какая - черная или нет...
а зачем столько "типов" LPSTR, LPCSTR, LPTSTR и еще много ))
А затем, что они все обозначают разные вещи. По крайней мере в С (что ни говори, а WinAPI изначально пишется под С, так что надо пользоваться теми типами, которые пришли оттуда). Я не просто так всегда говорю: пользуйтесь правильными типами переменных, а не просто подходящими. Сегодня WPARAM - это Integer, завтра положение может поменяться.
В частности, LPSTR - указатель на строку LPCSTR - константный указатель на строку LPTSTR - указатель на массив TCHAR-ов LPCTSTR - константный указатель на массив TCHAR-ов В зависимости от того, Юникодный или нет проект - все 4 типа могут быть различными...
Цитата
И что значат __out и __in в описании? это же СИ -шное описание, т.е. это зарезервированые слова? или только для информативности?
Без понятия, я не пользуюсь Microsoft-овскими компиляторами, а для себя сделал очень просто:
#define __in #define __out
т.е., ассоциировать __in, __out и еще несколько таких параметров с пустотой, чтоб не выдавало ошибок при компиляции, так что теперь у меня "бесплатный" довесок, показывающий, входной это параметр функции, или выходной...
Мне, кстати, проще. Меня Ада приучила к точному описанию типов - никаких отступлений, никаких авто-преобразований. Вот, смотри: 1) попробуем написать CallBack-функцию, используя не нужные типы, а замену: Что видим? Не получилось обмануть компилятор, это не тот прототип, программа компилироваться отказалась.
2) Чуть-чуть поправим программу, сделаем правильный прототип, но вызовем EnumWindows как процедуру, без обработки возвращаемого значения: Что? Опять не то, "Нельзя использовать функцию EnumWindows как процедуру"
3) Ну хорошо, уговорили, пускай она возвращает результат... Вот теперь все в порядке, откомпилировано...