LB_GETTEXT ошибка если больше 1064 символов

Тема в разделе "WASM.WIN32", создана пользователем Vjacheslav, 22 дек 2004.

  1. Vjacheslav

    Vjacheslav New Member

    Публикаций:
    0
    Регистрация:
    22 дек 2004
    Сообщения:
    11
    Помогите пожалуйста разобратся.Вот кусок кода


    Код (Text):
    1.   invoke SendMessage,hListBox,LB_GETCURSEL,0,0
    2.    mov Sel, eax
    3.   invoke SendMessage,hListBox,LB_GETTEXTLEN,Sel,0            invoke GlobalAlloc,GMEM_MOVEABLE,eax
    4.    mov h_StrBuffer,eax
    5.   invoke GlobalLock,h_StrBuffer    
    6.    mov p_StrBuffer,eax
    7.   invoke SendMessage,hListBox,LB_GETTEXT,Sel,p_StrBuffer     invoke MessageBox,NULL,p_StrBuffer,addr AppName,MB_OK
    8.   invoke GlobalUnlock,h_StrBuffer
    9.   invoke GlobalFree,h_StrBuffer




    Так вот если в листбоксе содержится больше 1064 символов

    то SendMessage,hListBox,LB_GETTEXT,Sel,p_StrBuffer

    вылетает с ошибкой.Ошибка происходит гдето в недрах системы,так что LB_ERR не возвращается
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Vjacheslav

    Какая ОС?

    Я пробовал под w2ksp4
    Код (Text):
    1. TCHAR buffer[512];
    2. ...
    3.  
    4. [i]// заполнить ListBox[/i]
    5. SendMessage(hwndLB, WM_SETREDRAW, (WPARAM) FALSE, 0);
    6. for (i = 0; i < 2010; i++)
    7. {
    8.   wsprintf(buffer, _T("Item %u"), ++num);
    9.   ret = SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM) buffer);
    10.   if (LB_ERR == ret || LB_ERRSPACE == ret)
    11.   {
    12.     OutputDebugString(_T("SendMessage LB_ADDSTRING failed"));
    13.     break;
    14.   }
    15. }
    16. SendMessage(hwndLB, WM_SETREDRAW, (WPARAM) TRUE, 0);
    17.  
    18. ...
    19.  
    20. [i]// получаю каждый элемент для определения ширины[/i]
    21. hdcLB = GetDC(hwndLB);
    22. cnt = SendMessage(hwndLB, LB_GETCOUNT, 0, 0);
    23. for (i = 0; i < cnt; i++)
    24. {
    25.   ret = SendMessage(hwndLB, LB_GETTEXT, (WPARAM) i, (LPARAM) buffer);
    26.   if (LB_ERR == ret)
    27.   {
    28.     OutputDebugString(_T("SendMessage LB_GETTEXT failed"));
    29.     break;
    30.   }
    31.   if (0 == GetTextExtentPoint32(hdcLB, buffer, lstrlen(buffer), &sz))
    32.   {
    33.     OutputDebugString(_T("GetTextExtentPoint32 failed"));
    34.     break;
    35.   }
    36.   wsprintf(buffer, _T("GetTextExtentPoint32 %ld cx = %ld cy = %ld"), i, sz.cx, sz.cy);
    37.   OutputDebugString(buffer);
    38. }
    39. ...
    в DbgView наблюдаю размеры всех 2010-ти элементов.
     
  3. Vjacheslav

    Vjacheslav New Member

    Публикаций:
    0
    Регистрация:
    22 дек 2004
    Сообщения:
    11
    q_q вы меня неправильно поняли программа падает не когда

    элементов больше 1064,а когда какой нибуть элемент содержит больше 1064 байт и я пытаюсь получить его

    содержание спомощью LB_GETTEXT
     
  4. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Vjacheslav

    Хорошо. Я изменил код заполнения ListBox
    Код (Text):
    1. TCHAR buffer[1024*3];
    2. ...
    3. SendMessage(hwndLB, WM_SETREDRAW, (WPARAM) FALSE, 0);
    4. for (i = 0; i < 2010; i++)
    5. {
    6.   wsprintf(buffer, _T("Item %u"), ++num);[b]
    7.   {
    8.     int j;
    9.     lstrcat(buffer, _T(" "));
    10.     for (j = 0; j < 200; j++)
    11.     {
    12.       lstrcat(buffer, _T("123456789"));
    13.       lstrcat(buffer, _T(" "));
    14.     }
    15.   }[/b]
    16. [i]// теперь длина строки больше 2000[/i]
    17.   ret = SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM) buffer);
    18.   if (LB_ERR == ret || LB_ERRSPACE == ret)
    19.   {
    20.     OutputDebugString(_T("SendMessage LB_ADDSTRING failed"));
    21.     break;
    22.   }
    23. }
    24. SendMessage(hwndLB, WM_SETREDRAW, (WPARAM) TRUE, 0);
    25. ...
    Итого 2010 строк, каждая более 2000 символов. Полет нормальный (снимок в аттаче).



    А теперь я повторяю вопрос: "Какая ОС?"

    [​IMG] _664962521__lb.gif
     
  5. Vjacheslav

    Vjacheslav New Member

    Публикаций:
    0
    Регистрация:
    22 дек 2004
    Сообщения:
    11
    Еще одно замечание.Только что попробовал на WIN98 все

    OK,а на WINXP PRO SP1 вылетает с ошибкой
     
  6. dead_body

    dead_body wasm.ru

    Публикаций:
    0
    Регистрация:
    3 сен 2004
    Сообщения:
    603
    Адрес:
    Украина;г.Харьков;г.Н.Каховка
    Vjacheslav

    приатачь ехе, у меня стоят ХР СП1 и СП2, я гляну что там...
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Vjacheslav



    invoke SendMessage,hListBox,LB_GETTEXTLEN,Sel,0

    invoke GlobalAlloc,GMEM_MOVEABLE,eax



    GETTEXTLEN возвращает длину строки без учёта нуля, может надо перед GlobalAlloc сделать inc eax? Хотя у меня без inc eax работает нормально на длине строки до 10000 байт (ХР Home)
     
  8. Vjacheslav

    Vjacheslav New Member

    Публикаций:
    0
    Регистрация:
    22 дек 2004
    Сообщения:
    11
    cresta

    Прикрепляю свой exe. Запускаешь файл,копируешь в буфер

    обмена какой нибуть текст,по клавишам win+down вызываешь

    прогу, в листбоксе давишь enter ,должен появится messagebox с текстом который ты скопировал.

    [​IMG] 102570462__MultiClpbrd.exe
     
  9. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Vjacheslav

    Прикрепляю свой exe ...

    А я прикрепляю картинку из Olly.

    Объясни почему в LB_GETTEXT передается не тот адрес который вернула GlobalLock?



    PS я согласен с cresta, лучше добавлять байт/слово для завершающего ноля.
     
  10. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    q_q



    Попробовал сделать вместо push <адрес ячейки с адресом от GlobalLock> сделать push eax - результат тотже.



    Vjacheslav

    Ты не пробовал так сделать: передавать с LB_GETTEXT адрес фиксированного буфера в секции .data?, а не от GlobalLock?



    .data?

    Buff_LBTEXT db 4096 Dup (?)



    и invoke SendMessage,hListBox,LB_GETTEXT,0,ADDR Buff_LBTEXT

    Как поведёт себя?
     
  12. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Vjacheslav

    Пробовал сам сделать SendMessage,,LB_GETTEXT с GlobalAlloc - работает, твой же - нет. Получается дело не в XP, дело не в SendMessage и не в GlobalAlloc. Может ты что намутил со стилями листбокса?
     
  13. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Вот пример получения из буфера обмена строки более 1064. Свой код прячешь, а в дебаггере разбирать твой ехе неохота :)

    Смотри, чем отличается от твоего и разбирайся сам, в чём дело.



    Запусти, нажми на кнопку Set Clipboard Viewer, затем скопируй в буфер длинный текст - появится строка в листбоксе. Выдели её и жми Get From ListBox.



    P.S. Проверку на тип данных в буфере не делал, поэтому если не текст в буфере - вылетит программа. Перед запуском скопируй текст в буфер.

    [​IMG] 643561246__GetText.zip
     
  14. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    cresta

    Попробовал сделать вместо push <адрес ячейки с адресом от GlobalLock> сделать push eax - результат тотже.

    Не обманывай.

    Открой hex-редактор, внеси изменения
    Код (Text):
    1. 00000925: 68 50
    2. 00000926: B8 90
    3. 00000927: 30 90
    4. 00000928: 40 90
    5. 00000929: 00 90
    и запусти программу. Она будет работать. Правда MessageBox будет пустой, потому что туда тоже передается не результат GlobalLock, а все тот же адрес 0x004030B8, если хочешь чтобы заработал MessageBox, то надо внести следующие изменения
    Код (Text):
    1. 00000925: 68 6A
    2. 00000926: B8 00
    3. 00000927: 30 68
    4. 00000928: 40 DD
    5. 00000929: 00 20
    6. 0000092A: FF 40
    7. 0000092B: 35 00
    8. 0000092C: CC 50
    9. 0000092D: 38 6A
    10. 0000092E: 40 00
    11. 0000092F: 00 50
    12. 00000930: 68 FF
    13. 00000931: 89 35
    14. 00000932: 01 CC
    15. 00000933: 00 38
    16. 00000934: 00 40
    17. 00000935: FF 00
    18. 00000936: 35 68
    19. 00000937: 88 89
    20. 00000938: 30 01
    21. 00000939: 40 00
    22. 0000093C: 15 35
    23. 0000093D: 6C 88
    24. 0000093E: 20 30
    25. 00000941: 6A FF
    26. 00000942: 00 15
    27. 00000943: 68 6C
    28. 00000944: DD 20
    29. 00000945: 20 40
    30. 00000946: 40 00
    31. 00000947: 00 90
    32. 00000948: 68 90
    33. 00000949: B8 90
    34. 0000094A: 30 90
    35. 0000094B: 40 90
    36. 0000094C: 00 90
    37. 0000094D: 6A 90
    38. 0000094E: 00 90
    Попробовал с размером 10000 байт - появился здоровый MessageBox.



    Свой код прячешь, а в дебаггере разбирать твой ехе неохота

    Imho там разбирать нечего.



    PS я тут недавно писал тебе при кривые программы и обвинения в адрес microsoft, так вот я имел ввиду заявления подобные:

    cresta > намутил со стилями листбокса

    Vjacheslav > Ошибка происходит гдето в недрах системы
     
  15. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    q_q



    Блин, чё ты такой злой???!!! С чего ты взял, что я тебя обманываю с push? Достал из корзины файл с push eax, прикрепляю тебе его, убедишься сам, что нет никакого messagebox'а, в т.ч. и пустого :dntknw:

    И что криминального в моём предположении о стилях листбокса? Разве это обвинения в адрес microsoft?



    Вот листинг из Olly, правилось там же:


    Код (Text):
    1. 00401514 . FF35 B0304000  PUSH DWORD PTR DS:[4030B0]               ; /hMem = NULL
    2. 0040151A . FF15 08204000  CALL DWORD PTR DS:[<&kernel32.GlobalLock>; \GlobalLock
    3. 00401520 . A3 B4304000    MOV DWORD PTR DS:[4030B4],EAX
    4. 00401525   50             PUSH EAX
    5. 00401526   90             NOP
    6. 00401527   90             NOP
    7. 00401528   90             NOP
    8. 00401529   90             NOP
    9. 0040152A . FF35 CC384000  PUSH DWORD PTR DS:[4038CC]               ; |wParam = 0
    10. 00401530 . 68 89010000    PUSH 189                                 ; |Message = LB_GETTEXT
    11. 00401535 . FF35 88304000  PUSH DWORD PTR DS:[403088]               ; |hWnd = NULL
    12. 0040153B . FF15 6C204000  CALL DWORD PTR DS:[<&user32.SendMessageA>; \SendMessageA






    Возможно, за 1064 байтом начинается другой кусок памяти, куда лезть нельзя, поэтому падает.



    [​IMG] 858469766__push eax.exe
     
  16. Vjacheslav

    Vjacheslav New Member

    Публикаций:
    0
    Регистрация:
    22 дек 2004
    Сообщения:
    11
    Наконец накопал из за чего глючит.Это происходит если

    подключаю манифест,хоть к своей проге хоть к проге

    cresta.Так что это глюк винды.

    Спасибо всем за советы !!!
     
  17. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    cresta & Vjacheslav

    В своем сообщении от Дек 24, 2004 04:36:19 я слукавил, не указав, что после изменений проверял работоспособность программы под w2ksp4 и xpprosp2.



    cresta

    Блин, чё ты такой злой???!!!

    Не люблю когда кто-то сваливает вину за свою некомпетентность на других.



    что криминального в моём предположении о стилях листбокса

    Imho криминал в том, что, ты не анализируя код: "разбирать твой ехе неохота" пытаешься дать совет/комментарий.



    Разве это обвинения в адрес microsoft?

    Косвенно да.



    Vjacheslav

    Так что это глюк винды.

    Глюк?! Почему тогда под w2ksp4 и xpprosp2 работает?



    Написал аналог твоей программы. Имеет manifest и работает w2ksp4, xppro, xpprosp1 и xpprosp2.

    [​IMG] 24682183__qqMultiClipboard.rar
     
  18. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    q_q

    Жаль, но в ХР Home твой пример также не работает. Ведет себя аналогично первым двум

    [​IMG] _1066648886__Err.JPG
     
  19. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Даже такой вариант:

    .data?

    MsgBuffer db 10000 Dup (?)

    .code

    invoke SendMessage,hListBox,LB_GETTEXT,ebx,ADDR MsgBuffer

    не проходит :dntknw:
     
  20. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    cresta

    Xp home у меня нет. Буду искать.