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