How do I open Word modally from my Delphi app? - delphi

I have a Word document on disk. I want my application to open Word modally, with this file loaded (and resume running when Word is closed)

Option A:
You can open Word using TOleContainer on the form and you show the Form as Modal
Option B:
something like:
EnableWindow(Application.MainForm.Handle, True);
application.Minimize;
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
Application.Restore;
EnableWindow(Application.MainForm.Handle, False);
Application.BringToFront;
c this for more information.

Related

How to open an external App as MDIChild or Modal Dialog in my App as if it is another form of my App

My company has a huge with-delphi-written 3-Million-line-code mostly-database-related Application, and we are responsible to support this program. This Application has a MainForm as fsMDIForm and other forms are fsMDIChild which are created programmatically when they are needed.
In our team, we have worked with other different programming languages like C++, C#, Python, VB, etc. An idea is to make some part of the program with another programming language like C# in Visual Studio and open it in our App.
For example in another C# project in our company we have a form which lets user select a convartable-to-PDF file (such as pictures, documents, ...) with special GUI and convert it to PDF/A for archiving. It allows user to attach multiple PDFs as well. Now the project manager has told us to use this code in our Delphi project. There are many ways to do so, such as making a DLL and call it from Delphi or simply convert it to EXE and call it from Delphi and wait for it to be closed and so on.
Sometimes writing it again in Delphi is the only solution, but it would be great, if I would put such a code in a simple C# project and make an EXE from it, then I run this EXE file as Modal/MDIChild-Form in the Delphi application, as if it is a part of the main App.
What an absolutely bad thing I did:
procedure TEditEmailDlg.btnAttachFileClick(Sender: TObject);
var
tf: string;
begin
tf := TempFolder + 'FCDAA5F7-E26D-4C54-9514-68BDEC845AE3.Finished';
ShellExecute(Handle, 'open', 'C:\Program Files (x86)\GL-K-S\tools\2PDFA.exe', '', '', SW_SHOWNORMAL);
repeat
Sleep(300);
until FileExists(tf);
with TStringList.Create do
begin
LoadFromFile(tf); // Selected and converted filenames
...
end;
...
DeleteFile(tf);
end;
As you see it waits for the App to be closed, but it is not like a MDI form of the project and the project is going to be not respounding.
If it is a good idea, please let me know how can I do it, and if not, why and what is the better solution to prevent rewriting forms and codes behind them in Delphi.
As you have the code of both Delphi (D) and C# or C++ (C) you can do a little modifications on both applications to use either Windows Messages or Shared Memory.
I used Windows Messages 10 years ago, sorry I don't have the code right now.
Windows Messages :
D will send a window handle (WH) to C as a command parameter when running it.
When C finish or any other reason, it will notify D by sending a custom message to WH.
Shared Memory :
D will send the name of shared memory to C as a command parameter when running it.
In both cases C will send back a window handle (WH2) to D, then D will use SetParent() function to make MyForm inside D is the parent for this window WH2.
SetParent(WH2, MyForm.Handle);
MoveWindow(WH2, 0, 0, MyForm.ClientWidth, MyForm.ClientHeight, True);
D will close MyForm when it get a notify message from C telling it that C is about to close.
You may also use GetWindowRect() function to get width and height of WH2 to adjust MyForm size.
var r: TRect;
GetWindowRect(WH2, r);
MyForm.ClientWidth := r.Right - r.Left;
MyForm.ClientHeight := r.Bottom - r.Top;

how to get the selected text from acropdf component to an edit directly with Delphi 7

