ActiveX, запись настроек
От: GladiatorX  
Дата: 23.04.12 11:13
Оценка:
На Дельфи написана ActiveX-кнопка с дополнительным свойством Command. Я хочу сохранять значение свойства в файле контейнера через IStorage, IStream или др.
К примеру, контейнером является Excel-документ (файл xls), куда вставляется моя кнопка. Как это реализовать?
Re: ActiveX, запись настроек
От: Vi2 Удмуртия http://www.adem.ru
Дата: 23.04.12 11:38
Оценка:
Здравствуйте, GladiatorX, Вы писали:

GX>На Дельфи написана ActiveX-кнопка с дополнительным свойством Command. Я хочу сохранять значение свойства в файле контейнера через IStorage, IStream или др.

GX>К примеру, контейнером является Excel-документ (файл xls), куда вставляется моя кнопка. Как это реализовать?

Нужно реализовать IPersistXXXX интерфейсы, такие как IPersistStorage, IPersistStream (IPersistStreamInit), IPersistPropertyBag etc. Контейнер запросит тот интерфейс, по которому он умеет сохраняться.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: ActiveX, запись настроек
От: GladiatorX  
Дата: 24.04.12 10:53
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, GladiatorX, Вы писали:


GX>>На Дельфи написана ActiveX-кнопка с дополнительным свойством Command. Я хочу сохранять значение свойства в файле контейнера через IStorage, IStream или др.

GX>>К примеру, контейнером является Excel-документ (файл xls), куда вставляется моя кнопка. Как это реализовать?

Vi2>Нужно реализовать IPersistXXXX интерфейсы, такие как IPersistStorage, IPersistStream (IPersistStreamInit), IPersistPropertyBag etc. Контейнер запросит тот интерфейс, по которому он умеет сохраняться.



Сделал следующее:

TButtonX = class(TActiveXControl, IButtonX, ISpecifyPropertyPages, IPersistStreamInit)
...
// IPersistStreamInit
    function IPersistStreamInit.IsDirty = IPersistStreamInit_IsDirty;
    function IPersistStreamInit_IsDirty: HResult; stdcall;
    function IPersistStreamInit.Load = IPersistStreamInit_Load;
    function IPersistStreamInit_Load(const stm: ActiveX.IStream): HResult; stdcall;
    function IPersistStreamInit.Save = IPersistStreamInit_Save;
    function IPersistStreamInit_Save(const stm: ActiveX.IStream; fClearDirty: BOOL): HResult; stdcall;
    function IPersistStreamInit.GetSizeMax = IPersistStreamInit_GetSizeMax;
    function IPersistStreamInit_GetSizeMax(out cbSize: Largeint): HResult; stdcall;
    function IPersistStreamInit.InitNew = IPersistStreamInit_InitNew;
    function IPersistStreamInit_InitNew: HResult; stdcall;

...

// IPersistStreamInit
function TButtonX.IPersistStreamInit_IsDirty: HResult; stdcall;
begin
  result := S_OK;
end;

function TButtonX.IPersistStreamInit_Load(const stm: ActiveX.IStream): HResult; stdcall;
begin
  result := S_OK;
end;

function TButtonX.IPersistStreamInit_Save(const stm: ActiveX.IStream;
fClearDirty: BOOL): HResult; stdcall;
begin
  result := S_OK;
end;

...


После этого перестали сохраняться и загружаться стандартные свойства кнопки.

Как мне сохранять и считывать все свойства моей кнопки?
Re[3]: ActiveX, запись настроек
От: Vi2 Удмуртия http://www.adem.ru
Дата: 24.04.12 12:20
Оценка:
Здравствуйте, GladiatorX, Вы писали:

GX>После этого перестали сохраняться и загружаться стандартные свойства кнопки.

GX>Как мне сохранять и считывать все свойства моей кнопки?

Что сохранишь, то и поимеешь. Каждый IPersistXXXX имеет свою собственную семантику, и какой из них лучше — хз. Иногда определяется контейнером: именно контейнер определяет тип хранилища. Иногда он сам упаковывает один тип хранилища в другое, чтобы не насиловать сам контрол.

IPersistXXXX.Load загружает из хранилища XXXX данные. Если ты оттуда читать не будешь, значит, свойства контрола будут такими, как при создании контрола. IPersistXXXX.Save сохраняет в хранилище XXXX данные. Если ты туда писать не будешь, значит, и оттуда нечего читать будет.

IPersistStream::Load(IStream *pStm), следовательно, твой контрол должен читать из pStm его методами свои данные, т.е. используя IStream::Read(void *pv, ULONG cb, ULONG *pcbRead). Что-то наподобие:
hr = pStm->Read(&coordX, sizeof(coordX), NULL);
hr = pStm->Read(&coordY, sizeof(coordY), NULL);

