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.
Main.c
/* |
File: main.c |
Contains: This sample demonstrates a variety of techniques and features of Carbon. |
¥ How to display sheets on Mac OS X, & Alert windows through CarbonLib |
¥ How to install the default event handlers without really using RunApplicationEventLoop() |
¥ How to efficiently set up and use cooperative threads from a CarbonEvent based application |
¥ Uses CarbonEvents on the Application, window, and control targets |
¥ Uses EventLoopTimers |
¥ How to bundle your CFM based application for use in CodeWarrior |
¥ How to use Nib's within your application |
- How to set up command IDs within InterfaceBuilder |
- How to automatically set up help tags for Mac OS X within InterfaceBuilder |
¥ÊTab controls |
¥ÊHow to enable the Preferences menu |
¥ CFPreferences |
¥ How to add a help book |
- How to add a menu item to the Help menu |
¥ 128 Bit Icon |
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 © 2001 Apple Computer, Inc., All Rights Reserved |
*/ |
#ifdef __APPLE_CC__ |
#include <Carbon/Carbon.h> |
#else |
#include <Carbon.h> |
#endif |
#include "Main.h" |
static pascal OSStatus MyTabEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static pascal OSStatus AppEventEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static pascal OSStatus MainWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static pascal void MainRunLoopForThreadedApps( EventLoopTimerRef inTimer, void *inUserData ); |
static pascal OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, long refcon ); |
static pascal OSStatus PrefsWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static pascal OSStatus AboutBoxWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static void InstallMainWindowEventHandlers( WindowRef window ); |
static void InitApplication( void ); |
static void MySwitchItemOfTabControl( WindowRef window, ControlRef tabControl, short currentTabIndex ); |
static void SaveMainWindowPrefs( WindowRef window ); |
static void SetMainWindowAttributesFromPrefs( WindowRef window ); |
static void SaveApplicationPrefs( WindowRef window ); |
static void GetApplicationPrefs( void ); |
static OSStatus RegisterMyHelpBook( void ); |
static OSStatus GoToMyHelpAnchor( CFStringRef anchorName ); |
static CFStringRef GetMachineNameAsCFString(); |
void DisplayAlertWindow( WindowRef parentWindow, StringPtr alertS ); |
static pascal OSStatus AlertWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData ); |
GlobalsStruct g; // Globals |
// Main entry point |
int main( int argc, char* argv[] ) |
{ |
HICommand newCommand = { 0, kHICommandNew }; |
InitApplication(); |
(void) InstallEventLoopTimer( GetCurrentEventLoop(), 0, 0, NewEventLoopTimerUPP( MainRunLoopForThreadedApps ), NULL, &g.mainRunLoopTimerRef ); |
ProcessHICommand( &newCommand ); // Open a new window |
// We really only call RunApplicationEventLoop() to install the default CarbonEvent handlers. Once the timer installed above |
// fires, we remain in the MainRunLoopForThreadedApps() routine which is designed to yield to other cooperative threads. |
RunApplicationEventLoop(); |
// We don't need the nib reference anymore. |
DisposeNibReference( g.mainNibRef ); |
return( noErr ); |
} |
// Q&A 1061 discusses how to handle cooperative threads from a CarbonEvent based application |
// http://developer.apple.com/qa/qa2001/qa1061.html |
// Main Event Loop |
static pascal void MainRunLoopForThreadedApps( EventLoopTimerRef inTimer, void *inUserData ) |
{ |
OSStatus err; |
EventRef theEvent; |
EventTimeout timeToWaitForEvent; |
EventTargetRef theTarget = GetEventDispatcherTarget(); |
do |
{ |
if ( g.numberOfRunningThreads == 0 ) |
timeToWaitForEvent = kEventDurationForever; |
else |
timeToWaitForEvent = kEventDurationNoWait; |
err = ReceiveNextEvent( 0, NULL, timeToWaitForEvent, true, &theEvent ); |
if ( err == noErr ) |
{ |
(void) SendEventToEventTarget( theEvent, theTarget ); |
ReleaseEvent( theEvent ); |
} |
else if ( err == eventLoopTimedOutErr ) |
{ |
err = noErr; |
} |
if ( g.numberOfRunningThreads > 0 ) |
(void) YieldToAnyThread(); |
// eventLoopQuitErr may be sent to wake up the queue and does not necessarily |
} while ( g.done == false ); // mean 'quit', we handle the Quit case from our AppleEvent handler |
} |
static Boolean RunningOnCarbonX( void ) |
{ |
UInt32 response; |
return( Gestalt(gestaltSystemVersion, |
(SInt32 *) &response) == noErr) |
&& (response >= 0x01000 ); |
} |
static Boolean RunningOnCarbonTenPointOneOrHigher( void ) |
{ |
UInt32 response; |
return( Gestalt(gestaltSystemVersion, |
(SInt32 *) &response) == noErr) |
&& (response >= 0x01010 ); |
} |
static void InitApplication( ) |
{ |
long response; |
OSStatus err; |
MenuRef menuHandle; |
MenuItemIndex customItemIndex; |
Rect rect; |
static const EventTypeSpec sAppEvents[] = |
{ |
{ kEventClassCommand, kEventCommandProcess }, |
{ kEventClassApplication, kEventAppActivated } |
}; |
InitCursor(); |
// Create a Nib reference passing the name of the nib file (without the .nib extension) |
// CreateNibReference only searches into the application bundle. |
err = CreateNibReference( CFSTR("main"), &g.mainNibRef ); |
if ( err != noErr ) goto Bail; |
// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar |
// object. This name is set in InterfaceBuilder when the nib is created. |
err = Gestalt( gestaltMenuMgrAttr, &response ); |
if ( err != noErr ) goto Bail; |
if ( response & gestaltMenuMgrAquaLayoutMask ) |
err = SetMenuBarFromNib( g.mainNibRef, CFSTR("MenuBar") ); |
else |
err = SetMenuBarFromNib( g.mainNibRef, CFSTR("MenuBar9") ); |
if ( err != noErr ) goto Bail; |
err = RegisterMyHelpBook(); |
if ( err == noErr ) // Add custom Help Menu items |
{ |
err = HMGetHelpMenu( &menuHandle, &customItemIndex ); |
if ( err == noErr ) |
{ |
if ( RunningOnCarbonX() == false ) // Mac OS 8/9 bundled applications must manually add and handle their help menu |
(void) SetMenuItemCommandKey( menuHandle, customItemIndex, true, 0x2C ); // Set <command> '/' to the menu |
InsertMenuItem( menuHandle, "\pGo To The Images Help", customItemIndex - 1 ); // Insert our extra Help item |
(void) SetMenuItemCommandID( menuHandle, customItemIndex, 'XHlp' ); |
} |
} |
// Create & initialize our "Large Cursor" window |
SetRect( &rect, 50, 50, 114, 114 ); // left, top, right, bottom |
err = CreateNewWindow( kOverlayWindowClass, kWindowHideOnSuspendAttribute, &rect, &g.cursorWindow ); |
// if ( err == errUnrecognizedWindowClass ) // Disabled on Mac OS 8/9 |
InstallApplicationEventHandler( NewEventHandlerUPP(AppEventEventHandlerProc), GetEventTypeCount(sAppEvents), sAppEvents, 0, NULL ); |
(void) AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false ); |
g.numberOfRunningThreads = 0; // Initialize globals |
g.done = false; |
g.largeCursorActive = false; |
g.largeCursorEventHandler = NewEventHandlerUPP( LargeCursorEventHandler ); |
GetApplicationPrefs(); |
EnableMenuCommand( NULL, kHICommandPreferences ); // Enable the preferences menu |
Bail: |
return; |
} |
static void InstallMainWindowEventHandlers( WindowRef window ) |
{ |
ControlRef control; |
OSStatus err; |
static const EventTypeSpec tabControlEvents[] = |
{ |
{ kEventClassControl, kEventControlClick }, // Sent before the tab control switches its control value |
{ kEventClassControl, kEventControlHit }, |
{ kEventClassCommand, kEventCommandProcess } |
}; |
static const EventTypeSpec windowEvents[] = |
{ |
{ kEventClassCommand, kEventCommandProcess }, |
{ kEventClassWindow, kEventWindowClose } |
}; |
g.tabControlID.signature = 'AAPL'; |
g.tabControlID.id = 128; |
GetControlByID( window, &g.tabControlID, &control ); |
err = InstallControlEventHandler( control, NewEventHandlerUPP( MyTabEventHandlerProc ), GetEventTypeCount(tabControlEvents), tabControlEvents, window, NULL ); |
if ( err != noErr ) SysBeep(0); |
SetMainWindowAttributesFromPrefs( window ); |
// We pass "window" as the userData to make it available from our event handler |
err = InstallWindowEventHandler( window, NewEventHandlerUPP( MainWindowEventHandlerProc ), GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
if ( err != noErr ) SysBeep(0); |
} |
static pascal OSStatus AppEventEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
#pragma unused ( inCallRef, inUserData ) |
HICommand command; |
WindowRef window; |
OSStatus err = eventNotHandledErr; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind(inEvent); |
switch ( eventClass ) |
{ |
case kEventClassCommand: |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
if ( eventKind == kEventCommandProcess ) |
{ |
if ( command.commandID == kHICommandNew ) |
{ |
err = CreateWindowFromNib( g.mainNibRef, CFSTR("MainWindow"), &window ); |
if ( err == noErr ) |
{ |
WindowinfoStruct *windowinfo = (WindowinfoStruct*)NewPtrClear( sizeof(WindowinfoStruct) ); |
windowinfo->windowidentifier = kMainTabWindowType; |
SetWRefCon( window, (long) windowinfo ); |
InstallMainWindowEventHandlers( window ); |
//CreateCGContextForPort( GetWindowPort(window), &windowinfo->cgContext ); |
CreateMyDataBrowserControl( window ); |
ShowWindow( window ); |
SetPortWindowPort( window ); |
} |
} |
else if ( command.commandID == kHICommandPreferences ) // Handle selection of the preferences menu |
{ |
err = CreateWindowFromNib( g.mainNibRef, CFSTR("PreferencesWindow"), &window ); |
if ( err == noErr ) |
{ |
ControlRef control; |
ControlID controlID = { 'PChk', 1 }; |
static const EventTypeSpec windowEvents[] = |
{ { kEventClassCommand, kEventCommandProcess }, |
{ kEventClassWindow, kEventWindowClose } |
}; |
err = InstallWindowEventHandler( window, NewEventHandlerUPP( PrefsWindowEventHandlerProc ), GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
DisableMenuCommand( NULL, kHICommandPreferences ); |
GetControlByID( window, &controlID, &control ); |
SetControlValue( control, g.saveOnClose ); |
ShowWindow( window ); |
} |
} |
else if ( command.commandID == kHICommandAbout ) // Handle selection of the About Box menu |
{ |
err = CreateWindowFromNib( g.mainNibRef, CFSTR("AboutBox"), &window ); |
if ( err == noErr ) |
{ |
const EventTypeSpec windowEvents[] = { { kEventClassMouse, kEventMouseDown } }; |
err = InstallWindowEventHandler( window, NewEventHandlerUPP( AboutBoxWindowEventHandlerProc ), GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
DisableMenuCommand( NULL, kHICommandAbout ); |
ShowWindow( window ); |
} |
} |
else if ( command.commandID == 'GHlp' ) // Mac OS 8/9 must handle Help menu selection |
{ |
(void) GoToMyHelpAnchor( NULL ); // Pass NULL to go to main page |
} |
else if ( command.commandID == 'XHlp' ) // Our extra help menu item |
{ |
(void) GoToMyHelpAnchor( CFSTR("ImagesAnchor") ); |
} |
} |
break; |
case kEventClassApplication: |
if ( eventKind == kEventAppActivated ) |
SetThemeCursor( kThemeArrowCursor ); |
break; |
} |
return( eventNotHandledErr ); |
} |
static pascal OSStatus MainWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData ) |
{ |
HICommand command; |
ControlRef control; |
SInt32 dataSize; |
EventRef event; |
ThreadID id; |
OSErr err; |
OSStatus result = eventNotHandledErr; |
WindowRef window = (WindowRef) inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
switch ( eventClass ) |
{ |
case kEventClassCommand: |
if ( eventKind == kEventCommandProcess ) |
{ |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
if ( command.commandID == 'SCrs' ) // Popup menu "Small Cursor" |
{ |
if ( g.cursorWindow != NULL ) |
{ |
if ( g.largeCursorActive == true ) |
{ |
RemoveEventHandler( g.largeCursorEventHandlerRef ); |
HideWindow( g.cursorWindow ); |
g.largeCursorActive = false; |
} |
} |
else |
{ |
DisplayAlertWindow( window, "\pOverlay windows are not supported in this configuration." ); |
} |
} |
else if ( command.commandID == 'LCrs' ) // Popup menu "Large Cursor" |
{ |
if ( g.cursorWindow != NULL ) |
{ |
if ( g.largeCursorActive == false ) |
{ |
const EventTypeSpec largeCursorAppEvents[] = { |
{ kEventClassMouse, kEventMouseMoved }, |
{ kEventClassMouse, kEventMouseDragged }, |
{ kEventClassWindow, kEventWindowBoundsChanging } |
}; |
ShowWindow( g.cursorWindow ); |
InstallApplicationEventHandler( g.largeCursorEventHandler, GetEventTypeCount(largeCursorAppEvents), largeCursorAppEvents, (void*)GetWRefCon(window), &g.largeCursorEventHandlerRef ); |
g.largeCursorActive = true; |
} |
} |
else |
{ |
DisplayAlertWindow( window, "\pOverlay windows are not supported in this configuration." ); |
} |
} |
else if ( command.commandID == 'MNme' ) // Machine Name button |
{ |
CFStringRef machineNameCF = GetMachineNameAsCFString(); // Get the FileSharing machine name |
if ( machineNameCF != NULL ) |
{ |
ControlID controlID = { 'MNme', 1 }; |
GetControlByID( window, &controlID, &control ); |
err = SetControlData( control, 0, kControlStaticTextCFStringTag, sizeof(CFStringRef), &machineNameCF ); |
if ( err == errDataNotSupported ) |
{ |
ConstStringPtr pString = CFStringGetPascalStringPtr( machineNameCF, kCFStringEncodingMacRoman ); |
(void) SetControlData( control, 0, kControlStaticTextTextTag, pString[0], pString+1 ); |
} |
Draw1Control( control ); |
CFRelease( machineNameCF ); |
} |
} |
else if ( command.commandID == 'Srch' ) // Launch the "Search Thread Window" |
{ |
CFStringRef cfString; |
ControlID controlID = { 'Extn', 0 }; |
GetControlByID( window, &controlID, &control ); |
err = GetControlData( control, 0, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&cfString, &dataSize ); |
if ( err != noErr ) |
{ |
char name[64]; |
err = GetControlData( control, 0, kControlStaticTextTextTag, 64, name, &dataSize ); |
name[dataSize] = '\0'; |
cfString = CFStringCreateWithCString( NULL, name, CFStringGetSystemEncoding() ); |
} |
result = NewThread( kCooperativeThread, NewThreadEntryUPP((ThreadEntryProcPtr) ProgressThread), (void *)cfString, 0, kCreateIfNeeded, nil, &id ); |
if ( result == noErr ) |
g.numberOfRunningThreads++; // Increment the total number of threads |
} |
else if ( command.commandID == 'IOwr' ) |
{ |
OpenGrabBagSharedFileWithWriteAccess( window ); |
} |
else if ( command.commandID == 'IOrd' ) |
{ |
DisplayDataFromGrabBagSharedFile( window ); |
} |
else if ( command.commandID == 'IOcl' ) |
{ |
CloseGrabBagSharedFile( window ); |
} |
else if ( command.commandID == 'IOsv' ) |
{ |
SaveDataToGrabBagSharedFile( window ); |
} |
else if ( command.commandID == kHICommandClose ) // <command>-W sends this command |
{ // We turn around and send it as a kEventWindowClose |
(void) CreateEvent( NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &event ); |
(void) SetEventParameter( event, kEventParamDirectObject, typeWindowRef, sizeof(window), &window ); |
(void) SendEventToWindow( event, GetUserFocusWindow() ); |
} |
} |
break; |
case kEventClassWindow: |
if ( eventKind == kEventWindowClose ) |
{ |
if ( g.saveOnClose == true ) |
SaveMainWindowPrefs( window ); // Save Prefs |
} |
break; |
} |
return( eventNotHandledErr ); // Use default handlers for things like kHICommandBringAllToFront |
} |
// Event handler for the Preferences window |
static pascal OSStatus PrefsWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
HICommand command; |
EventRef event; |
WindowRef window = (WindowRef) inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
switch ( eventClass ) |
{ |
case kEventClassCommand: |
if ( eventKind == kEventCommandProcess ) |
{ |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
if ( command.commandID == kHICommandClose ) // We turn around and send it as a kEventWindowClose |
{ |
(void) CreateEvent( NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &event ); |
(void) SetEventParameter( event, kEventParamDirectObject, typeWindowRef, sizeof(window), &window ); |
(void) SendEventToWindow( event, GetUserFocusWindow() ); |
} |
} |
break; |
case kEventClassWindow: |
if ( eventKind == kEventWindowClose ) |
{ |
SaveApplicationPrefs( window ); // Save Prefs |
EnableMenuCommand( NULL, kHICommandPreferences ); |
} |
break; |
} |
return( eventNotHandledErr ); |
} |
// We only subscribe to the MouseDown event for the window, so we just send ourselves a kEventWindowClose event, |
// and let thew default handler dispose it. |
static pascal OSStatus AboutBoxWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
HICommand command; |
EventRef event; |
WindowRef window = (WindowRef) inUserData; |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
(void) CreateEvent( NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &event ); |
(void) SetEventParameter( event, kEventParamDirectObject, typeWindowRef, sizeof(window), &window ); |
(void) SendEventToWindow( event, GetUserFocusWindow() ); |
EnableMenuCommand( NULL, kHICommandAbout ); |
return( eventNotHandledErr ); |
} |
// Event handler for the Tab control |
// Derrived from sample in O'Reilly's "Learning Carbon" book, page 298 |
static pascal OSStatus MyTabEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
ControlRef tabControl; |
static short lastTabIndex; |
short controlValue; |
WindowRef window = (WindowRef)inUserData; |
GetControlByID( window, &g.tabControlID, &tabControl ); |
controlValue = GetControlValue( tabControl ); |
if ( controlValue != lastTabIndex ) |
{ |
MySwitchItemOfTabControl( window, tabControl, controlValue ); |
lastTabIndex = controlValue; |
} |
return( eventNotHandledErr ); |
} |
// We must manually display the correct Tab information |
static void MySwitchItemOfTabControl( WindowRef window, ControlRef tabControl, short currentTabIndex ) |
{ |
ControlID controlID; |
ControlRef userPaneControl; |
short i; |
ControlRef selectedPaneControl = NULL; |
int tabList[] = {5, 1, 2, 3, 4, 5}; // Information about this tab, # of tabs, and IDs |
controlID.signature = 'AAPL'; |
for ( i=1 ; i<tabList[0]+1 ; i++ ) |
{ |
controlID.id = tabList[i]; |
GetControlByID( window, &controlID, &userPaneControl ); |
if ( i == currentTabIndex ) |
selectedPaneControl = userPaneControl; |
else |
SetControlVisibility( userPaneControl, false, true ); |
} |
if ( selectedPaneControl != NULL ) |
{ |
(void) ClearKeyboardFocus( window ); |
SetControlVisibility( selectedPaneControl, true, true ); |
} |
Draw1Control( tabControl ); // Redraw the Tab control itself |
} |
static pascal OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, long refcon ) |
{ |
#pragma unused ( appleEvt, reply, refcon ) |
(void) XFSClose( &g.sharedFileRefNum ); // Close shared file, if it's open |
g.done = true; // Quit our event loop |
QuitApplicationEventLoop(); |
return( noErr ); |
} |
// Demonstrates how to use CFPreferences to store simple preferences |
static void SaveApplicationPrefs( WindowRef window ) |
{ |
CFNumberRef saveOnCloseRef; |
ControlRef control; |
ControlID controlID = { 'PChk', 1 }; |
GetControlByID( window, &controlID, &control ); |
g.saveOnClose = (Boolean) GetControlValue( control ); |
saveOnCloseRef = CFNumberCreate( NULL, kCFNumberSInt8Type, &g.saveOnClose ); |
CFPreferencesSetAppValue( CFSTR("AppPrefsSaveOnClose"), saveOnCloseRef, kCFPreferencesCurrentApplication ); |
CFRelease( saveOnCloseRef ); |
(void) CFPreferencesAppSynchronize( kCFPreferencesCurrentApplication ); // Write them to disk! |
} |
static void GetApplicationPrefs( void ) |
{ |
CFNumberRef saveOnCloseRef; |
saveOnCloseRef = CFPreferencesCopyAppValue( CFSTR("AppPrefsSaveOnClose"), kCFPreferencesCurrentApplication ); |
if ( saveOnCloseRef != NULL ) |
{ |
(void) CFNumberGetValue( saveOnCloseRef, kCFNumberSInt8Type, &g.saveOnClose ); |
CFRelease( saveOnCloseRef ); |
} |
else |
{ |
g.saveOnClose = false; |
} |
} |
// Demonstrates how to use CFPreferences to store preferences saved as a CFArray |
static void SaveMainWindowPrefs( WindowRef window ) |
{ |
Rect rect; |
CFNumberRef selectedTab; |
CFNumberRef bounds[4]; |
CFArrayRef boundsArray; |
ControlRef control; |
SInt16 controlValue; |
// Save the window bounds |
SetPortWindowPort( window ); |
GetWindowPortBounds( window, &rect ); |
LocalToGlobal( (Point*) &(rect.top) ); |
LocalToGlobal( (Point*) &(rect.bottom) ); |
bounds[0] = CFNumberCreate( NULL, kCFNumberSInt16Type, &(rect.top) ); |
bounds[1] = CFNumberCreate( NULL, kCFNumberSInt16Type, &(rect.left) ); |
bounds[2] = CFNumberCreate( NULL, kCFNumberSInt16Type, &(rect.bottom) ); |
bounds[3] = CFNumberCreate( NULL, kCFNumberSInt16Type, &(rect.right) ); |
boundsArray = CFArrayCreate( NULL, (const void **)bounds, 4, &kCFTypeArrayCallBacks ); |
CFPreferencesSetAppValue( CFSTR( "MainWindowBounds" ), boundsArray, kCFPreferencesCurrentApplication ); |
CFRelease( boundsArray ); |
CFRelease( bounds[0] ); |
CFRelease( bounds[1] ); |
CFRelease( bounds[2] ); |
CFRelease( bounds[3] ); |
// Save the default Tab |
GetControlByID( window, &g.tabControlID, &control ); |
controlValue = GetControlValue( control ); |
selectedTab = CFNumberCreate( NULL, kCFNumberSInt16Type, &controlValue ); |
CFPreferencesSetAppValue( CFSTR("DefaultTab"), selectedTab, kCFPreferencesCurrentApplication ); |
CFRelease( selectedTab ); |
(void) CFPreferencesAppSynchronize( kCFPreferencesCurrentApplication ); // Write them to disk! |
} |
static void SetMainWindowAttributesFromPrefs( WindowRef window ) |
{ |
Rect rect; |
CFNumberRef selectedTab; |
CFNumberRef bounds[4]; |
CFArrayRef boundsArray; |
ControlRef control; |
SInt16 controlValue; |
Boolean lossyConversion; |
boundsArray = CFPreferencesCopyAppValue( CFSTR( "MainWindowBounds" ), kCFPreferencesCurrentApplication ); |
if ( boundsArray != NULL ) |
{ |
CFRange range = { 0, 4 }; |
CFArrayGetValues( boundsArray, range, (const void **)&bounds ); |
(void) CFNumberGetValue( bounds[0], kCFNumberSInt16Type, &(rect.top) ); |
(void) CFNumberGetValue( bounds[1], kCFNumberSInt16Type, &(rect.left) ); |
(void) CFNumberGetValue( bounds[2], kCFNumberSInt16Type, &(rect.bottom) ); |
(void) CFNumberGetValue( bounds[3], kCFNumberSInt16Type, &(rect.right) ); |
CFRelease( boundsArray ); |
MoveWindow( window, rect.left, rect.top, true ); |
SizeWindow( window, rect.right - rect.left, rect.bottom - rect.top, true ); |
} |
GetControlByID( window, &g.tabControlID, &control ); |
selectedTab = CFPreferencesCopyAppValue( CFSTR("DefaultTab"), kCFPreferencesCurrentApplication ); |
if ( selectedTab != NULL ) |
{ |
lossyConversion = CFNumberGetValue( selectedTab, kCFNumberSInt16Type, &controlValue ); |
CFRelease( selectedTab ); |
SetControlValue( control, controlValue ); |
} |
MySwitchItemOfTabControl( window, control, GetControlValue( control ) ); |
} |
// http://developer.apple.com/qa/qa2001/qa1022.html |
static OSStatus RegisterMyHelpBook( void ) |
{ |
FSRef myBundleRef; |
OSStatus err; |
CFBundleRef myAppsBundle = NULL; |
CFURLRef myBundleURL = NULL; |
myAppsBundle = CFBundleGetMainBundle(); // Get our application's main bundle from Core Foundation |
if ( myAppsBundle == NULL ) { err = fnfErr; goto Bail; } |
myBundleURL = CFBundleCopyBundleURL( myAppsBundle ); // Retrieve the URL to our bundle |
if ( myBundleURL == nil ) { err = fnfErr; goto Bail; } |
if ( ! CFURLGetFSRef( myBundleURL, &myBundleRef ) ) { err = fnfErr; goto Bail; } // Convert the URL to a FSRef |
err = AHRegisterHelpBook(&myBundleRef); // Register our application's help book |
Bail: |
if ( myBundleURL != NULL ) CFRelease( myBundleURL ); |
return( err ); |
} |
// http://developer.apple.com/qa/qa2001/qa1006.html |
static OSStatus GoToMyHelpAnchor( CFStringRef anchorName ) |
{ |
OSStatus err; |
CFBundleRef myAppsBundle = NULL; |
CFTypeRef myBookName = NULL; |
myAppsBundle = CFBundleGetMainBundle(); // Get our application's main bundle from Core Foundation |
if ( myAppsBundle == NULL ) { err = fnfErr; goto Bail; } |
myBookName = CFBundleGetValueForInfoDictionaryKey( myAppsBundle, CFSTR("CFBundleHelpBookName") ); // Get the help book's name |
if ( myAppsBundle == NULL ) { err = fnfErr; goto Bail; } |
if( CFGetTypeID( myBookName ) != CFStringGetTypeID() ) { err = paramErr; goto Bail; } // Verify the data type returned |
if ( anchorName != NULL ) |
err = AHLookupAnchor( myBookName, anchorName ); // Fing and go to the anchor |
else |
err = AHGotoPage( myBookName, NULL, NULL ); // Go to main page |
Bail: |
return( err ); |
} |
// This routine gets the file sharing name of the machine regardless of OS version. On Mac OS 8/9 it gets the name |
// from a resource, on Mac OS X (<10.1) it gets it from the SystemConfiguration/preferences.xml XML file, and On Mac OS X (>=10.1) |
// It calls the Mach-O routine CSCopyMachineNameProc() to retrieve the name. |
typedef pascal CFStringRef (*CSCopyMachineNameProc)(); // Mach-O function deffinition |
static CFStringRef GetMachineNameAsCFString() |
{ |
CFStringRef machineNameCF = NULL; |
if ( RunningOnCarbonX() ) |
{ |
if ( RunningOnCarbonTenPointOneOrHigher() ) |
{ |
CSCopyMachineNameProc CSCopyMachineNameFunc; |
CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR( "com.apple.Carbon" ) ); |
if ( bundle == NULL ) goto Bail; |
CSCopyMachineNameFunc = (CSCopyMachineNameProc) CFBundleGetFunctionPointerForName( bundle, CFSTR("CSCopyMachineName") ); |
if ( CSCopyMachineNameFunc != NULL ) |
machineNameCF = CSCopyMachineNameFunc(); |
} |
else // A bug in Mac OS X 10.0 returns "localhost" rather than the file sharing name |
{ // For Mac OS X 10.0, the answer is to read the name directly out of the System Configuration preferences file. |
CFURLRef url; |
CFDataRef data; |
CFDictionaryRef dict; |
CFDictionaryRef systemDict; |
CFDictionaryRef system2Dict; |
Boolean success; |
url = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, CFSTR("/var/db/SystemConfiguration/preferences.xml"), kCFURLPOSIXPathStyle, FALSE ); |
if ( url == NULL ) goto Bail; |
success = CFURLCreateDataAndPropertiesFromResource( kCFAllocatorDefault, url, &data, NULL, NULL, NULL ); |
if ( (success==true) && (data != NULL) ) |
{ |
dict = CFPropertyListCreateFromXMLData( kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL ); |
if ( dict != NULL ) |
{ |
systemDict = CFDictionaryGetValue( dict, CFSTR("System") ); |
if ( systemDict != NULL ) |
{ |
system2Dict = CFDictionaryGetValue( systemDict, CFSTR("System") ); |
if ( system2Dict != NULL ) |
{ |
machineNameCF = CFDictionaryGetValue( system2Dict, CFSTR("ComputerName") ); |
} |
} |
CFRelease( dict ); |
} |
CFRelease( data ); |
} |
CFRelease( url ); |
} |
} |
else // Running on Mac OS 8/9 |
{ |
#define kMachineNameID -16413 |
SInt16 saveResFile; |
StringHandle stringH; |
saveResFile = CurResFile(); // Save current resource file |
UseResFile( kSystemResFile ); // Make system resource current |
stringH = GetString( kMachineNameID ); |
if ( stringH == NULL ) goto Bail; |
machineNameCF = CFStringCreateWithPascalString( kCFAllocatorSystemDefault, *stringH, kCFStringEncodingMacRoman ); |
UseResFile( saveResFile ); |
} |
Bail: |
return( machineNameCF ); |
} |
void DisplayAlertWindow( WindowRef parentWindow, StringPtr alertS ) |
{ |
OSErr err; |
WindowRef window; |
ControlRef control; |
ControlID controlID = { 'Alrt', 0 }; |
EventTypeSpec windowEvents[] = { { kEventClassControl, kEventControlClick } }; |
err = CreateWindowFromNib( g.mainNibRef, CFSTR("AlertWindow"), &window ); |
if ( err != noErr ) goto Bail; |
GetControlByID( window, &controlID, &control ); |
(void) SetControlData( control, 0, kControlStaticTextTextTag, alertS[0], alertS+1 ); |
err = InstallWindowEventHandler( window, NewEventHandlerUPP( AlertWindowEventHandlerProc ), GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
if ( err != noErr ) goto Bail; |
err = ShowSheetWindow( window, parentWindow ); |
Bail: |
if ( err != noErr ) SysBeep(0); |
return; |
} |
static pascal OSStatus AlertWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData ) |
{ |
return( HideSheetWindow( (WindowRef) inUserData ) ); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-29