[futurebasic] Re: [FB] OSX Button Draw bug

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

From: Robert Covington <artlythere@...>
Date: Tue, 18 May 2004 00:11:50 -0400
On Monday, May 17, 2004, at 11:52  PM, Robert Covington wrote:

>
> On Monday, May 17, 2004, at 04:11  PM, Walter Lenk wrote:
>
>> Greetings -
>>
>> I have an program that I am migrating to OSX, and so far I have been 
>> able to solve all the problems, except one - this involves buttons 
>> that are in a window over a PICT.  It all works fine after I made the 
>> expected appearance manager changes, but when the program runs in OSX 
>> there is a 6 (approx) pixel border ring around the buttons that 
>> overwrites the PICT with the (white) background color - this border 
>> ring is not there when the same program runs in OS9. This is not a 
>> fatal problem, but it would be nice to fix it.
>>
>> I am creating the window with:
>>  APPEARANCE WINDOW #_wMain, A$, @Rect1, _kDocumentWindowClass,
>>                                _kWindowCollapseBoxAttribute, 
>> _noAutoFocus
>> I am creating the buttons with:
>>  APPEARANCE BUTTON 
>> _Btn1,_activeBtn,0,0,0,B$,@rect2,_kControlPushButtonProc
>>
>> I am running OSX 10.3.3 on a 800 MHz iMac, FB release 7.
>>
>> Any ideas?
>>
>> Thanks,
>>
>> Walter
>
> You need a "compositing window" where you embed your PICT in a button 
> subview (or other esoteric NeXT madness). RP has an example for this. 
> If he doesn't echo back with it, email me, and I'll forward it along.
>
> You'll need to set up the window for the compositing attributes, then 
> use a special carbon window handler for the controls after embedding 
> your pict in said subview. Such then passes along the control messages 
> to FB's regular dialog event handlers.
>
> Weird stuff, and a pain in comparison to the utterly simple old way 
> (and a much better old way in this case!)
>
> Of all the things in carbonizing, maintaining any dialog that used to 
> use a PICT in the background gave me the most fits, and made me have 
> "the most quits" as in just wanting to give up on it all. They 
> shouldn't make it that hard.
>
> Robert

I found RP's example (this in R7?)...beware any line wraps, though I 
wrapped where it looked right.

Kudos to RP for this one. "OS X buttons on Graphic Background"

  Note: I had mega issues with setting up my windows to get mouse clicks 
using all this in my own dialogs...I ended up trapping the carbon event 
in the window handler for_kMouseDown, verifying if a compositing window 
was about using my particular Fn WindowExists...  and if one was about, 
sending things on to my DoMouse from there

Robert



'~'A
'                       Runtime : Rntm Appearance.Incl
'                           CPU : Carbon
'                    CALL Req'd : Off
'~'B

/*
Putting buttons on a graphic background

A long-standing problem in OS X has been that some types
of control insist on drawing their background unsuitably
when placed, for instance, over a graphic.

Compositing windows solve that problem.

A compositing window (available in 10.2 and later) requires
   _kWindowCompositingAttribute
   _kWindowStandardHandlerAttribute
but these attributes isolate the window
from FB's event handling. Specifically, most CarbonEvents
do not propagate out to WaitNextEvent, which is the basis of
the familiar HandleEvents statement.

A compositing window is made up internally of the new (10.2)
HIViews. In some cases, button code must be written with
HIView API calls.
In particular, def EmbedButton (and fn EmbedControl) do not work:
use HIViewAddSubview instead. When creating a button that
will be a subview of another control, the rect parameter
should be expressed with 'view-centric' values, not window-based
as was the case before HIViews.  That is, the point (0,0) is
the top left of the superview control.

By installing handlers on controls and on windows
(for a selection of window CarbonEvents), we
override the default handling and/or allow signalling
via FB events.

A completed user interaction with a control (such as a click
on a push button) generates a
{_kEventClassControl,_kEventControlHit} CarbonEvent that is
intercepted in this demo and converted to an FB _btnClick event.
See InstallControlHitHandler and ControlHitHandler.

Robert P.   27 February 2003
*/

include "Tlbx CarbonEvents.Incl"

// from HIToolbox/HIView.h
#define HIViewRef as ControlRef // a ControlRef *is* an HIViewRef
toolbox fn HIViewAddSubview( HIViewRef inParent,¬
  HIViewRef inNewChild) = OSStatus

_kWindowCompositingAttribute = 1 << 19

// start of CarbonEvents stuff

local fn InstallControlHitHandler( c as ControlRef )
'~'1
dim as EventTypeSpec controlEvents
begin globals
dim as proc  sControlEventUPP // 'static' var
end globals

