Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Вниз

Непонятна работа GetWindowText   Найти похожие ветки 

 
Piter ©   (2004-11-05 22:39) [0]

Возьмем вот такой код:

procedure TForm1.Timer1Timer(Sender: TObject);
var
 FW: HWND;
 s: string;
 i: integer;
begin
 FW := GetForegroundWindow ;
 i := GetWindowTextLength(FW);
 SetLength(s, i);
 i := GetWindowText(FW, PChar(s), i);
 Edit1.text := s;
end;

И как-то странно получается. Для всех окон, которые я пробовал, записывается заголовок за исключением последнего символа. А последним символом в S идет #0. С какого перепуга он туда пишется?

Ну допустим я это еще могу понять, просто надо SetLength делать на 1 больще.
Но! Если таким образом узнавать заголовок собственного окна - то код работает как я и ожидал - то есть, возвращает полностью заголовок.

Если не понятно - приведу пример. Допустим, в фокусе сейчас окно редактора кода, заголовок "unit1.pas". На первом присвоении I получается 9, что верно. На втором присвоении I получается 8! Девятым символом в S записывается #0. Это можно объяснить.

Но если в фокусе форма моего приложения, которая имеет заголовок "Form1", то на первом присвоении I равно 5, что также верно. А на втором присвоении I получается тоже 5! При этом никакой записи #0 в последний символ S не происходит!

Замечу, что код у меня именно такой, я его скопировал из окна редактора кода.

После серии экспериментов я пришел только к одному мнению - если функция возвращает заголовок окна своего потока, то она работает "правильно" - то есть, какое количество символов ты хочешь скопировать - такое она и копирует. Если же окно относится к другому потоку (или процессу - не проверял), то она копирует иначе.

Сижу и думаю - меня глючит что ли? Или это такой глюк в windows? По идее, вероятнее, что глючит меня, так как баг то вроде простой и его давно бы заметили, а я ничего такого не слышал. С другой стороны, код тоже элементарный, все на ладони, ходил с отладчиком - никаких погрешностей в своем коде не обнаружил.

Кто что скажет?


 
Игорь Шевченко ©   (2004-11-05 23:06) [1]

GetWindowTextLength

"If the function succeeds, the return value is the length, in characters, of the text. Under certain conditions, this value may actually be greater than the length of the text".
"If the target window is owned by the current process, GetWindowTextLength causes a WM_GETTEXTLENGTH message to be sent to the specified window or control."

"Under certain conditions, the GetWindowTextLength function may return a value that is larger than the actual length of the text. This occurs with certain mixtures of ANSI and Unicode, and is due to the system allowing for the possible existence of double-byte character set (DBCS) characters within the text. The return value, however, will always be at least as large as the actual length of the text; you can thus always use it to guide buffer allocation."

"To obtain the exact length of the text, use the WM_GETTEXT, LB_GETTEXT, or CB_GETLBTEXT messages, or the GetWindowText function."

GetWindowText
"If the window text string is as long or longer than the buffer, the string is truncated and terminated with a NULL character. "

"nMaxCount
[in] Specifies the maximum number of characters to copy to the buffer, including the NULL character. If the text exceeds this limit, it is truncated. "


 
Piter ©   (2004-11-05 23:51) [2]

Игорь Шевченко ©   (05.11.04 23:06) [1]
"If the target window is owned by the current process, GetWindowTextLength causes a WM_GETTEXTLENGTH message to be sent to the specified window or control."


тут по-моему неграмотно написано. У меня хелп от D7 и там вот что написано:

"If the function succeeds, the return value is the length, in characters, of the text. Under certain conditions, this value may actually be greater than the length of the text. For more information, see the following Remarks section."

Соответственно Remarks:

"This function causes a WM_GETTEXTLENGTH message to be sent to the specified window or control."

Ну и далее там идет ваш текст "Under certain conditions..."

Никаких current process.

Игорь Шевченко ©   (05.11.04 23:06) [1]
"nMaxCount
[in] Specifies the maximum number of characters to copy to the buffer, including the NULL character. If the text exceeds this limit, it is truncated. "


хм, у меня опять же по другому:

"nMaxCount

Specifies the maximum number of characters to copy to the buffer. If the text exceeds this limit, it is truncated"

Ну допустим эту фразу "including the NULL character" я предполагал в первом своем посте. Допустим, так (хоть у меня в хелпе этого и не написано). Но почему тогда код со своим окном отрабатывает корректно?

Из ваших пояснений я не понял ответа на свой вопрос...


 
Игорь Шевченко ©   (2004-11-06 00:03) [3]

Piter ©   (05.11.04 23:51) [2]


> тут по-моему неграмотно написано


Да, Microsoft отличается изрядной неграмотностью при составлении документации, это я тоже отметил.

Однако даже неграмотное описание, на мой взгляд, соответствует описанной тобой ситуации.


 
_silver ©   (2004-11-06 00:31) [4]

Piter ©   (05.11.04 22:39)

А так???

function GetWndText(WndH : HWND) : string;
var
 s : string;
 Len : integer;
begin
 Len := GetWindowTextLength(WndH)+1;
 if Len > 1 then
   begin
     SetLength(s, Len);
     GetWindowText(WndH, @s[1], Len);
     Result := s;
   end
end;


 
Игорь Шевченко ©   (2004-11-06 00:46) [5]

Кстати, интересно - функции GetWindowText и GetWindowTextLength всегда посылают окну сообщения WM_GETTEXTLENGTH и WM_GETTEXT, в случае окна своего процесса функции посылают сообщение через DefWindowProc, а в случае чужого через SendMessage.


> Если таким образом узнавать заголовок собственного окна
> - то код работает как я и ожидал - то есть, возвращает полностью
> заголовок.


Давай ты примерчик напишешь, который можно скопировать в среду, запустить и убедиться, что поведение именно такое, как ты описываешь.


 
_silver ©   (2004-11-06 00:55) [6]

Игорь Шевченко ©   (06.11.04 0:46) [5]
Прошу всётаки обратить внимание на

> _silver ©   (06.11.04 0:31) [4][Ответить]

и сравнить результат с

> Piter ©   (05.11.04 22:39) [Ответить]


 
Piter ©   (2004-11-06 01:01) [7]

Игорь Шевченко ©   (06.11.04 0:03) [3]
Да, Microsoft отличается изрядной неграмотностью при составлении документации, это я тоже отметил


минуту думал - это вы иронизировали или серьезно сказали? Так и не пришел к заключению :)

Игорь Шевченко ©   (06.11.04 0:03) [3]
Однако даже неграмотное описание, на мой взгляд, соответствует описанной тобой ситуации


на мой взгляд не соответствует. Объясните чайнику:

> Но почему тогда код со своим окном отрабатывает
> корректно?


Я вообще не понимаю почему вы привели описание
GetWindowTextLength
эта функция то как раз абсолютно корректно отрабатывает. Проблема в
GetWindowText
перефразирую свой вопрос в третий раз (может, вам лень читать первый большой пост?) - почему для чужих окон ДЕЙСТВУЕТ приписка "including the NULL character", а для своего окна нет.

Кстати, вы из MSDN цитировали?

_silver ©   (06.11.04 0:31) [4]
А так???


а что так? Ну ясен пень работает, но это не ответ на вопрос.
Причем работает из-за +1 естественно, а не из-за @s[1], ибо это тоже самое, что и PChar(s)


 
Игорь Шевченко ©   (2004-11-06 01:08) [8]

Piter ©   (06.11.04 01:01) [7]


> минуту думал - это вы иронизировали или серьезно сказали?
> Так и не пришел к заключению :)


Иронизировал. Так как мои цитаты приведены из последней MSDN.
Хотя, ошибки есть и там, но все же не настолько по сравнению с Help из D7.

Кстати, в какой системе проявляется такое поведение ?


 
Игорь Шевченко ©   (2004-11-06 01:12) [9]


> procedure TForm1.Timer1Timer(Sender: TObject);
> var
>  FW: HWND;
>  s: string;
>  i: integer;
> begin
>  FW := GetForegroundWindow ;
>  i := GetWindowTextLength(FW);
>  SetLength(s, i);
>  i := GetWindowText(FW, PChar(s), i);
>  Edit1.text := s;
> end;


unit main;

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 S: string;
 I: Integer;
begin
 I := GetWindowTextLength(Button1.Handle);
 SetLength(S, I);
 GetWindowText(Button1.Handle, PChar(S), I);
 ShowMessage(S);
end;

end.


ShowMessage показывает "Button"

Система - Win2k


 
_silver ©   (2004-11-06 01:14) [10]

Piter ©   (06.11.04 1:01) [7]
Признаю свою ошибку...
Проверил, действительно не понятно...
Без +1 заголовки окон своего приложения возвращает правильно, окон других приложений на один символ меньше.
?


 
Piter ©   (2004-11-06 01:22) [11]

Игорь Шевченко ©   (06.11.04 0:46) [5]
Давай ты примерчик напишешь, который можно скопировать в среду, запустить и убедиться, что поведение именно такое, как ты описываешь


да вообще-то примерчик в моей первом посту. Ну можно еще более наглядно:

кидайте таймер на форму, интервал - 1 сек:

procedure TForm1.Timer1Timer(Sender: TObject);
var
 FW: HWND;
 s: string;
 i: integer;
begin
 FW := GetForegroundWindow ;
 i := GetWindowTextLength(FW);
 SetLength(s, i);
 GetWindowText(FW, PChar(s), i);
 if Pos(#0, s)>0 then
   beep;
end;


как видно, код прямо не привязан к тому, свое или не свое окно. Однако же, если в фокусе будет свое окно (окно вашего приложения) - пиканья (beep) вы не услышите. Но как только переключитесь на окно чужого приложения - услышите пиканье.

Знаете, меня даже порадовало - такой недокументированный способ определения - свое или не свое окно :)

P.S. Windows 2000 rus + SP2 + D7


 
Piter ©   (2004-11-06 01:32) [12]

Игорь Шевченко ©   (06.11.04 1:12) [9]
ShowMessage показывает "Button"


аналогично. Ситуация становится все интернеснее :)
Получается, исключительное поведение для СВОИХ окон верхнего уровня?

