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.
QTSkins.c
////////// |
// |
// File: QTSkins.c |
// |
// Contains: Sample code for using QuickTime's skins. |
// |
// Written by: Tim Monroe |
// |
// Copyright: © 2000 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <5> 12/27/00 rtm reworked window region geometry calculations, following StupidPlayer.c |
// <4> 12/06/00 rtm further refinements |
// <3> 12/06/00 rtm added Windows support |
// <2> 11/24/00 rtm more work; now apparently working fine on Macintosh |
// <1> 11/15/00 rtm first file |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "QTSkins.h" |
////////// |
// |
// global variables |
// |
////////// |
extern Handle gValidFileTypes; // the list of file types that our application can open |
extern long gFirstGITypeIndex; // the index in gValidFileTypes of the first graphics importer file type |
WindowDefSpec gDefSpec; |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Utilities for creating movies with skin tracks. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// QTSkin_AddSkinTrack |
// Add a skin track to the specified movie. |
// |
////////// |
OSErr QTSkin_AddSkinTrack (Movie theMovie) |
{ |
Track myTrack = NULL; // the movie track |
Media myMedia = NULL; // the movie track's media |
Rect myRect; |
MediaHandler myHandler = NULL; |
PicHandle myContentPic = NULL; |
PicHandle myDragPic = NULL; |
OSErr myErr = paramErr; |
if (theMovie == NULL) |
goto bail; |
// elicit the two pictures we need from the user |
myContentPic = QTSkin_GetPicHandleFromFile(); |
if (myContentPic == NULL) |
goto bail; |
myDragPic = QTSkin_GetPicHandleFromFile(); |
if (myDragPic == NULL) |
goto bail; |
// get the movie's dimensions |
GetMovieBox(theMovie, &myRect); |
MacOffsetRect(&myRect, -myRect.left, -myRect.top); |
// create the skin track and media |
myTrack = NewMovieTrack(theMovie, FixRatio(myRect.right, 1), FixRatio(myRect.bottom, 1), kNoVolume); |
if (myTrack == NULL) |
goto bail; |
myMedia = NewTrackMedia(myTrack, FOUR_CHAR_CODE('skin'), GetMovieTimeScale(theMovie), NULL, 0); |
if (myMedia == NULL) |
goto bail; |
myHandler = GetMediaHandler(myMedia); |
if (myHandler == NULL) |
goto bail; |
// add the skin content picture as public media information |
myErr = MediaSetPublicInfo(myHandler, FOUR_CHAR_CODE('skcr'), (void *)myContentPic, 0); |
if (myErr != noErr) |
goto bail; |
// add the skin drag picture as public media information |
myErr = MediaSetPublicInfo(myHandler, FOUR_CHAR_CODE('skdr'), (void *)myDragPic, 0); |
if (myErr != noErr) |
goto bail; |
// add the media to the track |
myErr = InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1); |
bail: |
if (myContentPic != NULL) |
KillPicture(myContentPic); |
if (myDragPic != NULL) |
KillPicture(myDragPic); |
return(myErr); |
} |
////////// |
// |
// QTSkin_GetPicHandleFromFile |
// Elicit a picture file from the user and return the picture in it. |
// |
////////// |
PicHandle QTSkin_GetPicHandleFromFile (void) |
{ |
OSType myTypeList = kQTFileTypeQuickTimeImage; // any image file readable by GetGraphicsImporterForFile |
short myNumTypes = 1; |
FSSpec myPictSpec; |
QTFrameFileFilterUPP myFilterUPP = NULL; |
GraphicsImportComponent myImporter = NULL; |
PicHandle myPicture = NULL; |
OSErr myErr = noErr; |
#if TARGET_OS_MAC |
myNumTypes = 0; |
#endif |
// have the user select an image file |
myFilterUPP = QTFrame_GetFileFilterUPP((ProcPtr)QTSkin_FileFilterFunction); |
myErr = QTFrame_GetOneFileWithPreview(myNumTypes, (QTFrameTypeListPtr)&myTypeList, &myPictSpec, myFilterUPP); |
if (myErr != noErr) |
goto bail; |
// get a graphics importer for the image file |
myErr = GetGraphicsImporterForFile(&myPictSpec, &myImporter); |
if (myErr != noErr) |
goto bail; |
// convert the image into a PicHandle |
myErr = GraphicsImportGetAsPicture(myImporter, &myPicture); |
bail: |
if (myFilterUPP != NULL) |
DisposeNavObjectFilterUPP(myFilterUPP); |
if (myImporter != NULL) |
CloseComponent(myImporter); |
return(myPicture); |
} |
////////// |
// |
// QTSkin_FileFilterFunction |
// Filter files for a file-opening dialog box. |
// |
////////// |
#if TARGET_OS_MAC |
PASCAL_RTN Boolean QTSkin_FileFilterFunction (AEDesc *theItem, void *theInfo, void *theCallBackUD, NavFilterModes theFilterMode) |
{ |
#pragma unused(theCallBackUD, theFilterMode) |
NavFileOrFolderInfo *myInfo = (NavFileOrFolderInfo *)theInfo; |
OSErr myErr = noErr; |
if (gValidFileTypes == NULL) |
QTFrame_BuildFileTypeList(); |
if (theItem->descriptorType == typeFSS) |
if (!myInfo->isFolder) { |
OSType myType = myInfo->fileAndFolder.fileInfo.finderInfo.fdType; |
OSType *myTypes = (OSType *)*gValidFileTypes; |
short myCount; |
short myIndex; |
// see whether the file type is in the list of image file types that QuickTime can open |
myCount = GetHandleSize(gValidFileTypes) / sizeof(OSType); |
for (myIndex = gFirstGITypeIndex; myIndex < myCount; myIndex++) |
if (myType == myTypes[myIndex]) |
return(true); |
// if we got to here, it's a file we cannot open |
return(false); |
} |
return(true); |
} |
#endif |
#if TARGET_OS_WIN32 |
PASCAL_RTN Boolean QTSkin_FileFilterFunction (CInfoPBPtr thePBPtr) |
{ |
#pragma unused(thePBPtr) |
return(false); |
} |
#endif |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Utilities for displaying movies with skin tracks. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// QTSkin_Init |
// Perform any application-specific initialization for skinned movie support. |
// |
////////// |
void QTSkin_Init (void) |
{ |
// set up the window procedure definition structure |
gDefSpec.defType = kWindowDefProcPtr; |
gDefSpec.u.defProc = NewWindowDefUPP(QTSkin_SkinWindowDef); |
} |
////////// |
// |
// QTSkin_Stop |
// Perform any application-specific tear-down for skinned movie support. |
// |
////////// |
void QTSkin_Stop (void) |
{ |
// dispose of the window procedure UPP |
if (gDefSpec.u.defProc != NULL) |
DisposeWindowDefUPP(gDefSpec.u.defProc); |
} |
////////// |
// |
// QTSkin_SkinWindowDef |
// A custom window definition procedure (WDEF) for a skinned movie window. |
// |
////////// |
static PASCAL_RTN long QTSkin_SkinWindowDef (short theVarCode, WindowRef theWindow, short theMessage, long theParam) |
{ |
#pragma unused(theVarCode) |
switch (theMessage) { |
case kWindowMsgInitialize: |
case kWindowMsgCleanUp: |
case kWindowMsgDrawGrowOutline: |
case kWindowMsgDrawGrowBox: |
// nothing here |
break; |
case kWindowMsgDraw: |
break; |
case kWindowMsgHitTest: { |
ApplicationDataHdl myAppData = NULL; |
Point myPoint; // location of cursor when mouse button pressed, in global coordinates |
Point myLocal; // location of cursor when mouse button pressed, in local coordinates |
GrafPtr myPort; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindow(QTFrame_GetWindowReferenceFromWindow(theWindow)); |
if (myAppData == NULL) |
return(wNoHit); |
// on entry, theParam contains the mouse location, in global screen coordinates |
myPoint.v = HiWord(theParam); |
myPoint.h = LoWord(theParam); |
// the content and drag regions are offset relative to the window origin |
GetPort(&myPort); |
SetPortWindowPort(theWindow); |
myLocal = myPoint; |
GlobalToLocal(&myLocal); |
MacSetPort(myPort); |
// look first to see if the mouse event is in the drag region; |
// it takes precedence over the content region |
if (PtInRgn(myLocal, (**myAppData).fDragRegion)) |
return(wInDrag); |
if (PtInRgn(myLocal, (**myAppData).fContentRegion)) |
return(wInContent); |
return(wNoHit); |
} |
case kWindowMsgGetFeatures: |
if (theParam != 0L) |
*(OptionBits *)theParam = kWindowCanGetWindowRegion; |
return(1); |
case kWindowMsgGetRegion: { |
// return the region corresponding to the specified region code, in global coordinates |
GetWindowRegionRec *myRgnRec = (GetWindowRegionRec *)theParam; |
ApplicationDataHdl myAppData = NULL; |
GrafPtr myPort; |
Rect myPortBounds; |
Point myTopLeft; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindow(QTFrame_GetWindowReferenceFromWindow(theWindow)); |
if (myAppData == NULL) |
return(noErr); |
if (myRgnRec == NULL) |
return(noErr); |
// get the top-left corner of the window, in global coordinates |
GetPort(&myPort); |
SetPortWindowPort(theWindow); |
#if TARGET_API_MAC_CARBON |
GetPortBounds(GetWindowPort(theWindow), &myPortBounds); |
#else |
myPortBounds = theWindow->portRect; |
#endif |
myTopLeft.h = myPortBounds.left; |
myTopLeft.v = myPortBounds.top; |
LocalToGlobal(&myTopLeft); |
MacSetPort(myPort); |
switch (myRgnRec->regionCode) { |
case kWindowTitleBarRgn: |
case kWindowCloseBoxRgn: |
break; |
case kWindowDragRgn: |
MacCopyRgn((**myAppData).fDragRegion, myRgnRec->winRgn); |
MacOffsetRgn(myRgnRec->winRgn, myTopLeft.h, myTopLeft.v); |
break; |
case kWindowContentRgn: |
MacCopyRgn((**myAppData).fContentRegion, myRgnRec->winRgn); |
MacOffsetRgn(myRgnRec->winRgn, myTopLeft.h, myTopLeft.v); |
break; |
case kWindowStructureRgn: |
MacCopyRgn((**myAppData).fStructRegion, myRgnRec->winRgn); |
MacOffsetRgn(myRgnRec->winRgn, myTopLeft.h, myTopLeft.v); |
break; |
default: |
break; |
} |
return(noErr); |
} |
#if !TARGET_API_MAC_CARBON |
case kWindowMsgCalculateShape: // aka wCalcRgns |
// this message is not used under Carbon; instead, the kWindowMsgGetRegion message is used |
break; |
#endif |
default: |
break; |
} |
return(0L); |
} |
////////// |
// |
// QTSkin_CreateSkinsWindow |
// Create a new window for a movie that contains a skins track. |
// |
// We need to call this function only on MacOS, where it is called instead of QTFrame_CreateMovieWindow; |
// on Windows, QTFrame_CreateMovieWindow eventually calls QTSkin_InitWindowData, which in turn calls SetWindowRgn |
// to install the custom window shape. |
// |
////////// |
WindowReference QTSkin_CreateSkinsWindow (void) |
{ |
WindowPtr myWindow = NULL; |
WindowReference myWindowRef = NULL; |
Rect myRect = {10, 60, 200, 200}; |
// call CreateCustomWindow to create a window using our custom window definition procedure |
CreateCustomWindow(&gDefSpec, kDocumentWindowClass, kWindowNoAttributes, &myRect, &myWindow); |
if (myWindow != NULL) { |
// get the "window reference" for this window |
myWindowRef = QTFrame_GetWindowReferenceFromWindow(myWindow); |
// create a new window object associated with the new window |
QTFrame_CreateWindowObject(myWindowRef); |
} |
return(myWindowRef); |
} |
////////// |
// |
// QTSkin_ConvertPictureToRegion |
// Get a region for the specified picture. |
// |
////////// |
OSErr QTSkin_ConvertPictureToRegion (PicHandle thePicture, RgnHandle *theRegionPtr) |
{ |
Rect myRect; |
GWorldPtr myGWorld = NULL; |
PixMapHandle myPixMap = NULL; |
CGrafPtr mySavedPort = NULL; |
GDHandle mySavedDevice = NULL; |
RgnHandle myRegion = NULL; |
OSErr myErr = noErr; |
if ((thePicture == NULL) || (theRegionPtr == NULL)) |
return(paramErr); |
// get the current graphics port and device |
GetGWorld(&mySavedPort, &mySavedDevice); |
// get the bounding box of the picture |
myRect = (**thePicture).picFrame; |
myRect.bottom = EndianS16_BtoN(myRect.bottom); |
myRect.right = EndianS16_BtoN(myRect.right); |
// create a new GWorld and draw the picture into it |
myErr = QTNewGWorld(&myGWorld, k1MonochromePixelFormat, &myRect, NULL, NULL, kICMTempThenAppMemory); |
if (myGWorld == NULL) |
goto bail; |
SetGWorld(myGWorld, NULL); |
myPixMap = GetPortPixMap(myGWorld); |
if (myPixMap == NULL) |
goto bail; |
LockPixels(myPixMap); |
HLock((Handle)myPixMap); |
EraseRect(&myRect); |
DrawPicture(thePicture, &myRect); |
// create a new region and convert the pixmap into a region |
myRegion = NewRgn(); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
myErr = BitMapToRegion(myRegion, (BitMap *)*myPixMap); |
bail: |
if (myErr != noErr) { |
if (myRegion != NULL) { |
DisposeRgn(myRegion); |
myRegion = NULL; |
} |
} |
if (myGWorld != NULL) |
DisposeGWorld(myGWorld); |
// restore the original graphics port and device |
SetGWorld(mySavedPort, mySavedDevice); |
*theRegionPtr = myRegion; |
return(myErr); |
} |
////////// |
// |
// QTSkin_InitWindowData |
// Do any skin-specific initialization for the specified window. |
// |
////////// |
ApplicationDataHdl QTSkin_InitWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData = NULL; |
Track myTrack = NULL; |
MediaHandler myHandler = NULL; |
PicHandle myPicture = NULL; |
RgnHandle myRegion = NULL; |
MatrixRecord myMatrix; |
OSErr myErr = noErr; |
// if we already have some window data, dump it |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) |
QTSkin_DumpWindowData(theWindowObject); |
myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord)); |
if (myAppData != NULL) { |
myTrack = GetMovieIndTrackType((**theWindowObject).fMovie, 1, FOUR_CHAR_CODE('skin'), movieTrackCharacteristic); |
if (myTrack != NULL) { |
myHandler = GetMediaHandler(GetTrackMedia(myTrack)); |
if (myHandler != NULL) { |
// get the current movie matrix |
GetMovieMatrix((**theWindowObject).fMovie, &myMatrix); |
myPicture = (PicHandle)NewHandle(0); |
if (myPicture == NULL) |
goto bail; |
// get the content region picture |
myErr = MediaGetPublicInfo(myHandler, FOUR_CHAR_CODE('skcr'), myPicture, NULL); |
if (myErr != noErr) |
goto bail; |
// convert it to a region |
myErr = QTSkin_ConvertPictureToRegion(myPicture, &myRegion); |
(**myAppData).fContentRegion = myRegion; |
if (myErr != noErr) |
goto bail; |
// scale that region so the window scales with the movie |
myErr = TransformRgn(&myMatrix, (**myAppData).fContentRegion); |
if (myErr != noErr) |
goto bail; |
#if TARGET_OS_WIN32 |
(**myAppData).fWinHRGN = MacRegionToNativeRegion((**myAppData).fContentRegion); |
if ((**myAppData).fWinHRGN != NULL) { |
RECT myRect; |
int myResult; |
GetRgnBox((**myAppData).fWinHRGN, &myRect); |
// the coordinates of a window region are relative to the upper-left corner of the window |
// (not to the client area of the window) |
OffsetRgn((**myAppData).fWinHRGN, -myRect.left + GetSystemMetrics(SM_CXFRAME), -myRect.top + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXFRAME)); |
myResult = SetWindowRgn((**theWindowObject).fWindow, (**myAppData).fWinHRGN, true); |
if (myResult == 0) { |
// SetWindowRgn failed |
DeleteObject((**myAppData).fWinHRGN); |
(**myAppData).fWinHRGN = NULL; |
goto bail; |
} |
} |
#endif |
// repeat with drag region picture |
myErr = MediaGetPublicInfo(myHandler, FOUR_CHAR_CODE('skdr'), myPicture, NULL); |
if (myErr != noErr) |
goto bail; |
// convert it to a region |
myErr = QTSkin_ConvertPictureToRegion(myPicture, &myRegion); |
(**myAppData).fDragRegion = myRegion; |
if (myErr != noErr) |
goto bail; |
// scale that region so the window scales with the movie |
myErr = TransformRgn(&myMatrix, (**myAppData).fDragRegion); |
if (myErr != noErr) |
goto bail; |
// copy the content region into the structure region |
(**myAppData).fStructRegion = NewRgn(); |
MacCopyRgn((**myAppData).fContentRegion, (**myAppData).fStructRegion); |
} |
} |
} |
bail: |
if (myPicture != NULL) |
KillPicture(myPicture); |
return(myAppData); |
} |
////////// |
// |
// QTSkin_DumpWindowData |
// Do any skin-specific tear-down for the specified window. |
// |
////////// |
void QTSkin_DumpWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData = NULL; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) { |
if ((**myAppData).fContentRegion != NULL) |
DisposeRgn((**myAppData).fContentRegion); |
if ((**myAppData).fDragRegion != NULL) |
DisposeRgn((**myAppData).fDragRegion); |
if ((**myAppData).fStructRegion != NULL) |
DisposeRgn((**myAppData).fStructRegion); |
(**myAppData).fContentRegion = NULL; |
(**myAppData).fDragRegion = NULL; |
(**myAppData).fStructRegion = NULL; |
#if TARGET_OS_WIN32 |
// according to the documentation, after passing a region to SetWindowRgn, the operating system |
// owns that region; I assume this means that we do not need to delete (**myAppData).fWinHRGN |
(**myAppData).fWinHRGN = NULL; |
#endif |
DisposeHandle((Handle)myAppData); |
(**theWindowObject).fAppData = NULL; |
} |
} |
#if TARGET_OS_WIN32 |
////////// |
// |
// QTSkin_IsDragClick |
// Return true if the mouse click whose coordinates are in lParam is in the drag region, false otherwise. |
// |
////////// |
Boolean QTSkin_IsDragClick (WindowObject theWindowObject, LONG lParam) |
{ |
WindowObject myWindowObject = NULL; |
ApplicationDataHdl myAppData = NULL; |
HRGN myRegion = NULL; |
POINT myPoint; |
Boolean isDragClick = false; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) { |
myPoint.x = LOWORD(lParam); |
myPoint.y = HIWORD(lParam); |
myRegion = MacRegionToNativeRegion((**myAppData).fDragRegion); |
if (PtInRegion(myRegion, myPoint.x, myPoint.y)) |
isDragClick = true; |
DeleteObject(myRegion); |
} |
return(isDragClick); |
} |
#endif |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Miscellaneous utilities. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// QTSkin_IsSkinnedMovie |
// Is the specified movie a skinned movie? |
// |
////////// |
Boolean QTSkin_IsSkinnedMovie (Movie theMovie) |
{ |
return(GetMovieIndTrackType(theMovie, 1, FOUR_CHAR_CODE('skin'), movieTrackCharacteristic) != NULL); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14