controlEvents.eventClass = _kEventClassControl
controlEvents.eventKind  = _kEventControlHit
long if ( sControlEventUPP == _nil )
sControlEventUPP = fn NewEventHandlerUPP( [Proc "ControlHitHandler" ¬
+ _FBprocToProcPtrOffset] )
end if
end fn = fn InstallEventHandler( fn GetControlEventTarget( c ), ¬
sControlEventUPP, 1, @controlEvents, #0, #0 )

long if 0
"ControlHitHandler"
enterproc fn ControlHitHandler( nextHandler as EventHandlerCallRef, ¬
theEvent as EventRef, userData as Ptr ) = OSStatus
'~'1
dim as OSStatus       ignore
dim as ControlRef   @ controlRef

ignore = fn GetEventParameter( theEvent, _kEventParamDirectObject,¬
  _typeControlRef, #0, sizeof( controlRef ), #0, @controlRef )
fn SendBtnFBDialogEvt( controlRef ) // FB _btnClick
exitproc = _noErr // we handled
end if


local fn InstallWindowHandler( w as WindowRef )
'~'1
_nWindEventKinds = 2
dim as EventTypeSpec  events(_nWindEventKinds - 1)
begin globals
dim as proc  sWindowEventUPP // 'static' var
end globals

long if ( sWindowEventUPP == _nil )
sWindowEventUPP = fn NewEventHandlerUPP( [Proc "WindowEventHandler" ¬
+ _FBprocToProcPtrOffset] )
end if

events.eventClass(0) = _kEventClassWindow
events.eventKind(0)  = _kEventWindowActivated
events.eventClass(1) = _kEventClassWindow
events.eventKind(1)  = _kEventWindowClose

end fn = fn InstallEventHandler( fn GetWindowEventTarget( w ), ¬
sWindowEventUPP, _nWindEventKinds, @events(0), #0, #0 )

long if 0
"WindowEventHandler"
enterproc fn WindowEventHandler( nextHandler as EventHandlerCallRef, ¬
theEvent as EventRef, userData as Ptr ) = OSStatus
'~'1
dim as WindowRef   @ w
dim as OSStatus      result, ignore
dim as long          wNum

result = _eventNotHandledErr
ignore = fn GetEventParameter( theEvent, _kEventParamDirectObject,¬
  _typeWindowRef, #0, sizeof( WindowRef ), #0, @w )
wNum   = fn FBGetWndNumber( w )

// handles _kEventClassWindow events only
select fn GetEventKind( theEvent )

case _kEventWindowActivated
fn SendFBDialogEvt( _wndActivate, wNum )

case _kEventWindowClose
// let the user's FB dialog handler close the window
// (It's bad to let the standard Carbon handler close the
// window, because the FB-specific associated information
// doesn't get properly disposed of).
fn SendFBDialogEvt( _wndClose, wNum )
result = _noErr // we handled

end select

exitproc = result
end if

// end of CarbonEvents stuff


local mode
local fn DoDialog
'~'1
dim as long   evnt, id

evnt = dialog( 0 )
id   = dialog( evnt )

select evnt
case _wndClick
window id
case _wndActivate
if ( id > 0 ) then window output id
case _btnClick
beep
case _wndClose
window close id
end select

end fn


local mode
local fn BuildWindow( wndNum as long, compositing as Boolean )
'~'1
dim as Rect              r
dim as WindowAttributes  attr
dim as Str255            title
dim as OSStatus          err

attr = _kWindowStandardDocumentAttributes
long if compositing
title = "Compositing"
attr += _kWindowCompositingAttribute
attr += _kWindowStandardHandlerAttribute
attr += _kWindowLiveResizeAttribute
xelse
title = "Ordinary"
end if

appearance window wndNum, title,, _kDocumentWindowClass, attr
def SetWindowBackground( _kThemeActiveDialogBackgroundBrush, _zTrue )

// picture button
SetRect( r, 100, 50, 400, 350 )
appearance button 1,, 30333,,,,@r, _kControlPictureNoTrackProc

// push button
SetRect( r, 100, 60, 190, 80 )
appearance button 2,,,,, "Beep", @r, _kControlPushButtonProc

// checkbox
OffsetRect( r, 0, 60 )
appearance button 3,,,,, "Checkbox", @r, _kControlCheckBoxAutoToggleProc

long if compositing
// put other buttons in the HIView of the picture button
err = fn HIViewAddSubview( button&( 1 ), button&( 2 ) )
err = fn HIViewAddSubview( button&( 1 ), button&( 3 ) )

// intercept _kEventControlHit
fn InstallControlHitHandler( button&( 2 ) )
fn InstallControlHitHandler( button&( 3 ) )

// intercept some window CarbonEvents
fn InstallWindowHandler( window( _wndRef ) )
xelse
def EmbedButton( 2, 1 )
def EmbedButton( 3, 1 )
end if

end fn

// Main program
'~'1
dim as MenuRef  @ windowMenu
dim as OSStatus   ignore

long if ( system( _sysVers ) < 1020 )
shutdown "Requires OS X 10.2 or higher"
end if

on dialog fn DoDialog
ignore = fn CreateStandardWindowMenu( 0, windowMenu )
InsertMenu( windowMenu, 0 )

fn BuildWindow( 1, _zTrue )
fn BuildWindow( 2, _false )

do
HandleEvents
until 0