Теперь интересно выяснить - под своими понимается своего процесса или своего потока? :)

Но сейчас я спать, глаза слипаются...


 
Piter ©   (2004-11-06 01:32) [13]

Игорь Шевченко ©   (06.11.04 1:08) [8]
приведены из последней MSDN


апрельской? Или какая новая вышла?
Или вы с сайта?


 
Игорь Шевченко ©   (2004-11-06 01:33) [14]

Piter ©   (06.11.04 01:22) [11]

Пост [9] - что я делаю не так ? Когда я заменяю Button1.Handle на просто Handle, ShowMessage честно выводит "Form", то есть, все работает в соответствии с описанием.


 
Игорь Шевченко ©   (2004-11-06 01:34) [15]

Piter ©   (06.11.04 01:32) [13]

С сайта


 
SPeller ©   (2004-11-06 06:12) [16]

Я думаю что это проделки VCL. В KOL код [11] пикает вне зависимости от того, свое окно или нет.


 
Игорь Шевченко ©   (2004-11-06 11:04) [17]

SPeller ©   (06.11.04 06:12) [16]

А где ты увидел VCL в данном случае ? Саша, думать, оно конечно, неплохо, но анализировать код - еще лучше.


 
Verg ©   (2004-11-06 11:40) [18]

Specifies the maximum number of characters to copy to the buffer, including the NULL character. If the text exceeds this limit, it is truncated.

Вот и вопрос - как оно truncated. Можно так, что просто обсечь, забив на 0, а можно так, чтобы 0 -терминатор был таки, т.е. укоротив значущую часть строки. Это тебе в Delphi string-ах в сущьности пофигу есть этот 0-терминатор или нет.
Я считаю, что при передаче неверного значения парамера, ф-ция вольна поступать как ей вздумается, не нарушая общих принципов защиты. К чему эти выяснялки - почиму на неверно заданный параметр ф-ция ведет себя неоднозначно. Передавай все правильно, и будет тебе счастье.


 
Piter ©   (2004-11-06 13:01) [19]

Игорь Шевченко ©   (06.11.04 1:33) [14]
Пост [9] - что я делаю не так ? Когда я заменяю Button1.Handle на просто Handle, ShowMessage честно выводит "Form",


Игорь, вы в этом уверены? У меня выводит именно "Form1"

SPeller ©   (06.11.04 6:12) [16]
В KOL код [11] пикает вне зависимости от того, свое окно или нет


угу, судя по всему, у Игоря тоже самое. Какая система у тебя (включая сервис паки)?

Игорь, и какая система у вас (включая сервис паки)?

У меня W2k SP2.

Verg ©   (06.11.04 11:40) [18]
including the NULL character


а в справке по D7 этого нету :(

Я считаю, что при передаче неверного значения парамера, ф-ция вольна поступать как ей вздумается

Verg ©   (06.11.04 11:40) [18]
Вот и вопрос - как оно truncated. Можно так, что просто обсечь, забив на 0, а можно так, чтобы 0 -терминатор был таки, т.е. укоротив значущую часть строки


да, ты верно сформулировал. В функцию передается число символов на 1 меньше, чем нужно передать, чтобы получить полный заголовок. В документации написано, что в этом случае произойдет усечение строки. Но вот факт в том, что в случае своих окон он усекает одним способом, а в случае чужих окон другим. Интересно - почему?

При этом сама MS, видимо, все таки считает это за ошибку, потому как явно исправила ее. Этот код:

procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
I: Integer;
begin
I := GetWindowTextLength(Button1.Handle);
SetLength(S, I);
GetWindowText(Handle, PChar(S), I);
ShowMessage(S);
end;


выдает мне "Form1". А Игорю выдается "Form".
У меня SP2, а я думаю у Игоря SP3 или SP4. Интересно, еще на WinXP проверить и win9x.

Так что данное несоответствие между своими и чужими окнами проявляется на некоторых системах (старых достаточно) со своими окнами верхнего уровня. Вон оно как (если в коде заменить Handle на Button1.Handle - то все работает как надо).

P.S. Провел таки эксперименты - на Windows ME и Windows XP работает как надо, то есть как в MSDN сказано. Пока неправильное поведение обнаружил только на Windows 2000 SP2 на своих окнах верхнего уровня.

P.S.S. А вообще, не понимаю - нафига GetWindowText пишет нулевой символ? Кому это надо... неудобно использовать, получается два нулевых символа подряд...


 
Verg ©   (2004-11-06 13:08) [20]


>  вообще, не понимаю - нафига GetWindowText пишет нулевой
> символ?


Здрасте. GetWindowText - ф-ция API.
С API ф-циями работают программируя не только на Delphi :)


 
Verg ©   (2004-11-06 13:13) [21]


> Но вот факт в том, что в случае своих окон он усекает одним
> способом, а в случае чужих окон другим. Интересно - почему?


Наверно этот механизм реализован в двух разных кусках кода для двух этих случаев. Может даже писанных разными людьми. Один так понял truncate, другой - иначе. :) Делов-то...


 
Piter ©   (2004-11-06 13:19) [22]

Verg ©   (06.11.04 13:08) [20]

