Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #16  
Старый 11.03.2012, 04:41
meneo meneo вне форума
Прохожий
 
Регистрация: 10.03.2012
Сообщения: 6
Репутация: 10
По умолчанию

да, пример рабочий.
нужно чтобы программа А подгружала длл и вызывала в длл sendmessage окну программы B.
у вас программа А и B в одном - test.
Ответить с цитированием
  #17  
Старый 11.03.2012, 18:48
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Да, в разных процессах (ДЛЛ в процессе A, окно в процессе B) вроде не заработает. Придется копировать структуру.
ЗЫЖ в одном процессе не стоит передавать адрес локальной структуры: структура будет в стеке, и в теории может затереться до приема её окном (хотя на практике шанс конечно стремится к нулю, но отличен от нуля; а по закону Мерфи это значит, что в самый неподходящий момент она затрётся). Лучше сделать глобальную структурку, или же выделить под нее память.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 11.03.2012 в 19:14.
Ответить с цитированием
  #18  
Старый 11.03.2012, 19:19
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Код:
Form1:=TForm.Create;
Form1.Show();...
Я бы такие вещи (расширение интерфейса) писал на WinAPI. Если расширение не требует каких-то очень сложных графиков, красивых нестандартных кнопок и т.д., то на WinAPI написать сие будет очень просто. Работа с VCL не прозрачна, в отличие от WinAPI, и найти ошибку там может быть весьма сложно.

Хотя я как-то писал вроде формочку, которая была целиком в DLLке. Никаких проблем не возникало. Поищу, может найду.

UPD: нашел. Писал так:
Код:
Form2 := TForm2.Create(Ctrl^);
Windows.SetParent(Form2.Handle, Ctrl^.Handle);
Windows.SetWindowPos(Form2.Handle, 0, 0, 0, Ctrl^.Width, Ctrl^.Height, 0);
Form2.BorderStyle := bsNone;
Form2.Show;
Где Ctrl мне передавался как указатель на TControl, хотя можно и без него обойтись (форма встраивалась в главную, поэтому в парент ставился тот самый контрол). Сама форма создавалась кажется визуально.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 11.03.2012 в 19:31.
Ответить с цитированием
  #19  
Старый 11.03.2012, 21:20
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Цитата:
Сообщение от Bargest
...ЗЫЖ в одном процессе не стоит передавать адрес локальной структуры: структура будет в стеке, и в теории может затереться до приема её окном (хотя на практике шанс конечно стремится к нулю, но отличен от нуля; а по закону Мерфи это значит, что в самый неподходящий момент она затрётся). Лучше сделать глобальную структурку, или же выделить под нее память.
Для SendMessage потери не будет, а вот PostMessage очень дружит с Мерфи. Косвенное описание почему так происходит имеется в справке.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #20  
Старый 11.03.2012, 23:10
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Оказывается, SendMessage блокирующий. Не знал, спасибо.
Тогда согласен, локальные юзать можно в одном процессе.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #21  
Старый 12.03.2012, 00:30
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Вариация, использующая WM_COPYDATA:

Вызывающее приложение
Код:
program Test;

uses
  Windows, Messages;

type
  TSetMessage	= procedure; stdcall;

const
  szAppName     = 'MainForm';
  szCaptionName = 'test';

var
  Window        : HWND;
  Msg           : TMsg;
  WndClass      : TWndClassEX;
  SizeX, SizeY  : Integer;
  hDll		: HMODULE;
  hBtn		: HWND;

  SetMessage	: TSetMessage;

//---------------------------------------------------------

procedure InitApp(Wnd : HWND);
begin
  hDLL := LoadLibrary(PChar('mydll.dll'));
  if hDLL = 0 then
    Exit;

  @SetMessage := GetProcAddress(hDLL, 'SetMessage');
  if Addr(SetMessage) = NIL then
    Exit;

  hBtn := CreateWindow('BUTTON', 'Жми', WS_CHILD or WS_VISIBLE, 280, 400, 80, 25, Wnd, 100, hInstance, NIL);
end;

//---------------------------------------------------------

procedure DeInitApp(Wnd : HWND);
begin
  DestroyWindow(hBtn);

  if hDll <> 0 then
    FreeLibrary(hDLL);
end;

//---------------------------------------------------------

function MainProc(Wnd : HWND; Msg : Integer;  wParam, lParam : Longint) : Integer; stdcall;
begin
  Result := 0;

  case Msg of
    WM_CREATE : InitApp(Wnd);

    WM_COMMAND :
    case LOWORD(wParam) of
      100 :
      if hDll <> 0 then
        SetMessage;
    end;
    
    WM_CLOSE :  DestroyWindow(Wnd);

    WM_DESTROY :
    begin
      DeInitApp(Wnd);
      PostQuitMessage(0);
      Exit;
    end;
  end;
  Result := DefWindowProc(Wnd, Msg, wParam, lParam);
