Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Передача указателя в сообщении Windows


Автор: Antony41 19.7.2013, 08:33
Вот есть стандартные значения параметров WPARAM и LPARAM
но мне нужно передать больше параметров, значит нужно создать свою структуру и передавать указатель на эту структуру в параметре LPARAM
делаю так 
Код

type
  PMyMessageStruct = ^TMYMessageStruct;
  TMYMessageStruct = packed record //Структура передаваемая главному окну сообщениями windows из потоков и др. окон
    MsgState: Integer; //выбор отображения сообщений содержит типы констант приведенных выше напр. C_MSG_LOG
    Cmd: Word; //передаваемая команда по которой определяется какое сообщение показать
    DialogState: Byte; //Отображение диалоговых сообщений содержит параметр типа напр. MT_INFO или MT_ERROR
  end;


Код

procedure ....
var
  MyMsgStruct: TMYMessageStruct;
begin
MyMsgStruct.MsgState := C_MSG_STATUS; //те вывод сообщений в статус бар
        MyMsgStruct.Cmd := 00005;
        MyMsgStruct.DialogState := 0; //не используется при C_MSG_STATUS
        PostMessage(Application.MainForm.Handle,MY_MESS,0,Integer(@MyMsgStruct));
end;



Вот так пытаюсь обработать полученное сообщение
Код

ShowMessage(IntToStr(PMyMessageStruct(msg.lParam)^.Cmd));


Вот не выходит и всё! как правильно то?

Автор: Illusion Dolphin 19.7.2013, 10:20
Как бы для этого надо использовать wm_CopyData . Пример - http://stackoverflow.com/questions/3058411/how-send-data-record-using-sendmessage-in-separate-process

Автор: Antony41 19.7.2013, 10:35
Блин так и подумал, но что то запутался... Будет ли правильным способом передавать структуры от потока к  основному потоку через wm_CopyData?

Автор: Illusion Dolphin 19.7.2013, 10:57
Цитата

 Будет ли правильным способом передавать структуры от потока к  основному потоку через wm_CopyData? 

Это один из вариантов взаимодейтсвия, слово "правильно" в данном случае неуместно и зависит от конкретного случая. В рамках одного delphi приложения обычно  достаточно стандартного Synchronize. Если это межпроцессовое взаимодействие то тогда wm_CopyData вполне уместно.

Автор: northener 19.7.2013, 11:00
При передаче сообщений внутри одного приложения wm_CopyData не нужен. Можно передать просто указатель на структуру. 
Вот только у вас в коде
Код

procedure ....
var
  MyMsgStruct: TMYMessageStruct;
begin
MyMsgStruct.MsgState := C_MSG_STATUS; //те вывод сообщений в статус бар
        MyMsgStruct.Cmd := 00005;
        MyMsgStruct.DialogState := 0; //не используется при C_MSG_STATUS
        PostMessage(Application.MainForm.Handle,MY_MESS,0,Integer(@MyMsgStruct));
end;

MyMsgStruct: похоже является локальной переменной и после выхода из этой процедуры она теряет свою актуальность и Application.MainForm получает указатель на мусор. Выделяйте память под свою структуру в куче, например через GetMem и передавайте указатель.

Автор: Illusion Dolphin 19.7.2013, 11:02
Цитата

Выделяйте память под свою структуру в куче, например через GetMem и передавайте указатель. 

И в таком случае не забудьте про освобождение памяти smile

Автор: Antony41 19.7.2013, 11:15
Дак в том то и дело что не получается передать указатель на структуру 

Код

var
  MyMsgStruct: PMYMessageStruct;
begin
...
        New(MyMsgStruct);
        MyMsgStruct^.MsgState := C_MSG_STATUS; //те вывод сообщений в статус бар
        MyMsgStruct^.Cmd := 00005;
        MyMsgStruct^.DialogState := 0; //не используется при C_MSG_STATUS
        //ShowMessage(IntToStr( PMyMessageStruct(@MyMsgStruct)^.Cmd ));
        SendMessage(Application.MainForm.Handle,MY_MESS,0,LPARAM(MyMsgStruct));
...
end;


Код

var
  P: PMyMessageStruct;
begin
  P := PMYMessageStruct(msg.lParam);
  ShowMessage(IntToStr(P^.Cmd));
end;

