Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.118.137.243] |
|
Сообщ.
#1
,
|
|
|
В одном известном примере ole_client_server2 продемонстрирована возможность подключения к серверу через:
- Interface (FIntf := CoAutoTest.Create); - Dispinterface (FDispintf := CreateComObject(Class_AutoTest) as IAutoTestDisp); - OleVariant (FVar := CreateOleObject('Srv.AutoTest')); Причём особой разницы я не заметил, в примере всё работает. Разница появилась, когда я добавил в библиотеку ещё один интерфейс, и в базовом интерфейсе добавил ещё одно свойство: TAutoTest = class(TAutoObject, IAutoTest) protected function Get_EditText: WideString; safecall; function Get_ShapeColor: OLE_COLOR; safecall; procedure Set_EditText(const Value: WideString); safecall; procedure Set_ShapeColor(Value: OLE_COLOR); safecall; function Get_ShapeType: TxShapeType; safecall; procedure Set_ShapeType(Value: TxShapeType); safecall; procedure ShowInfo; safecall; function Get_ButtonInfo: IButtonInfo; safecall; end; TButtonInfo = class(TAutoObject, IButtonInfo) private FCaption: string; protected function Get_Caption: WideString; safecall; procedure Set_Caption(const Value: WideString); safecall; public constructor Create; end; { TAutoTest } function TAutoTest.Get_ButtonInfo: IButtonInfo; begin Result := TButtonInfo.Create; end; { TButtonInfo } constructor TButtonInfo.Create; begin FCaption := ParamStr(0)+' Заголовок'; end; Теперь в клиенте наблюдается такая картина: procedure TControlForm.Button1Click(Sender: TObject); begin case CallViaRG.ItemIndex of 0: Edit.Text := FIntf.ButtonInfo.Caption; 1: Edit.Text := FDispintf.ButtonInfo.Caption; // в этом случае не работает 2: Edit.Text := FVar.ButtonInfo.Caption; // в этом случае не работает end; end; Объясните мне, в чём разница между этими тремя способами, или что я делаю не правильно? Мне необходимо, чтобы в моём случае работало подклчение через OleVariant. Прикреплённый файлole_client_server2.rar (371.4 Кбайт, скачиваний: 148) |
Сообщ.
#2
,
|
|
|
У тебя, скорее всего, IButtonInfo - потомок IUnknown? При позднем связывании не работает (ну не учитывая некоторые особые случаи)
|
Сообщ.
#3
,
|
|
|
Нет, IButtonInfo Parent Interface: IDispatch
Добавлено Попробовал для интереса IButtonInfo сделать потомком от IUnknown - теперь действительно не работает ни один из способов. |
Сообщ.
#4
,
|
|
|
Ну так. С налета не получилось, пришлось покопаться:
1. Почему такое отвращение к вызову inherited Create? Думаешь, совсем-совсем не надо? 2. Для несоздаваемых интерфейсов лучше пользовать TAutoIntfObject. Посему изменения: TButtonInfo = class(TAutoIntfObject, IButtonInfo) ... constructor TButtonInfo.Create; begin inherited Create(COMServer.TypeLib, IButtonInfo); FCaption := ParamStr(0)+' Çàãîëîâîê'; end; 3. Caption - по всей видимости, слово зарезервированное и пересекается. Сменить на btnCaption например. Лезть вглубь и смотреть, что не так - лень 4. DispInterface - если начал, то продолжай запрашивать именно disp, не путай компилятор procedure TControlForm.Button1Click(Sender: TObject); begin case CallViaRG.ItemIndex of 0: Edit.Text := FIntf.ButtonInfo.btnCaption; 1: Edit.Text := (FDispintf.ButtonInfo as IButtonInfoDisp).btnCaption; 2: Edit.Text := FVar.ButtonInfo.btnCaption; end; end; Второй выход - Передавать IDispatch вместо IButtonInfo, тогда запроса dispinterface не надо, зато в случае интерфейса запрашивать... Добавлено Да, и забыл сказать: если хочешь внести инициализацию при создании, то для потомков TComObject (как, например, TAutoObject ) надо перекрвать процедуру initialize. Просто потому что конструкторов несколько, для разных случаев. |
Сообщ.
#5
,
|
|
|
Спасибо, заработало! +
|