I use ShellExecuteEx to open a MS Word document and get its handle. How can I use the handle to close the document? Thanks?
CodePudding user response:
You can connect to running MSWORD COM object and use the API to find the document you want to close and close it using the same API. Here an simple example showing how to close the active document:
unit VclWordComObjectDemoMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
System.Win.ComObj, Word_TLB;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
MsWord: _Application;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
SaveChanges : OleVariant;
OriginalFormat : OleVariant;
RouteDocument : OleVariant;
begin
try
MsWord := GetActiveOleObject('Word.Application') as _Application;
except
Memo1.Lines.Add('Word is not already open or no document is open.');
Exit;
end;
Memo1.Lines.Add('Connected to Word.');
SaveChanges := wdDoNotSaveChanges;
OriginalFormat := EmptyParam;
RouteDocument := EmptyParam;
MsWord.ActiveDocument.Close(SaveChanges,
OriginalFormat,
RouteDocument);
end;
end.
Word_TLB is obtained by importing Microsoft Word type library (Delphi / Menu / Component / Import component / Import a type library. Then select Microsoft Word in the list of type libraries. Then select Create a unit and add it to your project.
CodePudding user response:
You can save the windows handle to a global variable, and then use the 'TerminateProcess' to terminate whatever you have executed.
Try this code for example:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, ShellApi;
type
TForm2 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
SEInfo: TShellExecuteInfo;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
var
ExecuteFile: string;
//ParamString, StartInString: string;
begin
ExecuteFile:='C:\Windows\System32\notepad.exe';
FillChar(SEInfo, SizeOf(SEInfo), 0);
SEInfo.cbSize := SizeOf(TShellExecuteInfo);
with SEInfo do
begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Application.Handle;
lpFile := PChar(ExecuteFile);
//lpParameters := PChar(ParamString);
{ParamString can contain the application parameters.}
//lpDirectory := PChar(StartInString);
{StartInString specifies the name of the working directory.
If ommited, the current directory is used.}
nShow := SW_SHOWNORMAL;
end;
if ShellExecuteEx(@SEInfo) then
begin
ShowMessage('Notepad started.');
end
else
ShowMessage('Error starting Notepad!');
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
TerminateProcess(SEInfo.hProcess,0);
end;
end.
- You have to put 'ShellApi' to uses units.
- You have to declare as a global variable the 'SEInfo: TShellExecuteInfo;' where you will save the Window Handle, of the executed process.
- Button1 will start the notepad.exe process.
- Button2 will terminate the notepad.exe process you have opened with button1 (not the other notepad.exe processes you may have open to this computer)