Proxy Icons

Proxy icons, those icons that appear in the title bar of a window, are not exposed in the REALbasic Window class. As it turns out, it is simple to add support for proxy icons.

Setting a Proxy Icon

When a window contains a document that has not yet been saved to a file, it's still good to show a proxy icon for consistency. To do so, you use the function SetWindowProxyCreatorAndType.

OSStatus SetWindowProxyCreatorAndType ( WindowRef window, OSType fileCreator, OSType fileType, SInt16 vRefNum );

The vRefNum parameter allows you to specify a volume containing the desktop database to search for the icon. You can set it to 0 to specify the boot volume, or you can pass the constant kOnSystemDisk = -32768 to signify that the volume is unknown.

We wrap this function into a method that extends the Window class.

Sub SetProxyIcon(Extends w as Window, creator as String, type as String) Const kOnSystemDisk = -32768 Declare Function SetWindowProxyCreatorAndType Lib WindowsLib (inWindow as WindowPtr, fileCreator as OSType, fileType as OSType, vRefNum as Short) as Integer dim OSError as Integer = SetWindowProxyCreatorAndType(w, creator, type, kOnSystemDisk) End Sub

For documents that don't have a creator and type, or if you want to set the proxy icon for other reasons, there is SetWindowProxyIcon.

OSStatus SetWindowProxyIcon ( WindowRef window, IconRef icon );

I will discuss Macintosh icons later, and show how to get icons from various sources. For now, I note that you declare a parameter of type IconRef as Integer.

Declare Function SetWindowProxyIcon Lib WindowsLib (window as WindowPtr, icon as Integer) as Integer

You can attach a file to a window, then use SetProxyIcon to display a different icon while preserving the file attachment.

The function GetWindowProxyIcon returns a reference to the current proxy icon.

OSStatus GetWindowProxyIcon ( WindowRef window, IconRef * outIcon );

Declare Function GetWindowProxyIcon Lib WindowsLib (window as WindowPtr, ByRef outIcon as Integer) as Integer

Note that you must release the IconRef reference when finished with it using the Icon Services function ReleaseIconRef.

Attaching Files

The main purpose of a proxy icon is to represent a file associated to a document window. In Carbon applications, you get all of the standard proxy icon behavior for free, including the ability to drag and drop the proxy icon and the window path popup menu.

To attach and remove files, we'll also need to use File Manager and Alias Manager functions. For File Manager functionality, we'll use classes developed in the next chapter. The Alias Manager functions take AliasHandle parameters. The creation of handles allocates memory which shoud be released. We do so using the Memory Manager function DisposeHandle.

The function SetWindowProxyAlias attaches a file to a window using an alias.

OSStatus SetWindowProxyAlias ( WindowRef inWindow, AliasHandle inAlias );

The function RemoveWindowProxy detaches a file from a window.

OSStatus RemoveWindowProxy ( WindowRef window );

We wrap both functions into a method that attaches a file to a window.

Sub DocumentFile(Extends w as Window, Assigns f as FolderItem) Soft Declare Function FSNewAlias Lib CarbonFramework (fromFile as Integer, target as Ptr, ByRef inAlias as Integer) as Short Soft Declare Function NewAlias Lib InterfaceLib (fromFile as Integer, target as Ptr, ByRef inAlias as Integer) as Short Declare Function SetWindowProxyAlias Lib WindowsLib (inWindow as WindowPtr, inAlias as Integer) as Integer Declare Function RemoveWindowProxy Lib WindowsLib (inWindow as WindowPtr) as Integer Declare Sub DisposeHandle Lib InterfaceLib (h as Integer) Const Null = 0 If f is Nil then dim OSError as Integer = RemoveWindowProxy(w) Else dim aliasHandle as Integer dim fileRef as MemoryBlock dim OSError as Integer If System.IsFunctionAvailable("FSNewAlias", CarbonFramework) then OSError = FSNewAlias(Null, new FSRef(f), aliasHandle) ElseIf System.IsFunctionAvailable("NewAlias", CarbonFramework) then fileRef = new FSSpec(f) OSError =NewAlias(Null, fileRef, aliasHandle) Else //the impossible has happened; you might want to log it Return End if If OSError <> 0 then Return End if OSError = SetWindowProxyAlias(w, aliasHandle) If aliasHandle <> 0 then DisposeHandle aliasHandle aliasHandle = 0 End if End if End Sub

You can get an alias to the attached file with GetWindowProxyAlias.

OSStatus GetWindowProxyAlias ( WindowRef window, AliasHandle * alias );

Here is REALbasic code that illustrates how to get a file reference, including resolving the alias and releasing it.

Function DocumentFile(Extends w as Window) as FolderItem dim isChanged as Boolean Declare Function GetWindowProxyAlias Lib WindowsLib (inWindow as WindowPtr, ByRef alias as Integer) as Integer Soft Declare Function FSResolveAlias Lib CarbonFramework (fromFile as Integer, alias as Integer, Target as Ptr, ByRef wasChanged as Boolean) as Short Soft Declare Function ResolveAlias Lib CarbonFramework (fromFile as Integer, alias as Integer, Target as Ptr, ByRef wasChanged as Boolean) as Short Declare Sub DisposeHandle Lib InterfaceLib (h as Integer) Const Null = 0 dim theAlias as Integer dim OSError as Integer = GetWindowProxyAlias(w, theAlias) If OSError <> 0 then Return nil End if dim isChanged as Boolean dim theResult as FolderItem If System.IsFunctionAvailable("FSResolveAlias", CarbonFramework) then dim fileRef as new FSRef OSError = FSResolveAlias(Null, theAlias, fileRef, isChanged) If OSError = 0 then theResult = fileRef Else theResult = Nil End if Else dim fileRef as new FSSpec OSError = ResolveAlias(Null, theAlias, fileRef, isChanged) If OSError = 0 then theResult = fileRef Else theResult = Nil End if End if Finally If theAlias <> 0 then DisposeHandle theAlias End if Return theResult End Function

The FSRef and FSSpec objects, discussed in the next chapter, have Operator_Convert functions that return a FolderItem.

Implementing Custom Behavior

It is possible to implement custom behavior in Carbon applications. The Carbon Event Manager exposes several window events related to drag and drop of proxy icons:

kEventWindowClickProxyIconRgn KeventWindowPathSelect kEventWindowProxyBeginDrag kEventWindowProxyEndDrag.

The standard window handler handles these events for files, but you can add your own event handlers and implement other behavior. For example, a window might hold contact infomation; you could add a proxy icon and enable the user to drag it as a proxy for the contact.

Implementing the Carbon event code is not difficult using the framework set up in Chapter X. Adding a custom menu requires Menu Manager functions.

Implementing custom behavior in Classic applications is difficult, and probably best done using a plugin.