Автор: northener 19.7.2013, 11:16
Цитата(Illusion Dolphin @  19.7.2013,  11:02 Найти цитируемый пост)
И в таком случае не забудьте про освобождение памяти

Ну это как бы само сабой подразумевается. Взрослому человеку не нужно постоянно напоминать что нужно мыть руки выйдя из туалета smile


Автор: Illusion Dolphin 19.7.2013, 11:38
Цитата

Дак в том то и дело что не получается передать указатель на структуру 

Да ну?
Код

unit Unit19;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

const
  MY_MESS = WM_USER + 1;
  C_MSG_STATUS = 0;

type
  TMYMessageStruct = record
    MsgState: Integer;
    Cmd: Integer;
    DialogState: Integer;
  end;
  PMYMessageStruct = ^TMYMessageStruct;

type
  TForm19 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure OnMyMessage(var Msg: TMessage); message MY_MESS;
  public
    { Public declarations }
  end;


type
  TMessageThread = class(TThread)
  private
    { Private declarations }
    FWndHandle: THandle;
  protected
    procedure Execute; override;
    constructor Create(WndHandle: THandle);
  end;

var
  Form19: TForm19;

implementation

{$R *.dfm}

constructor TMessageThread.Create(WndHandle: THandle);
begin
  inherited Create;
  FWndHandle := WndHandle;
end;

procedure TMessageThread.Execute;
var
  MyMsgStruct: PMYMessageStruct;
begin
  FreeOnTerminate := True;

  New(MyMsgStruct);
  MyMsgStruct^.MsgState := C_MSG_STATUS; //те вывод сообщений в статус бар
  MyMsgStruct^.Cmd := 00005;
  MyMsgStruct^.DialogState := 0; //не используется при C_MSG_STATUS
  //ShowMessage(IntToStr( PMyMessageStruct(@MyMsgStruct)^.Cmd ));
  SendMessage(FWndHandle,MY_MESS,0,LPARAM(MyMsgStruct));
end;


procedure TForm19.FormCreate(Sender: TObject);
begin
  TMessageThread.Create(Handle);
end;

procedure TForm19.OnMyMessage(var Msg: TMessage);
var
  P: PMyMessageStruct;
begin
  P := PMYMessageStruct(msg.lParam);
  ShowMessage(IntToStr(P^.Cmd));
end;

end.



Добавлено через 3 минуты и 32 секунды
Цитата

Ну это как бы само сабой подразумевается. Взрослому человеку не нужно постоянно напоминать что нужно мыть руки выйдя из туалета smile

New, PostMessage таит в себе теоретические проблемы освобождения памяти т.к. может быть 1) несколько обработчиков на сообщение 2) сообщение может не дойти (RecreateHandle или оно закрылось). В этом случае память будет потеряна - я хотел на всякий случай уберечь человека от такого smile 

Автор: Antony41 19.7.2013, 11:55
Во блин правда)))) вот я парился думал что правда не передается, а оказывается проблема то была в другом совсем)

Добавлено через 3 минуты и 20 секунд
Всё не работало из за того что у меня было так 
Код

procedure OnMyMessage(var Msg: TMsg); message MY_MESS;

а надо 
Код

procedure OnMyMessage(var Msg: TMessage); message MY_MESS;

Автор: northener 19.7.2013, 12:09
Цитата(Illusion Dolphin @  19.7.2013,  11:38 Найти цитируемый пост)
на всякий случай уберечь человека от такого

От сумы и от тюрьмы всё равно не убережешь smile
А SendMessage для многопоточной задачи как серпом по фабержам. Почти как Synchronize(DoWork) smile

Автор: Antony41 19.7.2013, 13:17
Цитата(northener @  19.7.2013,  12:09 Найти цитируемый пост)
А SendMessage для многопоточной задачи как серпом по фабержам. Почти как Synchronize(DoWork)

А PostMessage? я так понимаю поток будет продолжать свои действия и не будет как Synchronize

Автор: northener 19.7.2013, 13:41
Цитата(Antony41 @  19.7.2013,  13:17 Найти цитируемый пост)
А PostMessage? я так понимаю поток будет продолжать свои действия и не будет как Synchronize 

Да. Правильно полагаете. 
Вот http://forum.sources.ru/index.php?showtopic=379928 сейчас обсуждается подобное.

Автор: Antony41 19.7.2013, 14:35
Всем спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)