How to create an application that opens when you drag a file onto it

Lots of applications and programs allow you to open them by dragging a file onto the application icon. The application will then open and load the file you dragged on.

It is quite simple to add this behavior to your LiveCode standalones. In this lesson we will show you how to create a standalone that displays a text file in a field when you drag a text file onto the standalone.

You can download the sample stack from this url: https://tinyurl.com/yaed6zn3

Creating our stack

Creating our stack

Firstly lets create a very simple stack, all we need is a scrolling field which we will use to display the contents of our text file.

Getting the filename on Windows

Windows standalones start up automatically when a file is dropped on to them. We use the $ keyword to get the name of the file that is dropped onto the standalone. The $ is used to indicate an environment variable on Unix systems and a command-line parameter on Unix or Windows systems.

In this case we will use $1, when a file is dropped onto the standalone $1 contains the path to that file.

We will handle the startup message to retrieve the file name. The startup message is sent to the stack when the application opens. To start we just want to check we are successfully getting the filename so we add this handler to the stack script:

on startup
   put $1 into field "display"
end startup

Building a standalone

Building a standalone

We need to build a standalone to test our startup handler.

Open the Standalone Application Settings from the File menu and choose OS X and Windows to build for. Leave all the other settings at the defaults.

Then close the Standalone Application Settings and choose Save as Standalone Application from the File menu then choose where you want to build your standalone.

Testing the standalone

Testing the standalone

Now go to the folder your standalone application was built in and open the Windows folder, now try dragging a text file onto Text Display.exe. The application will open and the path to the file you dragged on will be displayed in the field.

Loading the text file

Loading the text file

We don't just want to display the file name though, we want to display the contents of the file so we need to include a handler that will put the contents of our file into the field. At this stage we also want to check that the file is a text file before we display it as our startup handler will accept any type of file.

on startup
	local tFileName
   
	put $1 into tFileName
	loadFile tFileName
end startup

on loadFile pFileName
	## Check that is is a text file
	if char -4 to -1 of pFileName is ".txt" then
		## We use the URL keyword to get the contents of the file 
		put URL ("file:" & pFileName) into field "display"
	end if
end loadFile

The build the standalone and test it again.

Getting the filename on Mac

On Mac we can't use the $ keyword to get the filename, instead we need to handle the appleEvent message. This message is sent to the current card whenever the application receives an Apple event.

We check what type of appleEvent we get, if it is an open document event then we call our loadFile handler.

on appleEvent pClass, pEventID, pSender
   if pClass is "aevt" then
      ## This is an apple event
      ## We request the data about the apple event
           
      request appleEvent data
      put it into tFileName
           
      if pEventID is "odoc" then
         ## This is an open document event
         loadFile tFileName
      end if
   end if
   pass appleEvent   
end appleEvent

Accepting text files on Mac

There is another step we need to take in order for our Mac standalone to accept text files. We need to modify the preferences file within the application bundle to specify the file types our application accepts, in this case it is only text files.

Within the application bundle go into the Contents folder and open the info.plist file. You can use a text editor or a plist editor.

We need to add an extra CFBundleTypeExtensions entry stating that the app can open text files. Add

<dict>
	<key>CFBundleTypeExtensions</key>
		<array>
			<string>txt</string>
		</array>
	<key>CFBundleTypeIconFile</key>
	<string>generic.icns</string>
	<key>CFBundleTypeName</key>
	<string>IMG Disk Image</string>
	<key>CFBundleTypeRole</key>
	<string>Viewer</string>
</dict>

after the automatic CFBundleTypeExtensions created by the standalone builder. This states the application can accept files with the extension txt.

If you want your application to accept other file types you need to add a CFBundleTypeExtensions entry for each allowed type.

 

9 Comments

Nicholas Lucia

You can also use this to pass these variables from OS X command line. In this example, with a single display field and a script to handle $1; in OS X, just issue...

open .app --args "This is what I want to show up in that nifty display field"

Matthias Rebbe

What do i have to enter if i want my application to accept all file types? Is there something like a wildcard i can use?

kee nethery

What macOS sandbox permissions allow LiveCode to actually open the text file that has been dropped onto the app? In my experience, this code works until you sign your macOS app and then it ceases to function. The sandbox doesn't recognize that the user dragged the file onto the app to open it.

Jon Adams

I am trying to use this to get the filepath of an associated file being sent from another app. Every time I get a new instance of my app running. I want to catch message, not open a new instance of my app and do something with the file? is there another better message to watch for? -Thanks

Elanor Buchanan

Hi Jon

If all you need is the filepath you could just use a field, if a file is dropped onto a LiveCode field the default behavior is to display the path in the field.

If you want to get the filepath without displaying it in the field you can handle the dragDrop message in the field script

on dragDrop
answer the dragData["files"]
end dragDrop

I hope that helps.

Kind regards

Elanor

Jon Adams

Thanks for the help! I'm actually trying to get EOS Utility (Canon Camera Software) to use my app as a linked app to open newly downloaded camera files. I only need the filename. I've got it working on Windows using on startup with $1 and on relaunch. Now on the mac. If I use an on appleEvent it gives me the path when dropping an image on the standalone icon, or when associating the file from the finder, but EOS Utility gives me an error "The application can't be launched" So I'm missing something in communicating through apple events somehow. Here's what I've been playing with. Is there another way to do something like this?
Thanks

on appleEvent pClass, pEventID, pSender
if pClass is "aevt" then
request appleEvent data
put it into tFilename
put tfilename into field "Field1"
if pEventID is "odoc" then
put tfilename after field "display"
end if
end if
pass appleEvent
end appleEvent

Elanor Buchanan

Hi Jon

I wonder if the EOS Utility doesn't see your app as something 'allowed' to open files.

Can you check if the appleEven is received by your app and what the values of the parameters are, something like

on appleEvent pClass, pID, pSender
answer pClass & return & pID & return & pSender
end appleEvent

If the app is not receiving the apple event it may be that it needs to be linked to the EOS Utility somehow, perhaps there is a setting in the Preferences?

Kind regards

Elanor

Simon

Editing the file info.plist is little ugly and slows the RAD process. File types associated with the app may be added in the standalone settings see jacque post here : https://forums.livecode.com/viewtopic.php?t=31441 for full details or just add file extensions as a comma list into the field "document extension" e.g. jpg, jpeg, txt .
Thanks to Jacque for the information.
best wishes
Simon

Mark

Thanks Simon. That advice worked for me. Although, since I added .plist as a file extension I had to provide my own input routine to handle an xml file. Still, it avoided having to edit the apps info.plist.

Add your comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.