Знаю :)

Verg ©   (06.11.04 13:08) [20]

тиы вот скажи лучше - у тебя "глюк" проявляется на своих окнах верхнего уровня? И какая у тебя система?


 
Piter ©   (2004-11-06 13:19) [23]

Verg ©   (06.11.04 13:13) [21]
Наверно этот механизм реализован в двух разных кусках кода для двух этих случаев


а зачем для своих окон делать один код, а для чужих - другой?


 
Verg ©   (2004-11-06 13:26) [24]

С точки зрения программирования на C - у меня truncate делается "корректно", т.е. усечением заначащей части строки - чтобы терм. 0 был в любом случае.

Windows 2000 Pro RUS SP4


 
Verg ©   (2004-11-06 13:32) [25]


> а зачем для своих окон делать один код, а для чужих - другой?


Странный вопрос.
Ответ: Так получилось. Может быть случайно, а может и нет - в каждом большом проекте можно найти нелогичности, не приводящие, тем не менее к неработоспособности. По мере "подчистки" обычно накие нелогичности устраняются и вклюяаются в сервиспаки, апдейты и т.д.


 
GuAV ©   (2004-11-06 13:36) [26]

procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
I: Integer;
begin
I := GetWindowTextLength(Button1.Handle);
SetLength(S, I);
GetWindowText(Handle, PChar(S), I + SizeOf(#0));
ShowMessage(S);
end


 
Piter ©   (2004-11-06 15:47) [27]

Piter ©   (06.11.04 13:19) [23]
Windows 2000 Pro RUS SP4


угу. Понятно. Где-то на уровне SP3, SP4 ошибку исправили, видимо. В SP2 она присутствует.
В WindowsME и WinXP (без сервис паков) все ок.


 
VID ©   (2004-11-06 17:41) [28]

Piter, проверь на машине с Win2k.SP<=2 этот код
Function _GetWindowText(HWND:THandle):String;
var
 WindowText : PChar;
 TextSize : DWORD;
begin
Result := ""; WindowText := #0;
TextSize := GetWindowTextLength(HWND)+1;
try
 GetMem(WindowText, TextSize);
 GetWindowText(HWND, WindowText, TextSize);
 Result:= StrPas(WindowText);
finally
 FreeMem(WindowText);
end;
end;

самому интересно будет ли описанный глюк или нет.


 
Игорь Шевченко ©   (2004-11-06 17:42) [29]

Piter ©   (06.11.04 13:01) [19]

Win2k Pro SP3(4) Rus


 
Игорь Шевченко ©   (2004-11-06 17:48) [30]

Кроме того, я уже писал в чем отличие работы этих функций для окно своего и чужого процессов.


 
Piter ©   (2004-11-06 18:31) [31]

VID ©   (06.11.04 17:41) [28]
самому интересно будет ли описанный глюк или нет.


даже проверять не хочу:

TextSize := GetWindowTextLength(HWND)+1

ты где вообще был то? Какие посты читал?

Игорь Шевченко ©   (06.11.04 17:42) [29]
Win2k Pro SP3(4) Rus


ясно. Значит, вероятно этот глюк в Win2000-SP2.
А исправили в SP3


 
Игорь Шевченко ©   (2004-11-06 18:57) [32]

Piter ©   (06.11.04 18:31) [31]

Сдается мне, что глюка быть не должно. В противном случае о нем бы было известно, начиная с NT4, где, собственно говоря, и изменился механизм работы с окнами. Поищи в MSDN в Knowledge Base, если там ничего нету, то глюк конкретно у тебя, IMHO.


 
Piter ©   (2004-11-06 19:36) [33]

Игорь Шевченко ©   (06.11.04 18:57) [32]
Поищи в MSDN в Knowledge Base, если там ничего нету, то глюк конкретно у тебя, IMHO.


сомневаюсь. Что, у меня win 2000 специальная что ли?
Вот пожалуйста:


_silver ©   (06.11.04 1:14) [10]
>Признаю свою ошибку...
>Проверил, действительно не понятно...
> Без +1 заголовки окон своего приложения возвращает
> правильно, окон других приложений на один символ меньше


Так что не только у меня. Просто найдите windows 2000 SP2 или меньше. И увидете.
Я ведь ничего не мудрил - я и ваш код использовал, у меня показывается "Form1".


 
марсианин ©   (2004-11-06 20:36) [34]

у меня в WinXP HE без сервис-паков - такая же фигня

но это только для окна Form1, если любое другое (в т.ч. и свои контролы), то все ок


 
Игорь Шевченко ©   (2004-11-06 20:53) [35]

Piter ©   (06.11.04 19:36) [33]

Из GetWindowText:
"nMaxCount
[in] Specifies the maximum number of characters to copy to the buffer, including the NULL character. If the text exceeds this limit, it is truncated. "

Из GetWindowTextLength
"If the function succeeds, the return value is the length, in characters, of the text".


procedure TForm1.Button1Click(Sender: TObject);
var
 S: string;
 I: Integer;
begin
 I := GetWindowTextLength(Handle);
 SetLength(S, I);
 GetWindowText(Handle, PChar(S), I);
 ShowMessage(S);
end;


Вот мой код работает точно по приведенному описанию. Из чего я делаю вывод, что дело не в Windows.
Я тебе искренне советую посмотреть свой код отладчиком, можно даже в CPU Window залезть, чтобы понять, в чем причина.


 
Verg ©   (2004-11-06 21:04) [36]

ой, парни, ну в конце концов, я уже говорил - не перекладывайте вы "с больной головы на здоровую" - указыайте правильно параметры при вызовах API ф-ций, и будет все зашибись. Какой еще "глюк"? :) Не смешите мои тапочки. :))
Piter - пытался тебе объянить эту простую мысль, нет, тебя клинануло на "глюк Windows", стал же таки выяснять, по сути, "какая винда из сервис паков лучче отрабатывает глючные параметры".

