Главная arrow В помощь студентам arrow Статьи по программированию в Delphi arrow Блокирование документов при использовании TOleContainer  
21.11.2024 г.
Блокирование документов при использовании TOleContainer Печать E-mail
Автор Administrator   
11.03.2009 г.

Автор: Дамир, Королевство 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 я не исследовал, поэтому, возможно есть другие, более красивые решения.

 
« Пред.   След. »

Ivanovo State University of Chemical Technology has entered into an academic partnership with Visual Paradigm to better facilitate the teaching of software design & modeling through the use of Visual Paradigm.
Enterprise Architect
Sparx Systems Enterprise Arctitect provides Ivanovo State University of Chemical Technology with Enterprise Architect, Eclipse Integration, Visual Studio Integration, SysML Technology, Zachman Framework and much more for use in educational purposes, offered by the Enterprise Architect Academic Site License.