I study preparing a dictionary programme with delphi. So far I have solved my problems about Word documents but I've got some problem about PDF documents.
I imported and installed the AcroPdf component with Delphi 7 and I want to get the word (or text) which was selected by dblclicking by user from pdf document which was viewed by the ACROPDF component in Delphi. If I can get it I'll send it the dictionary database directly.
If you help me I'll be glad. Thank you...
Remzi MAKAK
The following shows one way to get the selected text from a Pdf document which is
open in Adobe Acrobat Professional (v.8, English version).
Update The original version of this answer neglected to check the Boolean result of calling MenuItemExecute and specified the wrong argument to it. Both these points are fixed in the updated version of this answer. It turned out that the reason the call to MenuItemExecute was failing was that it is essential to call BringToFront on the Acrobat document before trying to copy the text selected in to to the clipboard.
Create a new Delphi VCL project.
In D7's IDE go to Projects | Import Type Library, and in the Import Type Library pop-up, scroll down until you see something like "Acrobat (Version 1.0) in the list of files, and
"TAcroApp, TAcroAVDoc..." in the Class names box. That is the one you need to import. Click the Create unit button/
In the project's main form file
a. Make sure it USES the Acrobat_Tlb.Pas unit from step 2. You may need to add the path to wherever you saved Acrobat_Tlb.Pas to the SearchPath of your project.
b. Drop a TButton on the form, name it btnGetSel. Drop a TEdit on the form and name it edSelection
Edit the source code of your main form unit as shown below.
Set a debugger breakpoint on Acrobat.MenuItemExecute('File->Copy'); Do not set a breakpoint within the GetSelection procedure as this is likely to defeat the call to BringToFront in it.
Close any running instance of Adobe Acrobat. Check in Task Manager that there are no hidden instances of it running. The reason for these step is to make sure that when you run your app, it "talks" to the instance of Acrobat that it starts, not another one.
Compile and run your app. Once the app and Acrobat are open, switch to Acrobat, select some text, switch back to your app and click the btnGetSel button.
Code:
uses ... Acrobat_Tlb, ClipBrd;
TDefaultForm = class(TForm)
[...]
private
FFileName: String;
procedure GetSelection;
public
Acrobat : CAcroApp;
PDDoc : CAcroPDDoc;
AVDoc : CAcroAVDoc;
end;
[...]
procedure TDefaultForm.FormCreate(Sender: TObject);
begin
// Adjust the following path to suit your system. My application is
// in a folder on drive D:
FFileName := ExtractfilePath(Application.ExeName) + 'Printed.Pdf';
Acrobat := CoAcroApp.Create;
Acrobat.Show;
AVDoc := CoAcroAVDoc.Create;
AVDoc.Open(FileName, FileName); // := Acrobat.GetAVDoc(0) as CAcroAVDoc; //
PDDoc := AVDoc.GetPDDoc as CAcroPDDoc;
end;
procedure TDefaultForm.btnGetSelClick(Sender: TObject);
begin
GetSelection;
end;
procedure TDefaultForm.GetSelection;
begin
// call this once some text is selected in Acrobat
edSelection.Text := '';
if AVDoc.BringToFront then // NB: This call to BringToFront is essential for the call to MenuItemExecute('Copy') to succeed
Caption := 'BringToFront ok'
else
Caption := 'BringToFront failed';
if Acrobat.MenuItemExecute('Copy') then
Caption := 'Copy ok'
else
Caption := 'BringToFront failed';
Sleep(100); // Normally I would avoid ever calling Sleep in a Delphi
// App's main thread. In this case, it is to allow Acrobat time to transfer the selected
// text to the clipboard before we attempt to read it.
try
edSelection.Text := Clipboard.AsText;
except
end;
end;

JclMapi - e-mail message window goes underneath the main form

I'm experiencing some troubles with JclMAPI. Currently I'm using JCL 2.6 Build 5178 with Delphi XE3.
The main form of my application is a MDIForm which handles different MDIChild forms. From one of these I can display a modal form and from it I call the JclSimpleBringUpSendMailDialog assigning the ParentWND parameter with the modal form handle.
Normally this method opens the email message window in front of the modal form.
My problem is that sometimes the e-mail message window goes underneath the application mainForm and I'm not able to bring it to the front anymore.
So the application waits for the return value of the Jcl Method and I'm not able to reactivate it. Real problem is that the e-mail window is behind my application and I can't compose the message.
i've had no luck on the internet searching.
Have you ever experienced this problem?
You might want to switch to using the Outlook Object Model instead of Simple MAPI. This way you can bring Outlook's main window to the foreground first before displaying the message. Outlook's HWND can be retrieved by casting the Explorer object (returned buy Application.ActiveExplorer) to IOleWindow and calling IOleWindow.GetWindow. Once you have HWND, you can bring it to the foreground using something like the folloowing:
function ForceForegroundWindow(hWnd: THandle): BOOL;
var
hCurWnd: THandle;
begin
hCurWnd := GetForegroundWindow;
AttachThreadInput(
GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, True);
Result := SetForegroundWindow(hWnd);
AttachThreadInput(
GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, False);
end;

I need an 'Open folder' dialog with possibility to manually enter path