Разбираться, что если свернуть башку водопроводному крану - почему в одной квартире вода потекла налево, а в другой направо? Бред.


 
Игорь Шевченко ©   (2004-11-06 21:39) [37]

Verg ©   (06.11.04 21:04) [36]

Зачем разный код при обращении к окнам своего и чужого процесса:
Для окна своего процесса можно выполнить обработку сообщения WM_GETTEXT посредством вызова DefWindowProc, не переходя в режим ядра, следовательно, быстрее. Для окон чужого процесса этого сделать нельзя, так как код должен выполнится в адресном пространстве чужого процесса и передать данные в процесс, который вызывает GetWindowText, для этого надо построить промежуточный объект-секцию для буфера строки, и т.д. Поэтому для окон чужого процесса посылается сообщение WM_GETTEXT вызовом функции SendMessage.

Кстати, интересующиеся могут поставить эксперимент - создать окно с оконном процедурой, обрабатывающей WM_GETTEXT и возвращающей какую-нибудь лабуду.


 
марсианин ©   (2004-11-06 21:40) [38]

2 [35] Игорь Шевченко ©   (06.11.04 20:53)

I := GetWindowTextLength(Handle);
SetLength(S, I);
GetWindowText(Handle, PChar(S), I);

почему не I := GetWindowTextLength(Handle) + 1;???

в сях strlen("my text") == 7 - количество символов
но  размер буфера, нужного для хранения этой строки, =  (7+1)*sizeof(char)
потому что еще "\0"  сзади

если так написать глюка не будет. нигде.

2[36] Verg ©   (06.11.04 21:04)
насколько я понял проблема в том, что когда GetWindowText обрубает текст в некоторых случаях "\0" не проставляется.. это наблюдается напр для Form1
д.б. Form+\0 при размере буфера 5
т.е все-таки глюк :)


 
Игорь Шевченко ©   (2004-11-06 22:05) [39]

марсианин ©   (06.11.04 21:40) [38]


> почему не I := GetWindowTextLength(Handle) + 1;???


Потому что так было в изначальном коде. Моей целью было продемонстрировать, что для окон своего процесса буфер обрезается точно также.

Я бы делал вообще по-другому, если бы мне нужно было получить текст из окна.


 
Piter ©   (2004-11-06 22:12) [40]

Игорь Шевченко ©   (06.11.04 20:53) [35]
Вот мой код работает точно по приведенному описанию. Из чего я делаю вывод, что дело не в Windows


ВСТАВИЛ ИМЕННО ЭТОТ КОД - У МЕНЯ ВЫДАЕТ "FORM1".
Из чего я делаю вывод, что глюк не во мне. Все это я проделываю в ЧИСТОМ проекте. Могу прислать проект на мыло.

марсианин ©   (06.11.04 20:36) [34]
у меня в WinXP HE без сервис-паков - такая же фигня


еще интереснее. Я проверял на WinXP без сервис паков - все ок. А у тебя какой сервис пак?
Получается, на W2k SP2 глюк есть, на SP3/SP4 исправили. На WinXP глюка нету, но он есть на WinXP SP1(2?)?

Игорь Шевченко ©   (06.11.04 20:53) [35]
Я тебе искренне советую посмотреть свой код отладчиком, можно даже в CPU Window залезть, чтобы понять, в чем причина


ну черт побери. ЧИСТЫЙ ПРОЕКТ. ВАШ КОД!
Почему вы не можете поверить? :)
Тем более, я не один это говорю.

Verg ©   (06.11.04 21:04) [36]
ой, парни, ну в конце концов, я уже говорил - не перекладывайте вы "с больной головы на здоровую" - указыайте правильно параметры при вызовах API ф-ций, и будет все зашибись


между прочим, я указываю ПРАВИЛЬНЫЕ ПАРАМЕТРЫ. Чем мои параметры неправильны? Я волен указать любое число. В документации по этому поводу ничего не сказано.

Verg ©   (06.11.04 21:04) [36]
Какой еще "глюк"? :) Не смешите мои тапочки. :))


Какой глюк? А ты как будто не знаешь? Хорошо, берем код:

procedure TForm1.Button1Click(Sender: TObject);
var
 P: PChar;
 I: Integer;
