Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 | 3 |

 

  Вопрос: SendMessage() Добавлено: 26.02.06 20:20  

Автор вопроса:  Sacred Phoenix | ICQ: 304238252 
Вызываю SendMessage(hWnd, WM_COMMAND, &h1, ByVal "Hello!"). В subclass-функции WindowProc(ByVal hWnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&) последний параметр передается целым числом. Как получить переданную строку? (по ходу возвращается указатель?)

Ответить

  Ответы Всего ответов: 40  

Номер ответа: 1
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #1 Добавлено: 26.02.06 20:51
Открою тебе страшную тайну :)), которая для vb-программера может показаться ересью: СТРОКИ НЕ ПЕРЕДАЮТ В КАЧЕСТВЕ ПАРАМЕТРОВ!!!
Передают только адреса строк. И то число, которое ты увидел в subclass-функции - это и есть адрес твоей строки.
Делаешь так:

WindowProc(ByVal hWnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&;)

Dim S As String

    S=Space$(wParam+1)
    Call CopyMemory(S, lParam, wParam+1)
    MsgBox S


Параметром h1 передавай длину строки.

Ответить

Номер ответа: 2
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #2 Добавлено: 26.02.06 21:21
Можно попробовать ещё вариант - не CopyMemory, которая требует количество байт для копирования, а что-то из разряда апи - lstrcpy например. Ей длина не нужна.

Ответить

Номер ответа: 3
Автор ответа:
 Sacred Phoenix



ICQ: 304238252 

Вопросов: 52
Ответов: 927
 Профиль | | #3 Добавлено: 26.02.06 21:49
СТРОКИ НЕ ПЕРЕДАЮТ В КАЧЕСТВЕ ПАРАМЕТРОВ!!!

Ну да! А FindWindow??? А SendMessage(hWnd, WM_SETTEXT, 0, ByVal "Text";)???

1. Вариант с CopyMemory подошел бы, но я не передаю длину строки через wParam! Тем более, что в вышеприведенном примере с WM_SETTEXT длина строки не передается!
2. Как юзать lstrcpy, если оба параметра опять-таки строковые?

Ответить

Номер ответа: 4
Автор ответа:
 mich



ICQ: 261800349 

Вопросов: 19
Ответов: 148
 Web-сайт: belkyokushin.net
 Профиль | | #4
Добавлено: 26.02.06 22:56
Можно в HKEY_CURRENT_CONFIG\Software\[wPar] записать строку.

Ответить

Номер ответа: 5
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #5 Добавлено: 26.02.06 22:59
Открываю вторую страшную тайну:)))
Параметры в любую из функций для процессоров семейства i386 (к которым принадлежит и наши с тобой процессоры) имеют длину 4 байта. В 4 байта можно вместить только строку из 3-х символов. Как по-твоему передаются строки, если их длина может превышать 3 символа? Правильно: в качестве параметра передается адрес памяти, начиная с которого расположены байты, составляющие твою строку. Т.е. передается адрес первого из набора байт (символов строки). А адрес как раз и занимает 4 байта в соответствие с тем, что процессор у нас 32-битный.
Когда пишешь ByVal "My Super - Puper String", то строку ты видишь только в редакторе кода IDE. А VB увидев ключевое слово ByVal и следующую за ним переменную строкового типа, заменяет при компиляции этот параметр (якобы строку) на её адрес, который и получается в принимающей процедуре

Ответить

Номер ответа: 6
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #6 Добавлено: 26.02.06 23:30
'Длину передавать не надо

Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyW" (ByVal lpString1 As String, _
                                                                  ByVal lpString2 As Long) As Long
         
Function WindowProc(ByVal hWnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&;) As Long
    'чтобы lstrcpy не отрезала строку по первому символу
    'возьмём её юникод-версию - lstrcpyW
    Dim SSS As String                       'Объявляем строку - приемник - буфер
    SSS = String$(512, Chr$(0))             'Растягиваем этот буфер под достаточный размер
    lstrcpy ByVal SSS, ByVal lParam         'копируем в него наши символы как юникод
    SSS = StrConv(SSS, vbFromUnicode)       'преобразуем из юникода в vb-строку
    Debug.Print SSS                         'наслаждаемся результатом
End Function


Банзай!

Ответить

Номер ответа: 7
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #7 Добавлено: 27.02.06 11:55
В принципе, можно заюзать функции msvbvm или, что проще, воспользоваться vbvm6lib.tlb для работы напрямую с указателями. Не потребуется лишней работы по копированию строк.

Ответить

Номер ответа: 8
Автор ответа:
 Sacred Phoenix



ICQ: 304238252 

Вопросов: 52
Ответов: 927
 Профиль | | #8 Добавлено: 27.02.06 13:25
А VB увидев ключевое слово ByVal и следующую за ним переменную строкового типа, заменяет при компиляции этот параметр (якобы строку) на её адрес, который и получается в принимающей процедуре

Да это я понял, в вопросе же я написал, что кажется, передается указатель! За lstrcpy спасибо большое! И за открытые страшные тайны тоже!

Ответить

Номер ответа: 9
Автор ответа:
 ANDREY



