(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Блокирование документов при использовании TOleContainer.

Источник: delphikingdom

Автор: Дамир, Королевство Delphi

Всем известно, что при использовании OleContainerа блокируются ранее открытые документы, и невозможно с ними ничего сделать. Недавно встал вопрос: хорошо бы иметь возможность как-то разблокировать эти документы. Я по привычке полез в VCL и вот что нашел: У объекта TOleContainer имеется внутренняя переменная FDocView, указывающая на интерфейс IOleDocumentView и инициализирующаяся в начале активизации OleContainerа:

TOleContainer = class(TCustomControl, IUnknown, IOleClientSite,
  IOleInPlaceSite, IAdviseSink, IOleDocumentSite, IOleUIObjInfo)
  private

    FDocView: IOleDocumentView;

В свою очередь, у интерфейса IOleDocumentView есть метод Show(fShow: BOOL):

IOleDocumentView = interface(IUnknown)
    ['{b722bcc6-4e68-101b-a2bc-00aa00404770}']

    function Show(fShow: BOOL):HResult; stdcall;

Для "оживления" заблокированных документов, достаточно вызвать этот метод с параметром "false". Добавляем процедуру (или функцию с возможностью обработки ошибок, кому как больше нравится) ShowView(fShow : boolean) в TOleContainer:

public
    procedure ShowView(fShow : boolean); // Добавляем новую процедуру

и реализацию:

procedure TOleContainer.ShowView(fShow : boolean);
begin
  if Pointer(FDocView) <> nil then
  FDocView.Show(fShow);
end;

Для демонстрации работы создадим MDI приложение. Пусть дочернее окно содержит компонент OleContainer1 (Модуль, где находится новый класс TOleContainer я назвал OleCtnrs_):

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtnrs_, StdCtrls, ExtCtrls, ExcelXP, ActiveX;

type
  TForm2 = class(TForm) //ChildForm
    procedure FormCreate(Sender: TObject);
  private
    OleContainer1: TOleContainer;
  public
    { Public declarations }
    procedure OpenFile(FileName : string);
    procedure DoDocShow;
    procedure DoHideView;
  end;

var
  Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

{Здесь открываем документ}
procedure TForm2.OpenFile(FileName : string);
begin
 OleContainer1.CreateObjectFromFile(FileName, false);
 DoDocShow;
end;

{Здесь вызываем ShowView }
procedure TForm2.DoHideView;
begin
 OleContainer1.ShowView(false);
end;

{Здесь снова активизируем OleContainer}
procedure TForm2.DoDocShow;
begin
 OleContainer1.DoVerb(ovShow);
end;

{Здесь создаем новый объект OleContainer}
procedure TForm2.FormCreate(Sender: TObject);
begin
 OleContainer1 := TOleContainer.Create(Self);
 OleContainer1.Parent := Self;
 OleContainer1.Align := alClient
end;
end.

Далее пишем родительское окно:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, OleCtnrs;

type
  TForm1 = class(TForm) //MDIForm
    GroupBox1: TGroupBox; // (Align := allBottom)TGroupBox, потому, что он не перекрывается дочерним окном.
    Button1: TButton; //Ставим кнопку на GroupBox1
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    {Испробовал всякие события, остановился на этих}
    procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure WMKillFocus(var Message: TWMSetFocus); message WM_KILLFOCUS;
  private
    { Private declarations }
    function GetViewActive : boolean;

  public
    { Public declarations }
    property ViewActive : boolean read GetViewActive;
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

function TForm1.GetViewActive : boolean;
begin
 result := MDIChildCount <> 0;
end;

procedure TForm1.WMKillFocus(var Message: TWMSetFocus);
begin
 if ViewActive then
 begin
  TForm2(MDIChildren[0]).DoDocShow;
 end;
 inherited;
end;


procedure TForm1.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin

 if ViewActive then
 begin
  TForm2(MDIChildren[0]).DoHideView;
 end;
 inherited;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
 if OpenDialog1.Execute then
 begin
  with TForm2.Create(Application) do
  begin
   Visible := true;
   OpenFile(OpenDialog1.FileName);
  end;
 end;
end;

end.

Программа работает следующим образом: Открывается, например, документ Excel. Затем запускается программа и открывается другой документ Excel, но уже внутри OleContainerа. При переключении между Excelем и программой появляется возможность работы с этими документами.

Программа работает со скрипом и скрежетом, но позволяет передавать фокус заблокированным документам. Может кому-то и пригодится. Остальные методы интерфейса IOleDocumentView я не исследовал, поэтому, возможно есть другие, более красивые решения.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 05.03.2009 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Delphi Professional Named User
Enterprise Connectors (1 Year term)
Oracle Database Personal Edition Named User Plus License
IBM RATIONAL Clearcase Floating User From Rational Clearcase Lt Floating User Trade Up License + Sw Subscription & Support 12 Months
Купить, скачать Dr.Web Security Space, 1 год, 1 ПК
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Вопросы и ответы по MS SQL Server
Программирование на Visual С++
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100