I use FileCtrl.SelectDirectory to show a 'open folder' dialog. However, I am unhappy with it because it doesn't allow the user to enter a path from where to start the browsing.
For example, if the user already has the path in clipboard it should be able to enter it into my dialog instead of wasting 12 seconds to navigate (open) lots of folders until it gets there.
I have found this code which seems to do EXACTLY what FileCtrl.SelectDirectory does. i hopped it will allow me to configure the dialog more. It doesn't.
So, how do I show a editbox in the SelectDirectory where the user can enter the path?
The solution that I have now, is my own dialog box. It is build from zero using TDirectory and TListBox. Very handy. BUT it looks so obsole because it uses Embarcadero's file management controls (TDirectory, TListBox) and we all know how dull they look like.
To make it clear: I would like something like FileCtrl.SelectDirectory but with an extact TEdit or a crumbar where the user can enter its path (if he has any).
Example:
Passing sdShowEdit to FileCtrl.SelectDirectory adds an edit box that you can paste a directory into.
FileCtrl.SelectDirectory('Caption', 'C:\', Dir, [sdNewUI, sdShowEdit]);
If you use the overloaded version of SelectDirectory() that has a Root parameter, it calls SHBrowseForFolder() internally (the other overload displays a custom VCL Win3.1-style dialog instead). If you assign an initial value to the variable that you pass to the Directory parameter, it gets passed to SHBrowseForFolder() as the initial selected folder. You can also specify the sdShowEdit flag in the Options parameter. However, the edit box is not meant for entering full paths. But, if you call SHBrowseForFolder() directly, you can provide your own callback function for it, so when the dialog sends you a BFFM_VALIDATEFAILED event for instance, you can grab the text from the dialog's edit box and send the dialog window a BFFM_SETSELECTION message to navigate to the correct path.
What you are really asking for is the customization provided by the Vista+ IFileDialog dialog instead. You can use the IFileDialogCustomize interface to add custom controls to the dialog, such as edit boxes and buttons, and then implement the IFileDialogControlEvents interface to know when various actions occur on those controls, like button clicks. You can use that to check your custom edit box, or the clipboard, for a valid path and if detected then tell the dialog to navigate to that path via the IFileDialog.SetFolder() method.
TJvDirectoryEdit from Jedi VCS does that. Look it up.
Here are some pictures of it:
If I understand correctly I think this could be your solution.
procedure TForm1.Button1Click(Sender: TObject);
var
opendialog : Topendialog;
begin
openDialog := TOpenDialog.Create(self);
openDialog.InitialDir := GetCurrentDir; {This can also be what is on the clipboard}
openDialog.Options := [ofFileMustExist];
openDialog.Filter := 'Text Document |*.txt'; {This is the type of file the user must open}
openDialog.FilterIndex := 1;
opendialog.execute;
end;
This code creates and shows a simple open dialog.
The path the user then selected is:
opendialog.filename
#davea's answer is ok but it only shows the old (WinXP) dialog style.
So, this is the code I use now. On Win Vista and up it shows the new style dialog and the old style on Win XP:
{$WARN SYMBOL_PLATFORM OFF}
{$IFDEF MSWindows}
function SelectAFolder(VAR Folder: string; CONST Options: TFileDialogOptions= [fdoPickFolders, fdoForceFileSystem, fdoPathMustExist, fdoDefaultNoMiniMode]): Boolean; { Keywords: FolderDialog, BrowseForFolder} { Works with UNC paths }
VAR Dlg: TFileOpenDialog;
begin
{ Win Vista and up }
if OS_IsWindowsVistaUp then
begin
Dlg:= TFileOpenDialog.Create(NIL); { Class for Vista and newer Windows operating systems style file open dialogs }
TRY
Dlg.Options := Options;
Dlg.DefaultFolder := Folder;
Dlg.FileName := Folder;
Result := Dlg.Execute;
if Result
then Folder:= Dlg.FileName;
FINALLY
FreeAndNil(Dlg);
END;
end
else
{ Win XP or down }
Result:= vcl.FileCtrl.SelectDirectory('', ExtractFileDrive(Folder), Folder, [sdNewUI, sdShowEdit, sdNewFolder], nil);
if Result
then Folder:= Trail(Folder);
end;
{$ENDIF}
{$WARN SYMBOL_PLATFORM On}
{ Keywords: FolderDialog, BrowseForFolder}

Delphi DDE Open url in active tab

I want to open url in already existing, active opera/IE/FF tab using delphi.
I tried:
ShellExecute(hw,'open',pchar(url),nil,nil,SW_SHOWNORMAL);
where hw is handle of web browser and url is string variable with url I want to open, but it opens new tab instead of using active tab.
I also tried:
procedure SetURL(Browser, URL: String);
var
Client_DDE: TDDEClientConv;
begin
Client_DDE := TDdeClientConv.Create(nil);
with Client_DDE do
begin
SetLink( Browser, 'WWW_Activate' );
RequestData('0xFFFFFFFF');
SetLink( Browser, 'WWW_OpenURL' );
RequestData(URL);
CloseLink;
end;
Client_DDE.Free;
end;
And SetURL('Opera', url); in buttonclick procedure, but it also opens url in new tab. When I use RequestData(URL + ',-1'); in SetURL procedure then it opens url in new window. Any ideas how to open url in already existing browser tab?
I have Delphi 7.
Unfortunately, that isn't possible. Take a look at similar question: Open link in same browser tab

Resources