Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> postmessage в отсутствии окна 
:(
    Опции темы
gonzales
Дата 16.11.2007, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Доброе время суток, уважаемые форумчане!!!
столкнулся с одной задачей, в силу своего ламерства не могу придумать как ее решить.
Суть следующая:
имеется юнит работы с ком-портом, который содержит следующую функцию
Код

//функция дочернего потока, обрабатывающего эвенты порта
//параметр введен для того, чтобы каждый (их стартует два)
//экземпляр работал с переменными "своего" порта
function WorkComm(var Parms : TComVar) : longint; stdcall;
var
  Kols,Mask,Trans,Errs : DWord;
  Ovr : TOverlapped;
  Buff : array [0..511] of byte;
  Modems, LenPacket : DWord;
  Reciv : pointer;
begin
  Result := 0;
//инициализируем TOverlapped структуру
  FillChar(Ovr,SizeOf(TOverlapped),0);
  Ovr.hEvent := CreateEvent(nil,TRUE,FALSE,#0);
//стартуем бесконечный цикл
  while not Parms.Terminated do with Parms do begin
    if Terminated then break;
    Mask := 0;
//запрашиваем (ожидаем) маску эвентов
    if not WaitCommEvent(cId,Mask,@Ovr) then begin
    //обрабатываем "отложенную" операцию ввода-вывода
      if (GetLastError() = ERROR_IO_PENDING) and
         (WaitForSingleObject(Ovr.hEvent,INFINITE)=Wait_Object_0)
        then GetOverlappedResult(cId,Ovr,Trans,False);
    end;
//очищаем ошибки с получением статуса порта, обязательно!!!
    ClearCommError(cId,Errs,@Stat);
    if Terminated then break;
    if Mask = 0  then continue;
    if (Mask and EV_RXCHAR) = EV_RXCHAR then begin
    //если принят хотя бы один байт
        if Stat.cbInQue < 512
         then Kols := Stat.cbInQue
       else Kols := 512;
      if Terminated then break;
    //пытаемся читать принятые байты
      ReadFile(cId,Buff,Kols,Kols,@Ovr);
      if Terminated then break;
      if Kols > 0 then begin
      //если хоть один байт считан - переносим в буфер накопления
        Move(Buff,RecivBuff[CntByte],Kols);
        inc(CntByte,Kols);

          while CntByte >= 1 do begin
//        while CntByte >= sizeof(TPacketHeader) do begin
        //пока количество принятых байт больше длины синхрочасти преамбулы
        //пытаемся засинхронизоваться
//          if Cardinal((@RecivBuff[0])^) = Sync
         if RecivBuff[0] = Sync
           then begin
             if CntByte >= kols
              then begin
              //если синхропосылка стоит вначале накопленного буфера
              //и общая длина принятых байт больше или равна длине
              //преамбулы плюс количество байт, указанное в преамбуле
                LenPacket := kols;

                 //если этот экземпляр потока работает с СОМ1
                 //получаем указатель, переписываем туда все байты пакета
                   GetMem(Reciv,LenPacket);
                   Move(RecivBuff,Reciv^,LenPacket);
                 //шлем сообщение основному потоку
                   PostMessage(fmMain.Handle,cmRxByte,Integer(Reciv),LenPacket);

                //удаляем из накопленного буфера байты обработанного выше пакета
                dec(CntByte,LenPacket);
                Move(RecivBuff[LenPacket],RecivBuff[0],CntByte);
              end
              //в случае неполного принятия пакета (синхропосылка вначале буфера)
              else break;
           end
           else begin
             //в случае, если начало накопленного буфера не содержит
             //синхропосылку, удаляем первый байт со сдвигом всего буфера
             dec(CntByte);
             Move(RecivBuff[1],RecivBuff[0],CntByte);
           end;
    //    end;
        end;
      end;
    end;
    if ((Mask and EV_DSR) = EV_DSR) or
       ((Mask and EV_CTS) = EV_CTS) then begin
      //если случилось изменение модемных линий
        if Terminated then break;
      if Master then begin
        //если этот экземпляр потока работает с СОМ1
        //запрашиваем текущее состояние модемных линий
        GetCommModemStatus(cId,Modems);
        //получаем указатель
        GetMem(Reciv,sizeof(TModems));
        //заполняем указатеь
        TModems(Reciv^).DSR := (Modems and MS_DSR_ON) = MS_DSR_ON;
        TModems(Reciv^).CTS := (Modems and MS_CTS_ON) = MS_CTS_ON;
        //шлем сообщение основному потоку
        PostMessage(fmMain.Handle,cmModem,Integer(Reciv),0);
      end;
    end;
  end;
  CloseHandle(Ovr.hEvent);
end;


как видно из описания в начале функции это функция дочернего потока, обрабатывающего эвенты порта, которая передает данные основному потоку через
Код

PostMessage(fmMain.Handle,cmRxByte,Integer(Reciv),LenPacket);
  

и вроде все правильно и все работает. Но тут мне захотелось все это удовольствие запихнуть в длл, соответственно формы fmMain, которой передается сообщение нет!!!
и тут загвоздка, как передать в основной поток (если я правильно выражаюсь) данные????


--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Lexicss
Дата 16.11.2007, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 16.8.2006
Где: Беларусь, Минск

Репутация: нет
Всего: 1



Могу, конечно, и ошибаться, но по-ходу никак. 
Сообщения ведь могут принимать либо окна, либо потоки. 
Раз нет окна, попробуй созадать поток-обработчик.
--------------------
Бери от жизни всё.
PM MAIL WWW ICQ Skype   Вверх
gonzales
Дата 16.11.2007, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



ну ведь можно же наверное послать сообщение типа всем всем всемsmile))
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Lexicss
Дата 16.11.2007, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 197
Регистрация: 16.8.2006
Где: Беларусь, Минск

Репутация: нет
Всего: 1



Можно. smile
Но примут их только те объекты у которых есть Handle, ИМХО.
--------------------
Бери от жизни всё.
PM MAIL WWW ICQ Skype   Вверх
ama_kid
Дата 16.11.2007, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 15
Всего: 95



Цитата(gonzales @  16.11.2007,  17:29 Найти цитируемый пост)
как передать в основной поток (если я правильно выражаюсь) данные?
Основной поток будет содержать окно? Вот и вызывай после LoadLibrary (но перед началом основной работы) функцию инициализации с передачей в dll хендла главного окна и потом пуляй уже в него сообщениями сколько влезет... Хотя имхо правильнее структура, когда приложение, использующее библиотеку, само забирает необходимые данные...



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
MetalFan
Дата 17.11.2007, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



callback функция?


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
dumb
Дата 17.11.2007, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 13
Всего: 158



Код

var
  hWndMain: HWND;
...
  hWndMain := FindWindow("TfrmMain", "caption главной формы");

PM MAIL   Вверх
gonzales
Дата 19.11.2007, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Цитата

Основной поток будет содержать окно?

если бы основной поток содержал окно, то вопросов бы не было.

Цитата

callback функция?


а можно подробнее
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
ama_kid
Дата 19.11.2007, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 15
Всего: 95



Цитата(gonzales @  19.11.2007,  10:55 Найти цитируемый пост)
если бы основной поток содержал окно, то вопросов бы не было.
Из изначального поста следует как раз, что окно существует  smile (основное окно юзающего dll приложения, т.к. ты просто захотел функциональность работы с COM-портом переместить в dll)...

Цитата(gonzales @  19.11.2007,  10:55 Найти цитируемый пост)
Цитата(MetalFan @  17.11.2007,  00:16 Найти цитируемый пост)
callback функция? 
а можно подробнее 
Утрированно: callback-функция - это функция, вызов которой осуществляется неявно... в твоем случае - это некая функция, адрес которой ты можешь передать в dll, и уже в библиотеке её вызывать, тем самым заставляя выполняться функцию основного потока из нутра dll... В качестве примера:
Код
library Project2;

uses
  SysUtils,
  Classes;

type
 TCallBackFunc = procedure (Buf:ShortString);    stdcall;
var
 MyVar:integer = 0;
 CallBackFunc:TCallBackFunc = nil;
{$R *.res}

procedure SetCallBack(P:TCallBackFunc); stdcall;
begin
 CallBackFunc:=P;
end;

procedure ExportedFunc; stdcall;
begin
 Inc(MyVar);
 if Assigned(CallBackFunc) then
  CallBackFunc(IntToStr(MyVar));
end;

exports
 SetCallBack,
 ExportedFunc;
begin
end.

Код
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
const
 LibName = 'Project2.dll';
type
 TSetCallBack = procedure (P:Pointer); stdcall;
 TDllFunc = procedure;    stdcall;


  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  h:THandle;
  hSetCallBack:Pointer;
  hExportedFunc:Pointer;

implementation

{$R *.dfm}
procedure MyCallBackFunction(Buf:ShortString); stdcall;  // Вызываемая из Dll callback-функция
begin
 ShowMessage(Buf);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
 h:=LoadLibrary(LibName);
 if h=0 then
  begin
   MessageBox(0,'Failed to Load','!!!',0);
   exit;
  end;
 hSetCallBack:=GetProcAddress(h,'SetCallBack');
 if (hSetCallBack<>nil) then
   TSetCallBack(hSetCallBack)(@MyCallBackFunction);    // Здесь передаем в библиотеку адрес callback-функции
 hExportedFunc:=GetProcAddress(h,'ExportedFunc');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 if (hExportedFunc<>nil) then
   TDllFunc(hExportedFunc);   // вызываем библиотечную функцию, которая в свою очередь вызовет нашу callback-функцию MyCallBackFunction;
end;
end.



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
gonzales
Дата 19.11.2007, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



спасибо за пример, буду разбираться. Идею я уловил. 

PS. Я ничего не передаю в основную форму, которая конечно же есть. Библиотека - это плагин, от которого в основное приложение идут только функции, заложенные в основное приложение. А дочерний и первичный поток идут в самой длл, просто в разных юнитах
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0572 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.