Вопросов: 0
Ответов: 33
 Профиль | | #9 Добавлено: 27.02.06 23:50
Параметры в любую из функций для процессоров семейства i386 (к которым принадлежит и наши с тобой процессоры) имеют длину 4 байта.

Нет, такого ограничения нигде нету :) Однако stdcall требует что бы суммарная длина всех параметров была всегда одинаковой. Кроме того передавать всю строку в качестве парметров не целесообразно с точки зрения скорости. Поэтому и передается указатель.
Кроме того, просто к сведению, длину VB-шной строки можно узнать используя просто прочитав четыре байта, которые лежат ДО того места, на которое указывает строка.

Ответить

Номер ответа: 10
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #10 Добавлено: 28.02.06 01:33
ANDREY
Я знаю, что такое bstr, и где лежит длина строки.

Нет, такого ограничения нигде нету :) Однако stdcall требует что бы суммарная длина всех параметров была всегда одинаковой


Это ты хорошо подумал, прежде чем сказать? Если нет, то сначала надо подумать, а лучше подучить матчасть, прежде чем делать такие заявления.

Кроме того передавать всю строку в качестве парметров не целесообразно с точки зрения скорости. Поэтому и передается указатель.


Строку передать невозможно. VB создает копию строки, и передает указатель на эту копию. Вот отчего снижается скорость: из-за копирования/преобразования. Ты просто слышал звон (о копировании строки при передаче в функции), но откуда этот звон так и не понял.

Так что подучи матчасть :)
Вот тебе пример:

msgString db "Message String",0

push 0
push 0
push offset msgString
push 0
call MessageBox

Это аналог MessageBox ByVal 0, ByVal "Message String", ByVal 0, ByVal 0

Возьми справочник по опкодам и посмотри что делают инструкции push. Сколько байт они ложат в стек процессора i386.

И заучи, как "Отче Наш": строки не передаются никуда, передаются их адреса, либо адреса их копий, что то же самое.

Ответить

Номер ответа: 11
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #11
Добавлено: 28.02.06 08:17
push ax - реально ;)

Ответить

Номер ответа: 12
Автор ответа:
 ANDREY



Вопросов: 0
Ответов: 33
 Профиль | | #12 Добавлено: 28.02.06 08:52
Возьми справочник по опкодам и посмотри что делают инструкции push. Сколько байт они ложат в стек процессора i386.
Сам возьми. Кроме того, кто тебе сказал что в стэк данные можно положить только командой push?
Строку передать невозможно
Если это cdecl функция то не вижу тут ничего невозможного.
Это ты хорошо подумал, прежде чем сказать?
А ты слышал про команды push r16 и push r8?

Ответить

Номер ответа: 13
Автор ответа:
 ANDREY



Вопросов: 0
Ответов: 33
 Профиль | | #13 Добавлено: 28.02.06 12:09
А вообще, если хочеш действитнльно обсудить, а не просто показать что ты умный, моя аська 202445204, давай вечером обсудим и потом ты напишеш сюда в чем и почему ты был неправ.

Ответить

Номер ответа: 14
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #14 Добавлено: 28.02.06 12:55
push ax - реально ;)

И что ? Ты сможешь сделать
mov ax,offset msgString
push ax
???
Попробуй :) Только не надо мне говорить, что можно сделать два раза push ax, т.к. это эквивалентно push eax

ANDREY
Я тебе привел пример. С push 0 и push offset msgString
Для особо одаренных повторю вопрос:
сколько байт ложит в стек push 0 и сколько ложит push offset msgString ?

А ты слышал про команды push r16 и push r8?

Ещё раз повторю: Думай, прежде чем говорить
push r8 - это что такое? Ты можешь сделать push al ?? Или push dh ???

Кроме того, кто тебе сказал что в стэк данные можно положить только командой push?


Я не говорю о том, что данные можно положить только с помощью push. И способов положить я знаю наверняка поболее чем ты :)

А чтобы ты не уводил разговор в сторону от темы, у меня к тебе просьба: сделай мне пример, который:
1. Читает текстовый файл размером 2 Мб в переменную типа String
2. Передает эту строку !ИМЕННО ВСЮ СТРОКУ - ВСЕ 2 МБ! а не просто указатель на неё, в качестве параметра в WndProc.
3. Считывает эту строку в WndProc и выводит длину строки и саму строку в читабельном виде любым удобным для тебя способом.

Напомню тебе твои слова:
передавать всю строку в качестве парметров не целесообразно с точки зрения скорости

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

Жду пример.
А пока для предотвращения флейма скажу:
обсуждать твои перлы типа push r8 или stdcall требует что бы суммарная длина всех параметров была всегда одинаковой
обсуждать не намерен.
Итак, жду пример...
Пока его нет - ни слова :)

Ответить

Номер ответа: 15
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #15 Добавлено: 28.02.06 13:09
Прошу прощения что встреваю в столь интересный спор, но есть одна маленькая просьба к уважаемому HOOLIGAN'у
Пожалуйста, не надо больше писать ложит. Коробит читать. Аффтаров у нас и без того хватает.
Незачот!

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам