Портировал почти дефолтный пример по работе с DDEML из Visual C++ на Lazarus, с оглядкой на Delphi и вот, что в итоге получилось:
- Код: Выделить всё
program test;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes,
SysUtils,
Windows;
{$R *.res}
const
DMLERR_NO_ERROR = 0;
APPCMD_CLIENTONLY = 10;
var
idInst: DWORD;
function DdeConnect(_para1:DWORD; _para2:HSZ; _para3:HSZ;_para4:PCONVCONTEXT ):HCONV; external 'user32' name 'DdeConnect';
function DdeCallback(CallType, Fmt: UINT; Conv: HConv; hsz1, hsz2: HSZ;
Data: HDDEData; Data1, Data2: DWORD): HDDEData stdcall;
begin
Result := 0
end;
function GetUrlBrowser(NameBrowser: String): String stdcall;
var
iReturn: DWORD;
hszApp, hszTopic, hszItem: HSZ;
hCnv: DWORD;
hData: HDDEDATA;
Buf: String[255];
begin
Result := '';
idInst := 0;
iReturn := DdeInitialize(@idInst, @DdeCallback, APPCMD_CLIENTONLY, 0);
if iReturn = DMLERR_NO_ERROR then
begin
//DDE Connect to Server using given AppName and topic.
hszTopic := 0;
hszApp := 0;
hCnv := 0;
hszApp := DdeCreateStringHandle(idInst, 'FIREFOX', CP_WINANSI);
hszTopic := DdeCreateStringHandle(idInst, 'WWW_GetWindowInfo', CP_WINANSI);
hCnv := DdeConnect(idInst, hszApp, hszTopic, nil);
DdeFreeStringHandle(idInst, hszApp);
DdeFreeStringHandle(idInst, hszTopic);
if hCnv <> 0 then
begin
hszItem := DdeCreateStringHandle(idInst, 'surl', CP_WINANSI);
hData := DdeClientTransaction(nil, 0, hCnv, hszItem, CF_TEXT, XTYP_REQUEST, 5000, nil);
if hData <> 0 then
begin
DdeGetData(hData, @Buf, 255, 0);
//strcopy(Result, PChar(Buf));
Result := Buf;
end;
//DDE Disconnect and Uninitialize.
DdeDisconnect(hCnv);
end;
DdeUninitialize(idInst);
end;
end;
var
slChromeUrl: String;
Process: String;
begin
Process := 'firefox';
slChromeUrl := GetUrlBrowser(Process);
MessageBox(0, PChar(slChromeUrl), 'Caption', 0);
end.
Это должно работать, но программа валится с ошибкой SIGSEGV при возврате из функции GetUrlBrowser, причем если закомментировать строку hCnv := DdeConnect(idInst, hszApp, hszTopic, nil), то программа завершается нормально, но результат ее работы нулевой, естественно.
Правильно WideString использовать, поэтому с нее начинал, а потом уже стал с String мучаться, но эффект тот же самый. Может там с юникодом как-то надо работать? Я уже вообще не знаю, куда рыть. Уже все объявления функций из WinAPI перепроверил. Все правильно. Еще одна деталь: DdeConnect возвращает 0, но DDEGetLastError выдает DMLERR_NO_ERROR (скорее всего вообще ничего не выдает, а код остается после предыдущей функции).