end;

//---------------------------------------------------------

begin
  SizeX := 640;
  SizeY := 480;

  FillChar(WndClass, SizeOf(TWndClassEx), 0);
  WndClass.cbSize        := SizeOf(TWndClassEx);
  WndClass.style         := CS_HREDRAW or CS_VREDRAW;
  WndClass.lpfnWndProc   := @MainProc;
  WndClass.cbClsExtra    := 0;
  WndClass.cbWndExtra    := 0;
  WndClass.hInstance     := hInstance;
  WndClass.hCursor       := LoadCursor(0, IDC_ARROW);
  WndClass.hbrBackGround := GetSysColorBrush(COLOR_BTNFACE);
  WndClass.lpszClassName := szAppName;

  if RegisterClassEx(WndClass) = 0 then
    Halt(255);

  Window := CreateWindowEx(0, szAppName, szCaptionName,
                           WS_DLGFRAME or WS_SYSMENU or WS_MINIMIZEBOX,
                           0, 0, SizeX, SizeY, 0, 0, hInstance, NIL);

  ShowWindow(Window, SW_SHOW);

  while(GetMessage(Msg, 0, 0, 0)) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
  Halt(Msg.wParam);
end.

Получающее приложение
Код:
program Main;

uses
  Windows, Messages;

const
  szAppName     = 'SuperMainForm';
  szCaptionName = 'test';

var
  Window        : HWND;
  Msg           : TMsg;
  WndClass      : TWndClassEX;
  SizeX, SizeY  : Integer;

//---------------------------------------------------------

function MainProc(Wnd : HWND; Msg : Integer;  wParam, lParam : Longint) : Integer; stdcall;
var
  cds : PCOPYDATASTRUCT;
  St  : AnsiString;
  Buf : array[Word] of AnsiChar;
begin
  Result := 0;

  case Msg of
    WM_COPYDATA :
    begin
      cds := PCopyDataStruct(lParam);
      if (cds^.dwData = DWORD($12345678)) then
      begin
        lstrcpynA(@Buf[0], cds^.lpData, cds^.cbData);
        SetString(St, Buf, cds^.cbData);
        if St <> '' then
          MessageBox(Wnd, PChar(St), '', MB_OK);
      end;
    end;

    WM_CLOSE : DestroyWindow(Wnd);

    WM_DESTROY :
    begin
      PostQuitMessage(0);
      Exit;
    end;
  end;
  Result := DefWindowProc(Wnd, Msg, wParam, lParam);
end;

//---------------------------------------------------------

begin
  SizeX := 320;
  SizeY := 240;

  FillChar(WndClass, SizeOf(TWndClassEx), 0);
  WndClass.cbSize        := SizeOf(TWndClassEx);
  WndClass.style         := CS_HREDRAW or CS_VREDRAW;
  WndClass.lpfnWndProc   := @MainProc;
  WndClass.cbClsExtra    := 0;
  WndClass.cbWndExtra    := 0;
  WndClass.hInstance     := hInstance;
  WndClass.hCursor       := LoadCursor(0, IDC_ARROW);
  WndClass.hbrBackGround := GetSysColorBrush(COLOR_BTNFACE);
  WndClass.lpszClassName := szAppName;

  if RegisterClassEx(WndClass) = 0 then
    Halt(255);

  Window := CreateWindowEx(0, szAppName, szCaptionName,
                           WS_DLGFRAME or WS_SYSMENU or WS_MINIMIZEBOX,
                           800, 0, SizeX, SizeY, 0, 0, hInstance, NIL);

  ShowWindow(Window, SW_SHOW);

  while(GetMessage(Msg, 0, 0, 0)) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
  Halt(Msg.wParam);
end.

dll
Код:
library mydll;

uses
  Windows, Messages;

const
  St = 'Hello World';

procedure SetMessage; stdcall; export;
var
  Wnd : HWND;
  cds : COPYDATASTRUCT;
begin
  Wnd := FindWindow('SuperMainForm', NIL);
  if Wnd <> 0 then
  begin
    cds.dwData := $12345678;
    cds.lpData := @St[1];
    cds.cbData := Length(St) + 1;
    SendMessage(Wnd, WM_COPYDATA, 0, DWORD(@cds));
  end
  else
    MessageBox(0, 'fail', 'Error', MB_OK);
end;

exports
  SetMessage;

begin
end.

Кроме передачи через WM_COPYDATA, можно также использовать:
1. Обмен через файлы
2. Каналы передачи данных Pipe
3. Каналы передачи данных Mailslot

Добавлено:
Статью с примерами, можно прочитать здесь.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.

Последний раз редактировалось angvelem, 12.03.2012 в 00:45.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:56.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter