Chapter 4 Windows
1 Window Update
1. 可以调用ShowWindow和HideWindow来显示/隐藏窗口。
2. DrawString作用是在当前Graphics Pen位置显示字符串
3. MoveTo移动当前Graphics Pen
Window绘图的时候发送Update事件:
EventTypeSpec windowEvent = { kEventClassWindow, kEventWindowDrawContent }; |
下面代码安装一个Update事件处理函数:
EventTargetRef target;
EventHandlerUPP handlerUPP; EventTypeSpec windowEvent = { kEventClassWindow, kEventWindowDrawContent };
target = GetWindowEventTarget( window ); handlerUPP = NewEventHandlerUPP( WindowEventHandler ); InstallEventHandler( target, handlerUPP, 1, &windowEvent, (void *)window, NULL ); |
Update事件处理函数可以这么写:
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; } |
在UpdateWindow中必须首先调用SetPortWindowPort用来指定当前绘图所用的Port(这名字还真怪)。Port是用来定义一个绘图环境的(类似Windows中的设备上下文DC)。每个窗口都有一个Port。屏幕也被认为是一个Port。如果不调用SetPortWindowPort,程序的行为将无法预测。
void UpdateWindow( WindowRef window ) { SetPortWindowPort( window ); // code to draw the contents of the window goes here } |
一个完整的UpdateWindow示例如下:
void UpdateWindow( WindowRef window ) { FMFontFamily fontFamily;
SetPortWindowPort( window );
fontFamily = FMGetFontFamilyFromName( "/pTimes" ); TextFont( fontFamily ); TextFace( bold + italic ); TextSize( 24 ); MoveTo( 30, 60 ); DrawString( "/pThis is drawn from code!" ); } |
/p表示字符串为一个Pascal String。
2 Associating Information with Windows
在Mac OS X中可以把数据和Window相关联起来,所调用的函数为SetWindowProperty和GetWindowProperty。
SetWindowProperty的原型如下:
OSStatus SetWindowProperty( WindowRef window, PropertyCreator propertyCreator, PropertyTag propertyTag, UInt32 propertySize, void * propertyBuffer ); |
1. PropertyCreate propertyCreator:Application的Signature,四个Char组成。可以传0
2. PropertyTag propertyTag:四个Char的Property的标记
3. Uint32 propertySize:property的大小(字节数)
4. Void *propertyBuffer:指向实际数据
GetWindowProperty的原型如下:
OSStatus GetWindowProperty( WindowRef window, PropertyCreator propertyCreator, PropertyTag propertyTag, UInt32 bufferSize, UInt32 * actualSize, void * propertyBuffer ); |
1. PropertyCreate propertyCreator:Application的Signature,四个Char组成。可以传0
2. PropertyTag propertyTag:四个Char的Property的标记
3. Uint32 propertySize:property的大小(字节数)
4. Uint32 *actualSize:实际大小,可传NULL
5. Void *propertyBuffer:指向实际数据
举例如下:
UInt32 windowNumber = 99; WindowRef window; UInt32 theNumber; ... err = CreateWindowFromNib( nibRef, CFSTR("MainWindow"), &window ); ... // associate the data (99) in variable windowNumber with a window: SetWindowProperty( window, 0, 'test', sizeof( UInt32 ), &windowNumber ); ... // retrieve the data (99) from the window and store it in theNumber: GetWindowProperty( window, 0, 'test', sizeof( UInt32 ), NULL, &theNumber ); |
如何将Structure和window相关联呢?
1. 定义下面这个Structure
typedef struct { UInt32 number; Str255 string; } WindowData, **WindowDataHandle; |
2. 创建一个Handle,相当于分配一块内存,大小为sizeof(WindowData)
WindowDataHandle windDataHndl; windDataHndl = ( WindowDataHandle )NewHandle( sizeof( WindowData ) ); |
3. 给Handle所指向的数据赋值。注意WindowDataHandle是指针的指针(为什么是指针的指针呢?因为NewHandle创建的是一块可重定位的内存)
UInt32 theNumber = 5; (**windDataHndl).number = theNumber;
Str255 theString = "/pCopyright (c) 2001" numBytes = theString[0] + 1; BlockMoveData( theString, (**windDataHndl).string, numBytes ); |
Str255本质上其实是一个数组,最多可以Hold255个字符。第一个元素是String大小(Pascal String正是这样),所以theString[0] + 1可以获得实际大小
4. 之后调用SetWindowProperty(我觉得这里似乎错了,应该是sizeof(WindowDataHandle),而不是sizeof(WindowData),待验证)
SetWindowProperty(window, 0, 'test', sizeof(WindowData), &windDataHndl); |
5. 如果要获得Property,可以调用GetWindowProperty(我觉得这里似乎错了,应该是sizeof(WindowDataHandle),而不是sizeof(WindowData),待验证)
GetWindowProperty( window, 0, 'test', sizeof( WindowData ), NULL, &windDataHndl ); |
(BTW,这本书我越看下去越觉得烂。。。。)