1) Почему не падает @fn[1].
Вообще-то, это тип pchar, который, для пустой строки fn - тупо равен нулю (проверил отладочными выводами). Если им пользоваться как указателем на символ - упадет сразу. В твоем коде это передается в _hi_onEvent, а Дельфи сначала переводит это дело в строку с помощью LStrFromPChar. А там есть "страховочка" против нулевого указателя. Она возвращает пустую строку. Потому и не падает.
В ком еще есть "страховочка", а в ком ее нет -- тайна сия велика есть.
2) Почему падает CharLower.
Потому что мягкотелые - говнюки. Оказывается, привести к нижнему регистру пустую строку - неразрешимая задача. Это мой прокол, ибо такой гадости я от них не ожидал.
НО, они подстелили соломку для лохов. Если указатель на строку "почти нулевой" (hword=0), то они считают его не указателем, а символом, который приводят к нижнему регистру и его и возвращают. Т.е., если ты лоханулся, и влепил нулевой указатель, то они посчитают его нулевым символом, приведут его к нижнему регистру, и ноль же и вернут.
Неправильными действиями получаем правильный результат, потому что кто-то специально рассчитал, что ты будешь действовать неправильно.
Дурдом на каникулах, но я в этом не виноват.
3) Маленькое открытие.
Дельфи, в тот момент, когда ты где-то запомнил указатель на символ строки, начинает подозревать тебя в том, что ты будешь менять содержимое строки, и АВТОМАТИЧЕСКИ выполняет UniqueString, без нашего участия. Если и мы это делаем, то это делается два раза (буквально подряд).
Вот такой он парень, этот Дельфи. Если мы получаем указатель на символы с помощью PChar(fn) -- то он нас ни в чем плохом не подозревает. А если тот же самый указатель с помощью @fn[1] -- сразу же влепляет UniqueString.
4) Вывод.
Надо делать CharLower(@st[1]) с последующим автоматическим преобразованием его в string, и забыть про UniqueString (он сам про него вспомнит).
Обновил этот аттач по вышеуказанным причинам.
------------ Дoбавленo в 00.22:
nesco писал(а):
То-то она нагарантировала#pas
function _LStrToPChar(const s: AnsiString): PChar;
asm
{ -> EAX pointer to str }
{ <- EAX pointer to PChar }
TEST EAX,EAX
JE @@handle0
RET
@@zeroByte:
DB 0
@@handle0:
MOV EAX,offset @@zeroByte
end;