[futurebasic] Calling all control freaks

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : January 2004 : Group Archive : Group : All Groups

From: Robert Purves <robert.purves@...>
Date: Sun, 18 Jan 2004 22:45:22 +1300
This is really for Bernie and 'The Window Maker', but others who have 
struggled to implement Carbon control-creation routines (like 
CreateDisclosureTriangleControl, CreateListBoxControl or 
CreateDataBrowserControl) may find it useful.

Robert P.


'-----------
/*
Appearance button makes use internally of NewControl, which dates
from the first Mac, when the only controls were push button,
radio button, checkbox, and scroll bar.
To allow NewControl to create the ridiculous widgets of recent years,
Apple had to "overload" the init/min/max values to mean something
quite different. Thus NewControl (and hence appearance button) became
difficult to understand.

With Carbon, Apple introduced the improved "CreateXXXXControl" functions
(listed below), which specify the relevant control features through 
named
parameters. Another advantage of the new functions is that titles and 
other
strings are supplied as CFStrings, i.e. Unicode, and could be (say) in
Cyrillic or ancient Greek.

A small number of controls have features that cannot be obtained at all
when the control is created with NewControl. To get these features
you *have* to use CreateXXXXControl.

Some FB programmers have experimented with CreateXXXControl, but
found it difficult to integrate the result (a ControlRef) into an FB
program. MakeIntoFBButton solves that problem.

MakeIntoFBButton takes a ControlRef obtained from one of the
CreateXXXControl functions, and turns it into a perfectly normal
FB button with any desired btnNum, just as though it had
been created with the appearance button statement.

MakeIntoFBButton should also work with HIViewRef widgets such as
that from HIComboBoxCreate, although I have not tested this.
(An HIViewRef *is* a ControlRef.)

Robert P.  18 January 2004
*/

'~'A
'                       Runtime : Rntm Appearance.Incl
'                           CPU : Carbon
'~'B


/*
See ControlDefinitions.h for these CreateXXXControl functions.

CreateBevelButtonControl
CreateSliderControl
CreateDisclosureTriangleControl
CreateProgressBarControl
CreateRelevanceBarControl
CreateLittleArrowsControl
CreateChasingArrowsControl
CreateTabsControl
CreateSeparatorControl
CreateGroupBoxControl
CreateCheckGroupBoxControl
CreatePopupGroupBoxControl
CreateImageWellControl
CreatePopupArrowControl
CreatePlacardControl
CreateClockControl
CreateUserPaneControl
CreateEditTextControl [don't use this  RP]
CreateStaticTextControl
CreatePictureControl
CreateIconControl
CreateWindowHeaderControl
CreateListBoxControl
CreatePushButtonControl
CreatePushButtonWithIconControl
CreateRadioButtonControl
CreateCheckBoxControl
CreateScrollBarControl
CreatePopupButtonControl
CreateRadioGroupControl
CreateScrollingTextBoxControl
CreateDisclosureButtonControl
CreateRoundButtonControl
CreateDataBrowserControl
CreateEditUnicodeTextControl
*/

// two CreateXXXControl translations for demo purposes
toolbox fn CreatePushButtonControl( WindowRef window, const Rect ¬
     *boundsRect, CFStringRef title, ControlRef *  outControl ) = 
OSStatus

toolbox fn CreateDisclosureTriangleControl( WindowRef inWindow,¬
     const Rect *inBoundsRect, UInt16 inOrientation,¬
     CFStringRef inTitle, SInt32 inInitialValue, Boolean inDrawTitle,¬
     Boolean inAutoToggles, ControlRef *outControl ) = OSStatus

_kControlDisclosureTrianglePointDefault = 0


// This is the magic routine...
// It fails silently if anything is wrong, for instance if
// c is already an FB button, or btnNum is already in use.
local mode
local fn MakeIntoFBButton( c as ControlRef, btnNum as long )
'~'1
dim cRefCon as ^^FBcontrolDescription
dim as WindowRef  w

w = fn GetControlOwner( c )
long if ( w )
long if ( fn GetCRefCon( c ) == 0 ) // not FB button already
long if ( fn FindFBBtnControl( w, btnNum ) == 0 ) // btnNum unused
cRefCon = fn NewHandleClear( sizeof( FBcontrolDescription ) )
long if ( cRefCon )
cRefCon..FBcontrolRef    = btnNum
cRefCon..FBcontrolClass  = _buttonControlClass
cRefCon..FBcntrlSubclass = _buttonSubclass
SetControlReference( c, cRefCon )
fn AddFBControlToList( fn GetWRefCon( w ), c, cRefCon )
end if
end if
end if
end if

end fn


// Simple dialog handler to show that all buttons
// have normal FB behaviour.
local mode
local fn DoDialog
'~'1
dim as long  evnt, ref
evnt = dialog( 0 )
ref  = dialog( evnt )
select evnt
case _btnClick
print "Button" + str$( ref ) + " clicked";
long if ( ref >= 3 )
print "  Value = " button( ref );
end if
print
end select
end fn


// Demo makes 2 push buttons and 2 disclosure triangles
dim as Rect          r
dim as ControlRef  @ c
dim as CFStringRef   cfTitle
dim as OSStatus      err

on dialog fn DoDialog

window 1
// appearance push button
SetRect( r, 160, 100, 260, 120 )
appearance button 1,,,,, "Push", @r, _kControlPushButtonProc

// CreatePushButtonControl [this has no advantage]
OffsetRect( r, 0, 40 )
cfTitle = fn CFStringCreateWithPascalString( 0, "Push",¬
      _kCFStringEncodingMacRoman )
err = fn CreatePushButtonControl( window( _wndRef ), r, ¬
      cfTitle, @c )
//if ( err ) then stop "CreatePushButtonControl error " + str$( err )
if ( err == _noErr ) then¬
     fn MakeIntoFBButton( c, 2 ) // becomes button 2
CFRelease( cfTitle )


// appearance button triangle control [cannot set a name on this]
SetRect( r, 300, 100, 385, 120 )
appearance button 3,, 0,,, "Name ignored", @r, 
_kControlTriangleAutoToggleProc

// CreateDisclosureTriangleControl [can set a name on this (in OS X 
only)]
OffsetRect( r, 0, 40 )
cfTitle = fn CFStringCreateWithPascalString( 0, "Triangle",¬
     _kCFStringEncodingMacRoman )
err = fn CreateDisclosureTriangleControl( window( _wndRef ), r,¬
     _kControlDisclosureTrianglePointDefault, cfTitle, 0, ¬
     (system( _sysVers ) >= 1000), _true, @c )
//if ( err ) then stop "CreateDisclosureTriangleControl error " + str$( 
err )
if ( err == _noErr ) then¬
     fn MakeIntoFBButton( c, 4 ) // becomes button 4
CFRelease( cfTitle )

do
HandleEvents
until 0

//kill resources "plst", 0 // force Classic in OS X
'-----------