Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
CustomTransparentWindow.c
/* |
* File: CustomTransparentWindow.c of CarbonTransparentWindow |
* |
* Contains: 1 custom transparent window. |
* |
* Version: 1.0 |
* |
* Created: 6/20/05 |
* |
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
* ("Apple") in consideration of your agreement to the following terms, and your |
* use, installation, modification or redistribution of this Apple software |
* constitutes acceptance of these terms. If you do not agree with these terms, |
* please do not use, install, modify or redistribute this Apple software. |
* |
* In consideration of your agreement to abide by the following terms, and subject |
* to these terms, Apple grants you a personal, non-exclusive license, under AppleÍs |
* copyrights in this original Apple software (the "Apple Software"), to use, |
* reproduce, modify and redistribute the Apple Software, with or without |
* modifications, in source and/or binary forms; provided that if you redistribute |
* the Apple Software in its entirety and without modifications, you must retain |
* this notice and the following text and disclaimers in all such redistributions of |
* the Apple Software. Neither the name, trademarks, service marks or logos of |
* Apple Computer, Inc. may be used to endorse or promote products derived from the |
* Apple Software without specific prior written permission from Apple. Except as |
* expressly stated in this notice, no other rights or licenses, express or implied, |
* are granted by Apple herein, including but not limited to any patent rights that |
* may be infringed by your derivative works or by other works in which the Apple |
* Software may be incorporated. |
* |
* The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
* COMBINATION WITH YOUR PRODUCTS. |
* |
* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* Copyright: Copyright © 2005 Apple Computer, Inc, All Rights Reserved |
*/ |
//**************************************************** |
//**************************************************** |
#pragma mark * compilation directives * |
//**************************************************** |
#pragma mark - |
#pragma mark * includes & imports * |
#include "CustomTransparentWindow.h" |
//**************************************************** |
#pragma mark - |
#pragma mark * typedef's, struct's, enums, defines, etc. * |
#define kHICustomViewClass CFSTR("com.apple.sample.dts.HICustomView") |
typedef struct |
{ |
HIViewRef view; // our view |
} |
HICustomViewData; |
//**************************************************** |
#pragma mark - |
#pragma mark * local (static) function prototypes * |
static CFStringRef GetHICustomViewClass(void); |
static OSStatus HICreateCustomView(HIViewRef * outHICustomView); |
static pascal OSStatus Internal_HICustomViewHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
//**************************************************** |
#pragma mark - |
#pragma mark * exported globals * |
//**************************************************** |
#pragma mark - |
#pragma mark * local (static) globals * |
//**************************************************** |
#pragma mark - |
#pragma mark * exported function implementations * |
/***************************************************** |
* |
* Do_NewCustomCompositingWindow() |
* |
* Purpose: Create a custom compositing transparent window |
* |
* Inputs: none |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
OSStatus Do_NewCustomCompositingWindow() |
{ |
OSStatus status; |
// create a custom View |
HIViewRef customView; |
status = HICreateCustomView(&customView); |
require_noerr(status, HICreateCustomView); |
// create a custom window |
Rect bounds = {0, 0, 360, 480}; |
WindowDefSpec def = {kWindowDefHIView, (void *)customView}; |
WindowRef aWindowRef; |
status = CreateCustomWindow(&def, kPlainWindowClass, kWindowStandardHandlerAttribute | kWindowCompositingAttribute, &bounds, &aWindowRef); |
require_noerr(status, CreateCustomWindow); |
require(aWindowRef != NULL, CreateCustomWindow); |
// telling the HIToolbox that our window is not opaque |
UInt32 features; |
status = GetWindowFeatures(aWindowRef, &features); |
require_noerr(status, GetWindowFeatures); |
if ( ( features & kWindowIsOpaque ) != 0 ) |
{ |
status = HIWindowChangeFeatures(aWindowRef, 0, kWindowIsOpaque); |
require_noerr(status, HIWindowChangeFeatures); |
} |
// adding some content |
Rect buttonBounds = { 50, 50, 70, 350 }; |
HIViewRef button; |
status = CreatePushButtonControl(NULL, &buttonBounds, CFSTR("Large Text Push Button"), &button); |
require_noerr(status, CreatePushButtonControl); |
status = HIViewAddSubview(customView, button); |
require_noerr(status, HIViewAddSubview); |
MoveWindow(aWindowRef, 100, 100, true); |
ShowWindow(aWindowRef); |
HIViewAddSubview: |
HIViewFindByID: |
CreatePushButtonControl: |
ReshapeCustomWindow: |
HIWindowChangeFeatures: |
GetWindowFeatures: |
CreateCustomWindow: |
HICreateCustomView: |
return status; |
} // Do_NewCustomCompositingWindow |
//**************************************************** |
#pragma mark - |
#pragma mark * local (static) function implementations * |
/***************************************************** |
* |
* HICreateCustomView(outHICustomView) |
* |
* Purpose: Create a HICustomView |
* |
* Inputs: outHICustomView - returning the created HIView |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus HICreateCustomView(HIViewRef * outHICustomView) |
{ |
OSStatus status = paramErr; |
require(outHICustomView != NULL, paramErr); |
*outHICustomView = NULL; |
// create the view |
HIObjectRef hiObject; |
status = HIObjectCreate(GetHICustomViewClass(), 0, &hiObject); |
require_noerr(status, HIObjectCreate); |
// return the view |
*outHICustomView = (HIViewRef)hiObject; |
HIObjectCreate: |
paramErr: |
return status; |
} // HICreateCustomView |
/***************************************************** |
* |
* GetHICustomViewClass() |
* |
* Purpose: Registers our custom HICustomView view class and installs the appropriate handlers |
* |
* Inputs: none |
* |
* Returns: our class ID as a CFStringRef |
*/ |
static CFStringRef GetHICustomViewClass(void) |
{ |
// following code is pretty much boiler plate. |
static HIObjectClassRef theClass; |
if (theClass == NULL) |
{ |
static EventTypeSpec kFactoryEvents[] = |
{ |
{ kEventClassHIObject, kEventHIObjectConstruct }, |
{ kEventClassHIObject, kEventHIObjectInitialize }, |
{ kEventClassHIObject, kEventHIObjectDestruct }, |
{ kEventClassControl, kEventControlInitialize }, |
{ kEventClassControl, kEventControlDraw }, |
{ kEventClassControl, kEventControlHitTest }, |
{ kEventClassControl, kEventControlTrack } |
}; |
HIObjectRegisterSubclass(kHICustomViewClass, kHIViewClassID, 0, Internal_HICustomViewHandler, |
GetEventTypeCount(kFactoryEvents), kFactoryEvents, 0, &theClass); |
} |
return kHICustomViewClass; |
} // GetHICustomViewClass |
/***************************************************** |
* |
* Internal_HICustomViewHandler(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: Event handler that implements our HICustomView custom view |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static pascal OSStatus Internal_HICustomViewHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void * inUserData) |
{ |
OSStatus status = eventNotHandledErr; |
HICustomViewData * myData = (HICustomViewData *)inUserData; |
switch (GetEventClass(inEvent)) |
{ |
case kEventClassHIObject: |
switch (GetEventKind(inEvent)) |
{ |
case kEventHIObjectConstruct: |
{ |
// allocate some instance data |
myData = (HICustomViewData *) calloc(1, sizeof(HICustomViewData)); |
require_action(myData != NULL, ConstructExit, status = memFullErr); |
// get our superclass instance |
HIViewRef epView; |
status = GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(epView), NULL, &epView); |
require_noerr(status, ConstructExit); |
// remember our superclass in our instance data |
myData->view = epView; |
// calloc fills our structure with all zeroes which is what we want a default value for all our fields |
// so we don't need to set them to NULL or 0 one by one |
// store our instance data into the event |
status = SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(myData), &myData); |
require_noerr(status, ConstructExit); |
ConstructExit: |
break; |
} |
#pragma mark * kEventHIObjectInitialize |
case kEventHIObjectInitialize: |
{ |
// always begin kEventHIObjectInitialize by calling through to the previous handler |
status = CallNextEventHandler(inHandlerCallRef, inEvent); |
require_noerr(status, InitializeExit); |
// if that succeeded, do our own initialization |
// in this sample code, there is nothing to do |
InitializeExit: |
break; |
} |
case kEventHIObjectDestruct: |
{ |
// freeing our storage |
if (myData != NULL) free(myData); |
status = noErr; |
break; |
} |
default: |
break; |
} |
break; |
case kEventClassControl: |
switch (GetEventKind(inEvent)) |
{ |
#pragma mark * kEventControlInitialize |
case kEventControlInitialize: |
{ |
status = CallNextEventHandler(inHandlerCallRef, inEvent); |
require_noerr(status, ControlInitializeExit); |
// we need to be an embedder HIView so that others HIViews can be added in our custom window |
UInt32 features = 0; |
status = GetEventParameter(inEvent, kEventParamControlFeatures, typeUInt32, NULL, sizeof(features), NULL, &features); |
if (status == noErr) |
features |= kControlSupportsEmbedding; |
else |
features = kControlSupportsEmbedding; |
status = SetEventParameter(inEvent, kEventParamControlFeatures, typeUInt32, sizeof features, &features); |
require_noerr(status, ControlInitializeExit); |
ControlInitializeExit: |
break; |
} |
#pragma mark * kEventControlDraw |
case kEventControlDraw: |
{ |
CGContextRef context; |
status = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(context), NULL, &context); |
require_noerr(status, ControlDrawExit); |
HIRect bounds, viewBounds; |
HIViewGetBounds(myData->view, &viewBounds); |
// this will make the entire view totally transparent |
CGContextClearRect(context, viewBounds); |
// and now we draw with partially opaque colors only where we want |
CGContextSetRGBFillColor(context, 0.7, 0, 0, 0.8); |
CGContextSetRGBStrokeColor(context, 0, 0, 0.7, 0.8); |
// using a line thickness of 3 |
CGContextSetLineWidth(context, 3); |
bounds = CGRectInset(viewBounds, 3, 3); |
float minDim = (bounds.size.height < bounds.size.width) ? bounds.size.height / 2 : bounds.size.width / 2; |
float cx = bounds.origin.x + minDim, cy = bounds.origin.y + minDim; |
// drawing an ellipse |
CGContextBeginPath(context); |
CGContextAddEllipseInRect(context, CGRectInset(bounds, bounds.size.width * 0.4, 0)); |
CGContextClosePath(context); |
CGContextDrawPath(context, kCGPathFillStroke); |
status = noErr; |
ControlDrawExit: |
break; |
} |
// we want our custom window to be draggable as if it were a metal window, ie. any click-and-drag in |
// the content other than a subview will move the window around |
// we just need to handle kEventControlHitTest and kEventControlTrack for that |
#pragma mark * kEventControlHitTest |
case kEventControlHitTest: |
{ |
// the point parameter is in view-local coords. |
HIPoint pt; |
status = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(pt), NULL, &pt); |
require_noerr(status, ControlHitTestExit); |
HIRect bounds; |
status = HIViewGetBounds(myData->view, &bounds); |
require_noerr(status, ControlHitTestExit); |
if (CGRectContainsPoint(bounds, pt)) |
{ |
ControlPartCode part = kControlButtonPart; |
SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); |
status = noErr; |
} |
else status = eventNotHandledErr; |
ControlHitTestExit: |
break; |
} |
#pragma mark * kEventControlTrack |
case kEventControlTrack: |
{ |
Point pt; |
status = GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(pt), NULL, &pt); |
require_noerr(status, ControlTrackExit); |
WindowRef window = GetControlOwner(myData->view); |
// |
// Convert point from view coordinates to global coordinates. On Tiger and later, |
// you could also use HIPointConvert to do this. |
// |
Rect windowBounds; |
GetWindowBounds(window, kWindowStructureRgn, &windowBounds ); |
pt.h += windowBounds.left; |
pt.v += windowBounds.top; |
DragWindow(window, pt, NULL); |
ControlTrackExit: |
break; |
} |
default: |
break; |
} |
break; |
default: |
break; |
} |
return status; |
} // Internal_HICustomViewHandler |
Copyright © 2005 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2005-08-10