Declare
From Real Software Documentation
Used to make API calls. Both PPC and x86 machines are supported. DLLs can be called from a built Windows application. Shared libraries can be called from Macintosh and Linux applications.
Syntax
[Soft] Declare Sub/Function Name Lib LibraryName [Alias AliasName] [selector theSelector] ([Parameters]) [As ReturnType]
| Part | Type | Description |
|---|---|---|
| Name | Name | Name of the API call. Use Name in your code to refer to the API call. |
| LibraryName | String | Library in which API call is found. |
| AliasName | String | Optional: If the API call has the same name as a Real Studio method, declare the call with a different name and use the alias to refer to the actual API call. |
| Selector | String | Mac OS X only: the parameters separated with a colon (but no space) to uniquely identify a Cocoa method. This is mutually exclusive with the "Alias" clause. For example: "addSubview:" like in: |
| Parameters
Changed 2005r1
| The parameters of the API call. You can pass Nil to a parameter of type Ptr. | |
| ReturnType | Optional: The data type of the value returned by the call if it is a function. |
Notes
Function names for the OS are case-sensitive. For example, SetLocalTime works on Win32 but SetlocalTime does not.
Declare statements must not call strictly “classic” libraries like AppearanceLib to run on Mac OS X.
The Declare statement allows use of constants for Lib names.
The Declare statement can be used to call external functions that return structure values.
When building a Carbon application in the Mach-O format, the Lib parameter to a Declare statement now accepts the name of a system framework in place of a full path to the library. If you wrote a declare against "CoreMIDI", for example, the compiler would see that the Lib string did not contain any path separators, and would expand it to "/System/Library/Frameworks/CoreMIDI.framework/CoreMIDI".
You can pass Nil to a Declare parameter of type Ptr. Passing Nil is not the same as passing a Nil MemoryBlock. The former is a constant and the latter require a conversion operation at run time. If the MemoryBlock is Nil, then the conversion operator will generate a NilObjectException. However, this isn't a problem when passing the constant Nil, as no conversion is needed.
Soft Declares
In versions of Real Studio prior to 2005, the only supported type of declares was a “hard” declare. A hard declare of the form:
tells Real Studio that Foo will always be in Bar, and Bar will always be installed on the user’s system. When building your application, Real Studio puts this dependency in your application’s Import table. When the system loader tries to load your application, it will automatically find all of these Declares and try to resolve them. If it can’t resolve a library or a function from a library, your application would refuse to load and terminate.
The Soft Declare keyword provides some important flexibility. Soft declares are not put into your application’s import table so the system loader doesn’t try to resolve them. Instead, when you first try to use the softly declared method, Real Studio is responsible for resolving the library and functions. This provides you with a few handy features.
First, it means that you now have a graceful way to deal with the situation of a function or library that isn&rsuo;t found. Instead of your application just not launching, you now have a FunctionNotFound exception that you can catch. Second, Real Studio can be more flexible about loading the library.
For example, LibC on many newer Linux distributions is really a ld loader script that GCC uses to determine which version of LibC to actually link against. This means that you can't write hard declares that link against LibC in Real Studio because libc.so isn't really a symbolic link to the proper shared library (like most other .so files are). You would have to write a Declare against the actual LibC version you wanted, which provides for a very poor experience for users who don't have the same version of LibC installed as you. However, with a soft declare, Real Studio can resolve the loader script for LibC and find the proper shared library to load against In other words, what used to be declared like this:
Can now be declared like this:
With the Soft keyword, you don't have to try to link against a specific version of that library.
On Windows, any function that uses a string will have two different versions, the A version, and the W version. This is the Win32 way of dealing with Unicode. The disadvantage is that the W version of the method is usually available only on Windows NT machines, not 9x ones. If you could not use a Soft declare, you'd have to make two different versions of your application. Using Soft declares, you can do this:
Soft Declare Function MessageBoxW Lib "User32" ( hwnd as Integer, msg as WString, title as WString, flags as Integer ) as Integer
Try
Call MessageBoxW( hWnd, "This is a string that handles unicode", "Title here", 0 )
Catch e as FunctionNotFoundException
Call MessageBoxA( hWnd, "This is a string that doesn't handle unicode", "Title here", 0 )
End Try
This code runs on any version of Windows. The reason is simple: if the wide char version (W version) is available, then your call will not throw an exception, and because of the WString data type, all your strings will be automatically converted into UTF-16 strings when passed into the function.
Note: On OS X Cocoa, all Cocoa declares are "soft"; there is no need to explicitly specify it.
Checking that a Function is Available
To check whether a function can be resolved, you can use the IsFunctionAvailable function of the System module. It determines whether a function can be resolved without having to actually declare it and try to call into it.
Data Types
The following data types are for use with Declares:
| Type | Description |
|---|---|
| Byte | Unsigned 8-bit integer. |
| CFStringRef | A CFString reference. Note that framework will attempt to automatically manage the memory of the CFStringRef based off of the CoreFoundation naming rules (and Objective-C naming rules if it is an Objective-C declare). If the framework does not get this right, you can manually manage the reference counting with CFRetain/CFRelease. |
| CString | A null-terminated string. |
| OSType | A four char code. |
| PString | A "Pascal" string. |
| Ptr | 4-byte pointer to memory. |
| Short | 2-byte signed integer. |
| UByte | Unsigned 8-bit integer. |
| UShort | Unsigned 2-byte integer. |
| WindowPtr | 4-byte integer to a handle |
| WString | A UTF-16 string. |
See the descriptions of each data type for more information.
Automatic Types
There are two new automatic types: WString and CFStringRef. You can pass Nil in place of a CString, WString, CFStringRef, or PString.
You can use these two new types with declares that need a wchar_t * or CFStringRef, respectively. Their usage is the same as with CString, and all data is cleaned up when appropriate. For example:
Examples
Name Conflicts
Suppose you want to write a function that got the various system metrics. You use a method declaration like this:
However, this conflicts with the Win32 API which the function wraps. In this case, you can rename the declare using an alias such as this:
Defining Double-clicks
The following example displays the maximum number of ticks between mouse clicks for two clicks to be considered a "double-click." Above this value, two clicks are considered separate mouse events.
#if TargetMacOS
Declare Function GetDblTime Lib "Carbon" () as Integer
doubleClickTime = GetDblTime()
#endif
#if TargetWin32
Declare Function GetDoubleClickTime Lib "User32.DLL" () as Integer
doubleClickTime = GetDoubleClickTime()
#endif
MsgBox Str(doubleclicktime)
The following example gets the current process ID and illustrates soft declares for Mac OS, Windows, and Linux. In addition, it illustrates the use of the Alias parameter to set the name of the declared function to the same value for all platforms.
#if TargetMacOS
// For a Mac OS app, we use the system's
// getpid function in the kernel framework, which
// is automatically included in the system framework.
// This is not the same as a Mac OS PSN.
Soft Declare Function GetProcessID Lib "System.framework" alias "getpid" () as Integer
#endif
#if TargetWin32
Soft Declare Function GetProcessID Lib "Kernel32" alias "GetCurrentProcessId" () as Integer
#endif
#if TargetLinux
Soft Declare Function GetProcessID Lib "libc.so" alias "getpid" () as Integer
#endif
Dim pid as Integer = GetProcessID
if pid <= 0 then
//an error occurred -- the Mac OS and Linux functions return -1 in this case -- so we set pid = 0.
pid = 0
end if
return pid
End Function
The following example adds the ability to detect a double-click to a Canvas control. The code is placed in a Canvas's MouseUp event handler.
Dim doubleClickTime, currentClickTicks as Integer
#If TargetMacOS then
Declare Function GetDblTime Lib "Carbon" () as Integer
DoubleClickTime = GetDblTime()
#endif
#If TargetWin32 then
Declare Function GetDoubleClickTime Lib "User32.DLL" () as Integer
doubleClickTime = GetDoubleClickTime()
#endif
#if TargetLinux then
Declare Function gtk_settings_get_default lib "libgtk-x11-2.0.so" as Ptr
Declare Sub g_object_get lib "libgtk-x11-2.0.so" (Obj as Ptr, first_property_name as CString, ByRef doubleClicktime as Integer, Null as Integer)
Dim gtkSettings as MemoryBlock
gtkSettings = gtk_settings_get_default()
g_object_get(gtkSettings,"gtk-double-click-time",doubleClickTime, 0)
// DoubleClickTime now holds the number of milliseconds
DoubleClickTime = DoubleClickTime / 1000.0 * 60
#endif
currentClickTicks = ticks
//if the two clicks happened close enough together in time
If (currentClickTicks - lastClickTicks) <= doubleClickTime then
//if the two clicks occured close enough together in space
If Abs(X - lastClickX) <= 5 And Abs(Y - LastClickY) <= 5 then
DoubleClick //a double click has occured so call the event
end if
end if
lastClickTicks = currentClickTicks
lastClickX = X
lastClickY = Y
Cocoa Declare and CocoaObject Examples
The Cocoa Declare project in the Examples folder that ships with Real Studio has several examples of calls to NSWindow methods. Calls for both Soft Declares and hard declares are included. Whether to use the Soft Declare version is controlled by the value of the UseCocoaObj radio button (top-right corner of the window). Each event handler includes both types of calls.
Centering a Window
Centers the window to draw attention to it.
//center
//Sets the window’s location to the center of the screen.
//
//- (void)center
//
//Discussion
//The window is placed exactly in the center horizontally and somewhat above center vertically. Such a placement carries a certain visual immediacy and importance.
//This method doesn’t put the window onscreen, however; use makeKeyAndOrderFront: to do that.
//
//You typically use this method to place a window—most likely an alert dialog—where the user can’t miss it.
//This method is invoked automatically when a panel is placed on the screen by the runModalForWindow: method of the NSApplication class.
//
//Availability
//Available in Mac OS X v10.0 and later.
soft declare sub center lib "Cocoa" selector "center" (windowRef as integer)
center(self.handle)
Miniaturizes the window to the Mac OS X Dock
//miniaturize:
//Removes the window from the screen list and displays the minimized window in the Dock.
//
//- (void)miniaturize:(id)sender
//
//Parameters
//sender
//The message’s sender.
//
//Availability
//Available in Mac OS X v10.0 and later.
//See Also
//– deminiaturize:
soft declare sub miniaturize lib "Cocoa" selector "miniaturize:" (windowRef as integer, id as Ptr)
miniaturize(self.handle, nil)
Move
Moves the window to the top of the screen and provides smooth animation of the process.
//setFrame:display:animate:
//Sets the origin and size of the window’s frame rectangle, with optional animation, according to a given frame rectangle, thereby setting its position and size onscreen.
//
//- (void)setFrame:(NSRect)windowFrame display:(BOOL)displayViews animate:(BOOL)performAnimation
//
//Parameters
//windowFrame
//The frame rectangle for the window, including the title bar..
//
//displayViews
//Specifies whether the window redraws the views that need to be displayed. When YES the window sends a displayIfNeeded message down its view hierarchy, thus redrawing all views.
//
//performAnimation
//Specifies whether the window performs a smooth resize. YES to perform the animation, whose duration is specified by animationResizeTime:.
//
//Availability
//Available in Mac OS X v10.0 and later.
dim newRect as NSRect
// note that coordinates are upside down from what you are used to with Carbon
// 0,0 is at the bottom left
newRect.x = 10
newRect.y = screen(0).Height - 30
newrect.width = self.width
newrect.height = self.height + 22
soft declare sub setFrameDisplayAnimate lib "Cocoa" selector "setFrame:display:animate:" (windowRef as integer, rect as NSRect, display as integer, animate as integer)
setFrameDisplayAnimate(self.Handle, newRect, 1, 1)
Color
Displays the Color Picker so you can set the background color of the window.
// setBackgroundColor:
// Sets the window’s background color to the given color.
//- (void)setBackgroundColor:(NSColor *)color
//Parameters
//color
//Color to set as the window’s background color.
dim rgb as Color
soft declare sub setBackgroundColor lib "Cocoa" selector "setBackgroundColor:" (windowRef as integer, backColor as Ptr)
soft declare function NSClassFromString lib "Cocoa" (aClassName as CFStringRef) as Ptr
soft declare function colorWithDeviceRed lib "Cocoa" selector "colorWithDeviceRed:green:blue:alpha:"(classRef as Ptr, red as Single, green as single, blue as single, alpha as single) as Ptr
// get the reference to the NSColor class so we can call one of the class methods
dim NSColorClassRef as Ptr = NSClassFromString("NSColor")
if SelectColor(rgb, "Select a color") then
// now ask the NSColor class to create a new NSColor from the values we have
dim NSColorInstance as Ptr = colorWithDeviceRed(NSColorClassRef, rgb.red / 255, rgb.Green / 255, rgb.blue/255, 1.0)
// and set the background
setBackgroundColor(self.Handle, NSColorInstance)
end if
Background Transparency
This method uses a Slider to set the transparency level of the window.
// setAlphaValue: Applies a given alpha value to the entire window.
//
// - (void)setAlphaValue:(CGFloat)windowAlpha
// this is an instance method so we need to pass a reference to the window to the method
// CGFloat is a 32 or 64 bit value depedning on the OS (a 64 bit value would be an RB double)
// you can/could declare appropriately and figure out which one to use
soft declare sub setAlphaValue lib "Cocoa" selector "setAlphaValue:" (windowRef as integer, windowAlpha as Single)
setAlphaValue(self.handle, slider1.Value / Slider1.Maximum)
Dragging the window by the title bar
This checkbox controls whether or not the setMovable flag is set.
//setMovable:
//Specifies whether the window can be dragged by clicking in its title bar or background.
//
//- (void)setMovable:(BOOL)flag
//
//Parameters
//flag
//If YES, dragging is enabled; if NO, it is disabled.
//
//Availability
//Available in Mac OS X v10.6 and later.
//See Also
//– isMovable
//Declared In
//NSWindow.h
if (UseCocoaObj.Value = true ) then
Dim co As New RBCocoaObject(Ptr(self.handle))
if me.value then
co.Invoke("setMovable:", 1)
else
co.Invoke("setMovable:", 0)
end if
else
soft declare sub setMovable lib "Cocoa" selector "setMovable:" (windowRef as integer, yesNo as integer)
if me.value then
setMovable(self.handle, 1)
else
setMovable(self.handle, 0)
end if
end if
Window can be dragged via the background
If this checkbox is disabled and the first checkbox is enabled, then the window can only be dragged by the title bar. It it is also enabled, then the window can also be dragged by the surface of the window.
//setMovableByWindowBackground:
//Sets whether the window is movable by clicking and dragging anywhere in its background.
//
//- (void)setMovableByWindowBackground:(BOOL)movableByWindowBackground
//
//Parameters
//movableByWindowBackground
//YES to specify that the window is movable by background, NO to specify that the window is not movable by background.
//
//Availability
//Available in Mac OS X v10.2 and later.
//See Also
//– isMovableByWindowBackground
//Related Sample Code
//MyMediaPlayer
//Declared In
//NSWindow.h
soft declare sub setMovableByWindowBackground lib "Cocoa" selector "setMovableByWindowBackground:" (windowRef as integer, yesNo as integer)
if me.value then
setMovableByWindowBackground(self.handle, 1)
else
setMovableByWindowBackground(self.handle, 0)
end if
See Also
TargetCarbon, TargetCocoa, TargetLinux, TargetMacOS, TargetMachO, TargetWin32 constants; System module, FunctionNotFound exception; Byte, CFStringRef, CString, ObjCException, OSType, PString, Ptr, Short,UShort, WindowPtr, WString data types.