begin

 Caption := "Ну это просто заголовок формы сделан просто так, чтобы память забить";
 I := GetWindowTextLength(Handle);
 GetMem(P, I);
 GetWindowText(Handle, P, I);
 FreeMem(P);

 Caption := "Caption12";

 I := GetWindowTextLength(Handle);
 GetMem(P, I);
 GetWindowText(Handle, P, I);
 ShowMessage(p); // интересно, ЧТО ЗДЕСЬ ОКАЖЕТСЯ?
 FreeMem(P);

end;


И знаешь что оказалось? Заголовок то равен "Caption12", а знаешь что мне код вернул?
"Caption12у это просто заголовок формы сделан просто так, чтобы память забить"

Это значит не глюк?

В MSDN есть такая строчка:

"If the window text string is as long or longer than the buffer, the string is truncated and terminated with a NULL character. "  ?!

Так вот эта строчка для Windows 2000 SP2 не выполняется, что может привести к краху программы. Все равно не глюк?


 
Piter ©   (2004-11-06 22:13) [41]

Игорь Шевченко ©   (06.11.04 22:05) [39]
Я бы делал вообще по-другому, если бы мне нужно было получить текст из окна


как?


 
Verg ©   (2004-11-06 22:59) [42]


> [40] Piter ©   (06.11.04 22:12)


Ты несешь уже откровенную чушь.


 
Игорь Шевченко ©   (2004-11-06 23:11) [43]

Piter ©   (06.11.04 22:13) [41]


> как?



var
 AText : array[0..MAX_PATH] of char;
begin
 GetWindowText(AWindowHandle, AText, SizeOf(AText));
....
end;


Так.


> Хорошо, берем код:


И мне этот код выдает "Caption1";

D6, стандартные настройки для проекта.

Я тебе еще раз советую, пройдись отладчиком по CPU Window, оно всем уже интересно


 
Verg ©   (2004-11-06 23:33) [44]


> между прочим, я указываю ПРАВИЛЬНЫЕ ПАРАМЕТРЫ. Чем мои параметры
> неправильны? Я волен указать любое число. В документации
> по этому поводу ничего не сказано.


Ты пойми, вьюноша, что права, дай Бог,  ты будешь качать в другом месте....
Здесть тебе сказано однозначно:  Specifies the maximum number of characters to copy to the buffer, including the NULL character. - какого хрена ты хочешь поднять волну? Другими словами - тебе не ясно, что там написано в документации?????? Ты до сих пор не смог в это врубиться?
Тебе неуютно в этом мире? Ты не дружишь с собственной головой? Нет, ну ты скажи - мы все потдержим!

P.S. Ну злишь ты меня, как никто другой..... своей упертостью. Иногда граничащей с тупостью....


 
Piter ©   (2004-11-07 02:06) [45]

Verg ©   (06.11.04 22:59) [42]
Ты несешь уже откровенную чушь


спасибо, что разъяснил

Игорь Шевченко ©   (06.11.04 23:11) [43]
И мне этот код выдает "Caption1";


ИГОРЬ! Ну как вы не поймете - я вам верю, что у вас все ок! Более того, на WinME и WinXP у меня тоже все ок! А на WINDOWS 2000 SP2 НЕ ОК! Ну сколько можно повторять? Вот я создал EXE"шник - запускаю его из под w2k SP2 - глючит. Запускаю из под XP - нормально. Какие вам доказательства нужны? Если вы хотите - могу привести скриншот из CPU window.

В чем проблема? Очевидно, ошибка в WinApi. В w2k SP3 ее исправили. Что с того? Ведь сервис паки не просто так выпускают? :)
Ну если так не верится - достаньте где-нибудь w2k SP2 и убедитесь!

Verg ©   (06.11.04 23:33) [44]
Ты пойми, вьюноша, что права, дай Бог,  ты будешь качать в другом месте....


какие права? Что я качаю? Я сообщаю о баге. Да, я считаю это багом. Вы не можете опровергнуть что это баг и ругаетесь на меня. За что? Или вы считаете, что я в принципе не могу понять всей проблемы? Или в чем проблема? Если вы не считаете это багом - аргументированно докажите, почему так считаете.

Specifies the maximum number of characters to copy to the buffer, including the NULL character. - какого хрена ты хочешь поднять волну?

да, в документации это написано. А я что, в своем примере нарушаю это?! Я выделил I байт под буфер. Я передаю в функцию это число I, которое задает длину буфера, ВКЛЮЧАЯ терминирующий символ. Где я пошел против документации?! ГДЕ?

Может, ты не понимаешь, что я пишу и в очередной раз спросишь что мне не нравится? Я отвечу. Мне не нравится, что система идет против документации. В документации написано:

"If the window text string is as long or longer than the buffer, the string is truncated and terminated with a NULL character. "

Я плохо знаю английский - признаю. Но трактую это так, что если размера буфера не хватает для записи полной строки заголовка + терминирующего символа, то строка усекается, но терминирующий символ по любому будет записан, о чем недвусмысленно дает понять фраза:
"and terminated with a NULL character"

Более того, это ожидаемое поведение от WinApi функции. Ведь если она не запишет признак окончания строки - как я узнаю где строка кончается? Конечно, я могу судить по возвращаемому значению, которое говорит о количестве записанных символов, но это не оправдывает того, что система забыла записать терминирующий символ.

Более того, я вам привел пример, который построен правильно с точки зрения документации, но который выдает полную фигню на некотором ПО.

Более того, как я понял ты не считаешь такое проявление ошибкой? Зато вот Microsoft, судя по всему, таки считает это ошибкой, если в своих сервис паках она ликвидировала данное недоразумение. И я солидарен с этим решением. Но ты видимо нет. Ты, наверное, считаешь, что вовсе не надо было переделывать данную функцию?

Тогда аргументировано, пожалуйста, обоснуй свою позицию почему это не глюк. Желательно последовательно, в том духе почему приведенная мной программа работает неправильно - где там ошибка?

Если аргументы на уровне "ты, Питер, дурак и ничего не понимаешь" - то можешь ничего не писать. Мне это уже неоднократно высказывали и влияние на меня это не оказывает, особенно потому, что в некоторых случаях я все таки был прав.

Игорь Шевченко ©   (06.11.04 23:11) [43]
var
AText : array[0..MAX_PATH] of char;
begin
GetWindowText(AWindowHandle, AText, SizeOf(AText));
....


я тоже об этом думал. Но вроде MAX_PATH говорит только о максимальном размере пути в файловой системе! Или для заголовков окон такое ограничение тоже присутствует? Употребление данной конструкции в GetWindowDirectory я понимаю. А точно для GetWindowText это подходит?


 
Piter ©   (2004-11-07 02:06) [46]

Verg ©   (06.11.04 23:33) [44]
Ну злишь ты меня, как никто другой..... своей упертостью. Иногда граничащей с тупостью


ну и ты меня злишь тем, что даже не хочешь понять, что я тебе хочу сказать


 
Verg ©   (2004-11-07 17:20) [47]

Да ладно, не бери в голову - сегодня праздник как ни как.
Давай лучше нальем и выпьем за согласие и примирение.
Ты со мной согласен? :)


 
Игорь Шевченко ©   (2004-11-07 17:26) [48]

Piter ©   (07.11.04 02:06) [45]

извини, у меня вопрос - до тебя с какого раза просьба посмотреть в CPU Window дойдет ?

С праздничком:)


 
GuAV ©   (2004-11-07 17:51) [49]

Игорь Шевченко ©   (06.11.04 23:11) [43]
var
AText : array[0..MAX_PATH] of char;
begin
GetWindowText(AWindowHandle, AText, SizeOf(AText));
....
end;


А причём тут MAX_PATH ?
Заголовки окон бывают и длинее.


 
Игорь Шевченко ©   (2004-11-07 17:57) [50]

GuAV ©   (07.11.04 17:51) [49]

Мне достаточно. Насчет заголовков окон длиннее 260 символов - так GetWindowText обрежет. Мне анализировать их содержимое (длинных заголовков) не приходилось, чаще всего показывать, а сверхдлинный текст смотреть неудобно. Потому и привожу свой способ.


 
Piter ©   (2004-11-07 19:18) [51]

Игорь Шевченко ©   (07.11.04 17:26) [48]
извини, у меня вопрос - до тебя с какого раза просьба посмотреть в CPU Window дойдет ?


ну а что там смотреть? Вот я скомпилировал EXE"шник. Я его запускаю под win 2000 SP2 - глючит. Запускаю под WindowsXP - не глючит. ОДИН И ТОТ ЖЕ EXE"ШНИК. Какие еще доказательства нужны? Я не знаю, что смотреть в CPU Windows. Если хотите посмотреть - пожалуйста. Чистый проект, настройки по дефолту, код такой:

program Project1;

uses
 Forms,
 Unit1 in "Unit1.pas" {Form1};

{$R *.res}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.

----------------------------------------------------------------------------

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
I: Integer;
begin
I := GetWindowTextLength(Handle);
SetLength(S, I);
GetWindowText(Handle, PChar(S), I);
ShowMessage(S);
end;

end.


Данный код выдает "Form1"

Вот окно CPU window:

http://piter007.newmail.ru/cpu.gif


 
Игорь Шевченко ©   (2004-11-07 21:16) [52]

Piter ©   (07.11.04 19:18) [51]

А мне-то какой смысл смотреть - у меня все работает согласно описанному в документации.

Я вот не понимаю, неужели самому так трудно посмотреть, какие символы заносятся, вместо того, чтобы флейм на 50 постов разводить.


 
Piter ©   (2004-11-07 22:23) [53]

Игорь Шевченко ©   (07.11.04 21:16) [52]
Я вот не понимаю, неужели самому так трудно посмотреть, какие символы заносятся


Игорь, а разве непонятно какие символы заносятся? Я вроде раз 150 сказал, что данный пример у меня записывает "Form1" без записи терминирующего символа. Я это говорю на каждой странице. Только видимо никто не слушает?


 
Игорь Шевченко ©   (2004-11-07 22:25) [54]

Piter ©   (07.11.04 22:23) [53]

Knowledge Base смотрел ?


 
_silver ©   (2004-11-08 00:03) [55]

У меня WIN2000 pro SP3 rus.
И этот глюк(а может и не глюк, просто ни когда не приходило в голову определять длину заголовка без +1) имеет место быть.


 
Piter ©   (2004-11-08 12:17) [56]

Игорь Шевченко ©   (07.11.04 22:25) [54]
Knowledge Base смотрел ?


нет. А на что смотреть?


 
Piter ©   (2004-11-08 17:33) [57]

Игорь Шевченко ©   (07.11.04 17:57) [50]
Насчет заголовков окон длиннее 260 символов - так GetWindowText обрежет


ага, обрежет. А том то и дело, что на некоторых системах она неверно обрежет строку, что явно может привести к некорректной работе приложения.
Правда, некоторые личности утверждают, что это проблема программиста, нефиг мол передавать "неправильные" параметры...


 
Игорь Шевченко ©   (2004-11-09 11:09) [58]

Piter ©   (08.11.04 12:17) [56]


> нет. А на что смотреть?


На пофиксенные баги, разумеется. Все пофиксенные баги отражаются в knowlegde base в MSDN. Если ты там не нашел чего-то, то баг не в функции GetWindowText, а где-то еще.


 
kaZaNoVa ©   (2004-11-09 14:08) [59]

Piter ©   (07.11.04 19:18) [51]

> Данный код выдает "Form1"

у меня на 2003 выдаёт  "Form" !!!!

I := GetWindowTextLength(Handle)+1;
SetLength(S, I);
GetWindowText(Handle, PChar(S), I);

выдаёт Form1 ;))))


 
kaZaNoVa ©   (2004-11-09 14:09) [60]

Игорь Шевченко ©   (09.11.04 11:09) [58]
в 2003 снова этот баг ;))))))


 
Piter ©   (2004-11-09 19:55) [61]

kaZaNoVa ©   (09.11.04 14:08) [59]
у меня на 2003 выдаёт  "Form" !!!!


ну так и должно выдавать имеено так... А у меня выдает "Form1" - глюк.

Игорь Шевченко ©   (09.11.04 11:09) [58]
На пофиксенные баги, разумеется. Все пофиксенные баги отражаются в knowlegde base в MSDN


я даже не знаю как искать... может, вы посмотрите? :)


 
kaZaNoVa ©   (2004-11-09 21:11) [62]

Piter ©   (09.11.04 19:55) [61]
а .. понятно, это я перепутал ...   ;(
а ввобще-то имхо form1 как-то логичнее .. :)


 
Nous Mellon ©   (2004-11-09 22:06) [63]


> а ввобще-то имхо form1 как-то логичнее .. :)

Ты похоже даже не понял смысл ветки


 
Nous Mellon ©   (2004-11-09 22:07) [64]

Мишань, поддерживаю. Мастера занаезжались немного. Обвиняют в тупизне не читая вопроса.


 
Piter ©   (2004-11-09 22:47) [65]

Nous Mellon ©   (09.11.04 22:07) [64]

спасибо :)


 
Piter ©   (2004-11-09 22:52) [66]

Игорь Шевченко ©   (09.11.04 11:09) [58]

поискал, поискал - ничего не нашел. Может, мелкий баг и не описали? А может плохо ищу...


 
Германн ©   (2004-11-10 05:30) [67]

Удалено модератором


 
Германн ©   (2004-11-10 05:33) [68]

Удалено модератором


 
Игорь Шевченко ©   (2004-11-10 11:12) [69]

Piter ©   (09.11.04 19:55) [61]


> я даже не знаю как искать... может, вы посмотрите? :)


Я тоже не нашел. Нашел про Win32s 1.25 но немного другое, про возвращаемое значение.


 
SPeller ©   (2004-11-10 13:52) [70]

Я тоже ради интереса посмотрел на КВ - ничего кроме [69] не нашел. Быть може это действительно баг?


 
GuAV ©   (2004-11-11 01:36) [71]

Piter ©   (06.11.04 1:22) [11]
Но как только переключитесь на окно чужого приложения


To retrieve the text of a control in another process, send a WM_GETTEXT message directly instead of calling GetWindowText.

Если бы наоборот - пикало бы на своё - то всё бы было ваще правильно :)

У меня в 98 всегда пикает.


 
Piter ©   (2004-11-11 10:20) [72]

SPeller ©   (10.11.04 13:52) [70]
Быть може это действительно баг?


ну по моему очевидный баг. Причем явно исправленный...

Давайте так - у меня сейчас SP2. Я создам EXE"шник - посмотрю выводимые значения. Потом поставлю SP4 и запущу тот же EXE"шик - если такого поведения не будет, значит просто не упомянули про это...



Страницы: 1 2 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.69 MB
Время: 0.04 c
14-1100438747
Иной
2004-11-14 16:25
2004.11.28
Сумрачная ветка


6-1095338917
Stanislav
2004-09-16 16:48
2004.11.28
Indy Help, Demo


4-1097838267
Wolffgang
2004-10-15 15:04
2004.11.28
Проблема с определением заголовка окна


14-1099647778
TankMan
2004-11-05 12:42
2004.11.28
Хотелось бы узнать, никто не знает, где скачать первый Delphi?


1-1100506148
Lera
2004-11-15 11:09
2004.11.28
Длинна слова.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский