(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
Enterprise Connectors (1 Year term)
Delphi Professional Named User
IBM Domino Enterprise Server Processor Value Unit (PVU) License + SW Subscription & Support 12 Months
Quest Software. Toad for SQL Server Development Suite
Microsoft 365 Business Standard (corporate)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Работа в Windows и новости компании Microsoft
ЕRP-Форум. Творческие дискуссии о системах автоматизации
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100