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