Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 38 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
38
Dung lượng
210,72 KB
Nội dung
#define kPopUpSizeSmallCommand 'pop1' #define kPopUpSizeMediumCommand 'pop2' #define kPopUpSizeLargeCommand 'pop3' pascal OSStatus CommandEventHandler( EventHandlerCallRef handlerRef, EventRef event, void *userData ); void PopUpCommandHandler ( WindowRef window, UInt32 command ); int main( int argc, char* argv[] ) { IBNibRef nibRef; WindowRef window; OSStatus err; EventTargetRef target; EventHandlerUPP handlerUPP; EventTypeSpec cmdEvent = { kEventClassCommand, kEventProcessCommand }; err = CreateNibReference( CFSTR("main"), &nibRef ); err = SetMenuBarFromNib( nibRef, CFSTR("MainMenu") ); err = CreateWindowFromNib( nibRef, CFSTR("MainWindow"), &window ); DisposeNibReference( nibRef ); target = GetWindowEventTarget( window ); handlerUPP = NewEventHandlerUPP( CommandEventHandler ); InstallEventHandler( target, handlerUPP, 1, &cmdEvent, (void *)window, NULL ); ShowWindow( window ); RunApplicationEventLoop(); return( 0 ); } pascal OSStatus CommandEventHandler( EventHandlerCallRef handlerRef, EventRef event, void *userData) { OSStatus result = eventNotHandledErr; HICommand command; WindowRef window; window = ( WindowRef )userData; GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof (HICommand), NULL, &command); switch ( command.commandID ) { case kPopUpSizeSmallCommand: PopUpCommandHandler( window, kPopUpSizeSmallCommand ); result = noErr; break; case kPopUpSizeMediumCommand: PopUpCommandHandler( window, kPopUpSizeMediumCommand ); result = noErr; break; case kPopUpSizeLargeCommand: PopUpCommandHandler( window, kPopUpSizeLargeCommand ); result = noErr; break; } return result; } void PopUpCommandHandler( WindowRef window, UInt32 command ) { // { T, L, B, R } Rect whiteRect = { 60, 10, 90, 270 }; Pattern white; SetPortWindowPort( window ); GetQDGlobalsWhite( &white ); FillRect( &whiteRect, &white ); MoveTo( 30, 80 ); switch ( command ) { case kPopUpSizeSmallCommand: DrawString( "\pYou chose the size Small shirt." ); break; case kPopUpSizeMediumCommand: DrawString( "\pThe size Medium shirt was selected." ); break; case kPopUpSizeLargeCommand: DrawString( "\pThat was the size Large shirt." ); break; } } Book: Mac® OS X Programming Section: Chapter 6. Menus For More Information The following web sites provide extra information about some of this chapter's topics: ● Menu GUI guidelines: http://developer.apple.com/techpubs/macosx/Carbon/ HumanInterfaceToolbox/Aqua/aqua.html ● Menu manager routines: http://developer.apple.com/techpubs/macosx/Carbon/ HumanInterfaceToolbox/MenuManager/Menu_Manager/index.html Book: Mac® OS X Programming Chapter 7. QuickDraw Graphics WHAT IS QUICKDRAW? You're asking that question just a little late. QuickDraw is a large set of Carbon API routines that enables programmers to draw simple shapes such as lines, rectangles, and ovals. All the programs in this book, as well as the programs you created, relied on QuickDraw. That's because QuickDraw is all about drawing, including the drawing of interface items such as windows and menus. The routines in the Carbon API are conceptually categorized into separate areas. Each area consists of routines that, for the most part, work with a single programming topic. Each Carbon area can have a name that includes "Manager," such as Window Manager, Menu Manager, and Carbon Event Manager. On the other hand, some Carbon API areas don't include "Manager" in their names. QuickDraw is one such area. In this chapter, you'll see how to draw shapes, as well as how to enhance the look of such shapes by filling them with monochrome or colored patterns. Book: Mac® OS X Programming Section: Chapter 7. QuickDraw Graphics QuickDraw Basics So, you're ready to jump right into drawing a fancy shape such as an oval filled with a checkerboard pattern, right? No you aren't! Before drawing shapes, make sure that you know about the graphics grid that's used to define the size and window location of a shape. You also need to know how to go about setting drawing parameters, such as the thickness of the lines used to draw shapes. Topics such as these are covered in this section. Coordinate System When your program draws, it needs to specify where to draw. There are two components to this specification. Your program should specify the window to which to draw, and it should specify where in that window the drawing is to take place. Drawing always takes place in a port, which is a graphics entity used to hold information about a drawing. Every window has its own port, and the screen (monitor) itself includes a port. The screen's port makes it possible for the desktop to be displayed. Note that the desktop isn't a window, yet it gets drawn to. A window's port makes it possible to specify to which window to draw, in the event a program enables more than one window at a time to be open. You tell your program which port to draw to by passing to the SetPortWindowPort routine the window in which the drawing will occur. Typically, this is done within a window update routine, before any drawing takes place: void UpdateWindow( WindowRef window ) { SetPortWindowPort( window ); // now start drawing } Specifying where within a window a drawing should take place is done by specifying the coordinates at which to draw. Macintosh windows make use of a coordinate grid system. In this system, every pixel in the content area of a window is defined by a coordinate pair. The content area is the area drawn to. This area excludes the window title bar and scroll bars, if present. The grid is a coordinate system that has a horizontal component and a vertical component. The upper- left pixel in a window's content area has a horizontal component of 0 (zero pixels from the left side of the window) and a vertical component of 0 (zero pixels from the top of the window). The horizontal component of the pair is specified first, followed by the vertical component. Thus, the upper-left pixel of a window is referred to as (0, 0). To specify the pixel located 20 pixels in from the left side of the window, but still in the uppermost row of pixels, you'd refer to the pixel as (20, 0). Figure 7.1 illustrates this. In this figure, the circled pixel is 60 pixels in from the left side of the window and 20 pixels down from the top of the window, so to reference this one pixel, you'd use the coordinate pair of (60, 20). Figure 7.1. The coordinate system of a window. In Chapter 4, "Windows," the example program WindowUpdate used a graphics grid. There, before a string of text was drawn, the MoveTo routine was called to specify the starting point for drawing. That code specified that the drawing should start 30 pixels from the left side of the window and 60 pixels down from the top of the window: MoveTo( 30, 60 ); DrawString( "\pThis is drawn from code!" ); The MoveTo routine specifies the starting location for drawing based on a coordinate pair global to the window. Another routine, Move, specifies the starting location based on the current drawing location. Here are the prototypes for those two routines: void MoveTo( SInt16 h, SInt16 v ); void Move( SInt16 h, SInt16 v ); To see these routines used in conjunction with one another, consider this snippet: MoveTo( 40, 80 ); Move( 70, 10 ); The call to MoveTo moves the starting location to the pixel 40 pixels in from the left side of the window and 80 pixels down from the top of the window. The call to Move moves the starting point 70 pixels to the left of its current position of 40 pixels in, and 10 pixels down from its current position of 80 pixels down. After both routines execute, the result is that the new starting position for drawing is at pixel ( 110, 90 ). To use Move to move the starting position to the left or up, use negative values. For instance, to move the starting position left 10 pixels and up 20 pixels, call Move like this: Move( -10, -20 ); Line and Shape Drawing and the Graphics Environment Each port has its own graphics environment. That is, a port has a set of properties that a program makes use of when drawing to that port. Consider this snippet: SetPortWindowPort( window ); MoveTo( 20, 60 ); LineTo( 120, 60 ); The preceding call to MoveTo specifies that the drawing should start 20 pixels from the left side of the window and 60 pixels down from the top of that window. LineTo is a drawing routine that draws a line from the current starting location to the specified ending location. The call to LineTo specifies that a line should be drawn from that starting point and extend to the point 120 pixels from the left side of the window and 60 pixels down from the top of the window. The result is a horizontal line 100 pixels in length. That line will be black, and it will have a thickness of one pixel. The line has these attributes because a graphics port has a graphics environment, and that environment assigns its various fields default values. One of those fields is line thickness, which is initially set to one pixel. Collectively, these fields that affect line and shape drawing make up a conceptual drawing device referred to as the graphics pen. There are a few access routines that enable you to change the attributes of the graphics pen. You've already seen that Move and MoveTo move the graphics pen (though you might not have known that what was being affected by these routines was, in fact, the graphics pen). To change the pixel size of lines drawn in a port, call SetPortPenSize: void SetPortPenSize( CGrafPtr port, Point penSize ); A CGrafPtr is a pointer to a color graphics port, which is the type of port associated with a window. Rather than simply passing the WindowRef , you need to pass a pointer to the window's port. That's easy enough to do with the GetWindowPort routine. Assuming the window is a WindowRef variable, here's how you can change the size of the graphics pen so that it draws lines that have a height of 8 pixels and a width of 5 pixels: Point thePenSize = { 8, 5 }; SetPortPenSize( GetWindowPort( window ), thePenSize ); Use the PenNormal routine to return the current port's graphics pen to its initial, or default, state: PenNormal(); Text Drawing and the Graphics Environment The characteristics of text drawn to a window also are under the control of the port's graphics environment, though the graphics pen won't affect the look of the text. For instance, if you call SetPortPenSize to change the thickness of the graphics pen, the thickness of lines will be affected, but the thickness of the text won't be. To change the look of the text, use any of the following routines: void TextFont( SInt16 font); void TextFace( StyleParameter face ); void TextSize( SInt16 size ); TextFont establishes the font used in drawing text to the current graphics port. The font parameter specifies the font family ID. Each font is considered a family, and each family has an ID. A font family ID of 0 is used to represent the system font. This system font ID is the initial value that a graphics port uses for the display of text. Rather than trying to determine what ID is associated with any one font family, simply use the FMGetFontFamilyFromName routine to let the system supply your program with this information. Pass FMGetFontFamilyFromName the exact name of a font, prefaced with \ p, and the routine returns the ID for that font. Use that value in a call to TextFont: FMFontFamily fontFamily; fontFamily = FMGetFontFamilyFromName( "\pTimes" ); TextFont( fontFamily ); TextFace sets the style of the font in which text is drawn. The face parameter can be any one, or any combination, of the following constants: normal, bold, italic, underline, outline, shadow, condense, and extend. To set the face to one particular style, use the appropriate style constant. After the following call, all text drawn with DrawString will be in bold: TextFace( bold ); To set the face to a combination of styles, use a plus () sign between each style: TextFace( italic + underline + shadow ); To change the size of text drawn to a window, use the TextSize routine. Pass a size in points. A 12- point size is common and is considered a de facto standard for text. The initial setting for the text size is 0, which represents the size of the system font. This line of code sets the text size to twice the normal size: TextSize( 24 ); GraphicsPortAndPen Program The purpose of the GraphicsPortAndPen program is to provide an example of the effects of making changes to a window's graphics environment. The GraphicsPortAndPen program draws three horizontal lines, making changes to the graphics pen between the drawing of each line. The program also draws three lines of text, making changes to the graphics environment before drawing each line of text. Figure 7.2 shows the window that this program displays. Figure 7.2. Altering a window's graphics environment affects line and text drawing. Example 7.1 provides the source code for the GraphicsPortAndPen program. Most of the code that makes up this program was introduced in the WindowUpdate program found in Chapter 4. Of interest here is only the application-defined UpdateWindow routine. All the Carbon calls in UpdateWindow have been discussed on the preceding pages. One point worth discussing is the length of the three horizontal lines that UpdateWindow draws. Each line is drawn by calling Line. The Line routine draws a line of the specified length, regardless of where the current starting point is. Notice in Figure 7.2 that the middle line is slightly longer than the other two lines, despite the fact that each line is drawn with the same arguments passed to Line. The reason the middle line is longer is that before it is drawn, the size of the graphics pen is set to a height and width of 10 pixels. It is the change in pixel width of the pen that affects the overall length of the line that's subsequently drawn. The call to Line does indeed draw a line 100 pixels in length, but because the pen's width is 10 pixels rather than 1, that extra width shows up after the line is drawn. The bulk of the source code in all the examples in this chapter is similar. In fact, only the UpdateWindow routine in each program varies. All the rest of the code in each example is identical. For that reason, only this first example shows the entire source code listing. After this example, each following example shows only the routine that holds new code-the UpdateWindow routine. Example 7.1 GraphicsPortAndPen UpdateWindow Source Code #include <Carbon/Carbon.h> pascal OSStatus WindowEventHandler( EventHandlerCallRef handlerRef, EventRef event, void *userData ); void UpdateWindow( WindowRef window ); int main(int argc, char* argv[]) { IBNibRef nibRef; OSStatus err; WindowRef window; EventTargetRef target; EventHandlerUPP handlerUPP; EventTypeSpec windowEvent = { kEventClassWindow, kEventWindowDrawContent }; err = CreateNibReference( CFSTR("main"), &nibRef ); err = SetMenuBarFromNib( nibRef, CFSTR("MainMenu") ); err = CreateWindowFromNib( nibRef, CFSTR("MainWindow"), &window ); DisposeNibReference( nibRef ); target = GetWindowEventTarget( window ); handlerUPP = NewEventHandlerUPP( WindowEventHandler ); InstallEventHandler( target, handlerUPP, 1, &windowEvent, (void *)window, NULL ); ShowWindow( window ); RunApplicationEventLoop(); return( 0 ); } pascal OSStatus WindowEventHandler( EventHandlerCallRef handlerRef, EventRef event, void *userData) { OSStatus result = eventNotHandledErr; UInt32 eventKind; WindowRef window; window = ( WindowRef )userData; eventKind = GetEventKind( event ); if ( eventKind == kEventWindowDrawContent ) { UpdateWindow( window ); } return result; } void UpdateWindow( WindowRef window ) { [...]... DisposePixPat( blueDiagonalPixPat ); } Book: Mac OS X Programming Section: Chapter 7 QuickDraw Graphics For More Information For more information about QuickDraw and Macintosh graphics, stop in at any of the following web sites: q ResEdit resource editor: http://developer.apple.com/tools/ q QuickDraw routines: http://developer.apple.com/techpubs/macosx/Carbon/ grahics/QuickDraw/quickdraw.html Book: Mac ... the line so that the line's pattern is more readily noticeable Example 7. 4 PixPatResource UpdateWindow Source Code #define kPixPatBlueDiagonal 128 void UpdateWindow( WindowRef window ) { PixPatHandle blueDiagonalPixPat; Rect theRect; SetPortWindowPort( window ); blueDiagonalPixPat = GetPixPat( kPixPatBlueDiagonal ); PenPixPat( blueDiagonalPixPat ); PenSize( 10, 10 ); MoveTo( 20, 20 ); Line( 220, 60 );... should dispose of the memory referenced by that handle A call to the Carbon routine DisposePixPat takes care of that task: DisposePixPat( blueDiagonalPixPat ); PixPatResource Program The purpose of the PixPatResource program is to demonstrate how a program uses a programmer-defined color pattern resource (ppat) to draw patterned lines and shapes Figure 7. 11 shows the window displayed by the PixPatResource... blue lines, in case you're curious) As you turn pixels on and off in the magnified view of the pattern in left box of the two boxes at the top of the pixel editor, the right-most box shows how the pattern will look when drawn at actual size in an area larger than 8x8 pixels Figure 7. 9 Creating a ppat resource in ResEdit After creating the ppat resource, choose Save from the File menu to save the file in... System Preferences and then run the program Book: Mac OS X Programming Section: Chapter 8 Text and Localization Localizing Window Content Text An application might be able to display all its text as static text items in window resources However, that's likely only for the most trivial of programs An application also might be able to display all its text using the QuickDraw routine DrawString That's... The final GetIndPattern parameter is an index to the pattern to retrieve Pattern numbering in a list starts with the number 1 Figure 7. 7 shows the 38 patterns and their associated index value In the previous code snippet, the twelfth pattern in the list (the pattern that looks like bricks in Figure 7. 7) is being sought Figure 7. 7 The patterns, with their index values, from the system pattern list After... &patternRect, 70 , 0 ); } SetRect( &patternRect, 30, 120, 50, 140 ); for ( x = 1; x . http://developer.apple.com/techpubs/macosx/Carbon/ HumanInterfaceToolbox/Aqua/aqua.html ● Menu manager routines: http://developer.apple.com/techpubs/macosx/Carbon/ HumanInterfaceToolbox/MenuManager/Menu_Manager/index.html. moves the starting point 70 pixels to the left of its current position of 40 pixels in, and 10 pixels down from its current position of 80 pixels down. After both routines execute, the result is. pixel of a window is referred to as (0, 0). To specify the pixel located 20 pixels in from the left side of the window, but still in the uppermost row of pixels, you'd refer to the pixel