IPersistPropertyBag::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog), следовательно, твой контрол должен читать из pPropBag его методами свои свои данные, т.е. используя IPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog). Что-то наподобие:
hr = pPropBag->Read(L"coordX", &v, NULL); coordX присвоить из v;
hr = pPropBag->Read(L"coordY", &v, NULL); coordY присвоить из v;
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: ActiveX, запись настроек
От: Аноним  
Дата: 24.04.12 13:48
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, GladiatorX, Вы писали:


GX>>После этого перестали сохраняться и загружаться стандартные свойства кнопки.

GX>>Как мне сохранять и считывать все свойства моей кнопки?

Vi2>Что сохранишь, то и поимеешь. Каждый IPersistXXXX имеет свою собственную семантику, и какой из них лучше — хз. Иногда определяется контейнером: именно контейнер определяет тип хранилища. Иногда он сам упаковывает один тип хранилища в другое, чтобы не насиловать сам контрол.


Vi2>IPersistXXXX.Load загружает из хранилища XXXX данные. Если ты оттуда читать не будешь, значит, свойства контрола будут такими, как при создании контрола. IPersistXXXX.Save сохраняет в хранилище XXXX данные. Если ты туда писать не будешь, значит, и оттуда нечего читать будет.


Vi2>IPersistStream::Load(IStream *pStm), следовательно, твой контрол должен читать из pStm его методами свои данные, т.е. используя IStream::Read(void *pv, ULONG cb, ULONG *pcbRead). Что-то наподобие:

Vi2>
Vi2>hr = pStm->Read(&coordX, sizeof(coordX), NULL);
Vi2>hr = pStm->Read(&coordY, sizeof(coordY), NULL);
Vi2>

Vi2>IPersistPropertyBag::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog), следовательно, твой контрол должен читать из pPropBag его методами свои свои данные, т.е. используя IPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog). Что-то наподобие:
Vi2>
Vi2>hr = pPropBag->Read(L"coordX", &v, NULL); coordX присвоить из v;
Vi2>hr = pPropBag->Read(L"coordY", &v, NULL); coordY присвоить из v;
Vi2>




При чтении вылетает исключение. Что я сделал не так?


type
  PBtnProps = ^TBtnProps;
  TBtnProps = record
    Caption: string;
  end;

var
  BtnProps: PBtnProps;

function TButtonX.IPersistStreamInit_Load(const stm: ActiveX.IStream): HResult; stdcall;
var
 BytesRead: Longint;
begin
  New(BtnProps);
  try
    stm.Read(BtnProps, SizeOf(TBtnProps), @BytesRead);
    if BytesRead > 0 then
    begin
      ShowMessage('Load=' + BtnProps.Caption);
    end;
  finally
    Dispose(BtnProps)
  end;
  result := S_OK;
end;

function TButtonX.IPersistStreamInit_Save(const stm: ActiveX.IStream; fClearDirty: BOOL): HResult; stdcall;
var
  BytesWrite: Longint;
begin
  ShowMessage('Save=' + FDelphiControl.Caption);
  New(BtnProps);
  try
    BtnProps^.Caption := FDelphiControl.Caption;
    stm.Write(BtnProps, SizeOf(TBtnProps), @BytesWrite);
    if BytesWrite > 0 then
    begin
      ShowMessage('Save=' + IntToStr(BytesWrite));
    end;
  finally
    Dispose(BtnProps)
  end;
  result := S_OK;
end;
Re[5]: ActiveX, запись настроек
От: Vi2 Удмуртия http://www.adem.ru
Дата: 24.04.12 18:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>При чтении вылетает исключение. Что я сделал не так?


Трудно сказать. Язык Дельфи для меня незнакомый. Но навскидку, разве можно писать строки напрямую в файл или поток как в "stm.Read(BtnProps, SizeOf(TBtnProps), @BytesRead);"? В С/С++ нельзя. И структуры со строками тоже нельзя. Поскольку в структуре хранится адрес строки, а не сама строка. Соответственно, при чтении таких данных могут получиться коллизии. Я завтра спрошу у специалиста по Дельфи.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: ActiveX, запись настроек
От: GladiatorX  
Дата: 25.04.12 04:49
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, Аноним, Вы писали:


А>>При чтении вылетает исключение. Что я сделал не так?


Vi2>Трудно сказать. Язык Дельфи для меня незнакомый. Но навскидку, разве можно писать строки напрямую в файл или поток как в "stm.Read(BtnProps, SizeOf(TBtnProps), @BytesRead);"? В С/С++ нельзя. И структуры со строками тоже нельзя. Поскольку в структуре хранится адрес строки, а не сама строка. Соответственно, при чтении таких данных могут получиться коллизии. Я завтра спрошу у специалиста по Дельфи.



Спасибо большое, Vi2!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.