![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передать PChar через PostMessage [D5, 2000]
Призрак © (2006-07-02 21:38:00)Один поток передаёт другому
PostMessage(MyWnd.Handle, WM_USER, integer(PChar('Log Entry')), 0), а второй добавляет этот'Log Entry'кMemo. Вопрос - это не приведёт к каким-нибудь проблемам с освобождением памяти? Я же передаю адрес на специально автоматически созданную переменную... она точно правильно автоматически освободится сразу после добавления вMemo? И то же самое - если я не явно укажу'Log Entry', а черезstring-переменную... проблем не будет?..
begin...end (2006-07-03 21:12:00) [1]> Призрак © (03.07.06 20:48) [10]
Можно и так. Правда, не совсем понятно, откуда взялось число 255. Лучше выделять память именно в том количестве, в котором она нужна. Т.е. отправку я бы оформил так: PostMessage(LogForm.Handle, WM_USER, WParam(StrNew(PChar(s))), 0).
Призрак (2006-07-03 21:10:00) [2]ой... да. спасибо. ^_^
Leonid Troyanovsky (2006-07-03 21:09:00) [3]
> Призрак © (03.07.06 20:48) [10]
> procedure AddLogMessage(s: string);
> var pch: PChar;
> begin
> pch:=StrAlloc(255);
Тогда уж pch := StrAlloc(Length(s) + 1)
--
Regards, LVT.
Призрак (2006-07-03 20:48:00) [4]Ммм... Так?
procedure AddLogMessage(s: string);
var pch: PChar;
begin
pch:=StrAlloc(255);
StrCopy(pch, PChar(s));
PostMessage(LogForm.Handle, WM_USER, integer(pch), 0);
end;
procedure TLogForm.ProcessLogReport(var Msg: TMessage); (message WM_USER)
var pch: PChar;
begin
pch := PChar(Msg.wParam);
Memo1.Lines.Add(pch);
StrDispose(pch);
end;
Leonid Troyanovsky (2006-07-03 07:11:00) [5]
> Призрак © (03.07.06 04:09) [8]
> А как это надо делать? Я не хочу использовать SendMessage,
> надо асинхронно... Что мне приходит в голову - это создать
Это ж почему асинхронно? Надо, как раз, синхронно, если,
конечно, это дейс-но, запись в лог.
> динамическую переменную, то есть указатель, создать его
> в одном потоке, потом передать в другой и освободить после
> добавления в мему... но я с трудом представляю, как в винде
Да так и делать - первый поток cделает GetMem/StrAlloc,
а второй, после обработки - FreeMem/StrDispose.
--
Regards, LVT.
Призрак (2006-07-03 04:09:00) [6]У меня была теория: я передаю "представление указателя на строку в виде целого", потом меняю строку, и когда в лог добавляется то что лежит там куда указывает указатель, то получится новая строка... Если нет - значит, PChar() не указатель на данную строку даёт, а копирует данную в другое место и возвращает указатель на это... А вот когда "это" разрушается - я не знаю...
А как это надо делать? Я не хочу использовать SendMessage, надо асинхронно... Что мне приходит в голову - это создать динамическую переменную, то есть указатель, создать его в одном потоке, потом передать в другой и освободить после добавления в мему... но я с трудом представляю, как в винде работает вся эта система выделения переменных, освобождения... и вообще как PChar работает... может, просто сделать указатель на строку, и потом New(s) - s:=<что там мне надо> - Postmessage(...s...) и потом в другом потоке тоже описать указатель на строку, взять его из GetMessage и потом Dispose?..
Leonid Troyanovsky (2006-07-02 23:19:00) [7]
> Призрак © (02.07.06 23:07) [6]
> а в принимающем потоке сделал перед отображением задержку
> на секунду, так чтобы сначала отправилось, потом строка
> изменилась, а потом уже отобразилось... и отобразилась первая
> строка :)
Эксперименты без подходящей теории - поиски в темноте.
Изучать же следует threads & synchronization (Delphi help & msdn).
> *перечитал несколько раз и не понял* ..."здесь тоже константа"?
> .. где?.. там же переменная...
Эта переменная string, которой присвоена константа.
В ее поле кол-во ссылок стоит -1, IMHO. (see system.pas also).
> а моя та приведённая большая штука работать нормально будет?
Нет.
--
Regards, LVT.
Призрак (2006-07-02 23:07:00) [8]ну, я написал для проверки так:
s:='A string';
PostMessage(....... integer(PChar(s)) .....);
s:='Another string!'
а в принимающем потоке сделал перед отображением задержку на секунду, так чтобы сначала отправилось, потом строка изменилась, а потом уже отобразилось... и отобразилась первая строка :)
*перечитал несколько раз и не понял* ..."здесь тоже константа"?.. где?.. там же переменная...
а моя та приведённая большая штука работать нормально будет?
PostMessage(MyForm.Handle, WM_USER, integer(PChar('COM'+IntToStr(portNum)+': Error '+IntToStr(GetLastError)+' - '+SysErrorMessage(GetLastError))), 0)
Leonid Troyanovsky (2006-07-02 22:25:00) [9]
> Призрак © (02.07.06 22:03) [3]
> А какие именно проблемы меня ждут если я буду переменную
> писать? ну,
> var s: string;
> s:='Magic!';
> PostMessage(MyWnd.Handle, WM_USER, integer(PChar(s)), 0);
Здесь снова константа, хотя уже String.
Но, делать это, в общем случае нельзя, т.к. string может освободится
раньше, чем сообщение будет обработано, бо ассинхронно,
а не через SendMessage.
--
Regards, LVT.
Leonid Troyanovsky (2006-07-02 22:20:00) [10]
> Призрак © (02.07.06 22:03) [3]
> SendMessage(LogMemo.Handle, EM_REPLACESE, integer(PChar(s)),
> 0)
> так?.. а почему replace? что-то заменяется?..
Заменяется выделение. Т.е., сначала карет ставится в
в последнюю позицию (EM_SETSEL), затем
SendMessage(.., EM_REPLACESEL, 0, LParam(PChar(s))
--
Regards, LVT.
Призрак (2006-07-02 22:03:00) [11]> Хотя удобней не мемо, а листбокс, и LB_ADDSTRING со-сно.
Спасибо... хотя здесь мне нужна мемо...
> SendMessage(..EM_REPLACESE).
А как именно?..
var s: string;
s:='Log Entry';
SendMessage(LogMemo.Handle, EM_REPLACESE, integer(PChar(s)), 0)
так?.. а почему replace? что-то заменяется?..
Конкретно... Ну, например, вот такой:
PostMessage(MyForm.Handle, WM_USER, integer(PChar('COM'+IntToStr(portNum)+': Error '+IntToStr(GetLastError)+' - '+SysErrorMessage(GetLastError))), 0)
то есть - "COM1: Error xxx - error description"
А какие именно проблемы меня ждут если я буду переменную писать? ну,
var s: string;
s:='Magic!';
PostMessage(MyWnd.Handle, WM_USER, integer(PChar(s)), 0);
P. S. принимающая часть выглядит просто -
procedure TMonitorForm.ProcessReport(var Msg: TMessage); (она описана как message WM_USER);
begin
Memo1.Lines.Add(PChar(Msg.wParam));
end;
Leonid Troyanovsky (2006-07-02 21:49:00) [12]
> Призрак © (02.07.06 21:38)
> Один поток передаёт другому PostMessage(MyWnd.Handle, WM_USER,
> integer(PChar('Log Entry')), 0), а второй добавляет этот
> 'Log Entry' к Memo. Вопрос - это не приведёт к каким-нибудь
> проблемам с освобождением памяти? Я же передаю адрес на
> специально автоматически созданную переменную... она точно
> правильно автоматически освободится сразу после добавления
> в Memo? И то же самое - если я не явно укажу 'Log Entry',
> а через string-переменную... проблем не будет?..
Если это константа (PChar('Log Entry')) то не будет.
Если это переменная, то будут.
А, вообще-то, для того, чтобы добавить к Memo есть
SendMessage(..EM_REPLACESE).
Хотя удобней не мемо, а листбокс, и LB_ADDSTRING со-сно.
--
Regards, LVT.
begin...end (2006-07-02 21:47:00) [13]> Призрак © (02.07.06 21:38) [0]
> Я же передаю адрес на специально автоматически созданную
> переменную...
Никакой переменной автоматически не создаётся. Ваша строка -- это константа, записанная в исполняемом файле и отображённая в память. Адрес этой константы Вы и передаёте. А при добавлении в memo эта строка туда (в memo) скопируется.
> она точно правильно автоматически освободится сразу после
> добавления в Memo?
Нет, константа никуда не денется. И освобождать её не надо.
> И то же самое - если я не явно укажу 'Log Entry', а через
> string-переменную... проблем не будет?..
Нужен конкретный код.