Проблема с русскими буквами в Lazarus 0.9.30.4 от 14.03.2012

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
PapaNT
постоялец
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Проблема с русскими буквами в Lazarus 0.9.30.4 от 14.03.2012

Сообщение PapaNT »

Всем доброго времени суток!

Слил свежий лазарь. Попробовал в нем кусок старого кода, успешно работавшего на FPC 2.6.0. При сборке в лазаре вместо русских букв стали вопросы, а в FPC все работало нормально (вывод шел в кодировке 1251)...
Кусок кода:

Код: Выделить всё

Function WinList (Wd : LongWord; Param : LongInt) : LongBool; StdCall;

  Function GetWindowName(Wd : LongWord) : ShortString;
  Var
    Nm : Array [0..255] of Char;
    St : ShortString;
    i  : Word;
  begin
    GetWindowText(Wd,Nm,255); // Получаем имя окна
    i := 0;                   // Переводим имя в строку
    St := '';
    While (Nm[i] <> #0) and (i <> 256) do
      begin
        St := St + Nm[i];
        inc(i)
      end;
    GetWindowName := St       // Возвращаем строку с именем окна в результат
  end;

begin
      if IsWindowVisible(WD) Then // Это видимое окно...
        if IsWindow(WD) Then // Это окно???
          Form1.ListBox1.Items.Add(IntToStr(WD) + #32 + GetWindowName(Wd));
    WinList := True;
end;
daesher
постоялец
Сообщения: 221
Зарегистрирован: 09.03.2010 21:17:14

Сообщение daesher »

Скорее всего, проблема в этой строке:

Код: Выделить всё

Form1.ListBox1.Items.Add(IntToStr(WD) + #32 + GetWindowName(Wd));

GetWindowName, скорее всего, окажется ссылкой на GetWindowNameA, вернёт строку в Ansi, а ListBox ожидает элементы в UTF8. Надо конвертировать.
SSerge
энтузиаст
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Сообщение SSerge »

Мне всё было любопытно, ткнут сотоварищи вопрошающего носом "в LCL Unicode Support", или нет, тем более что в статейке оной даже примерчики с этими самыми GetWindowText. Ан нет. Более того, даже абсолютно невнимательно читаем текст проблемного примера :) Ибо, по нему GetWindowName никогда не окажется ссылкой на GetWindowNameA, потому что это функция определенная пользователем. Однако ж:

- Принципиальная ошибка номер 1 - перед вызовом GetWindowText полагается определить требуемую длину буфера вызовом GetWindowTextLength. Намек, надеюсь, понятен. А никаких там буферов с размером 255 и определения конца оного по недокументированным признакам НЕ НАДО.
- Принципиальная ошибка номер два. С операционной системой Windows взаимодействуем через WideStrings. Точка. Windows 95/98/ME грохнули сколько лет назад? Стоит ли пользоваться устаревшим/obsolete интерфейсом и потом удивляться, что неожиданно что-то перестанет работать в Windows 8,9 etc. То есть, GetWindowTextW, GetWindowTextLengthW куда более правильные чем GetWindowTextA, которые еще и исказят при случае ваши имена окон.
- Принципиальная ошибка номер три - вы таки не понимаете вообще сути конверсии и представления кодовых страниц.

Если с точки зрения "как должно быть и как правильно" - это здесь: http://sirserge.altai.info/articles/?id=44

Если с точки зрения "как сделать вручную чтобы было более менее корректно, когда компилятор уникод не поддерживает" - это здесь: http://sirserge.altai.info/articles/?id=41

И для полноты картины, чтобы не возникало иллюзий, как оно на самом деле правильно: http://sirserge.altai.info/articles/?id=43 (Это, извините, С++, но методика работы с уникодом во все что ни попадя копируется именно оттуда)
PapaNT
постоялец
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Сообщение PapaNT »

Решено!


Прокурил исходники лазаря... "Не ту страну назвали Гондурасом..." (с)

Код: Выделить всё

Uses Win32proc;
Var
St : String;
....

st := GetControlText(Handler);

И все работает...
Ответить