Q: 私のアプリケーションは、Mac OS X 10.2 (Jaguar) で HIThemexxx を実行するとクラッシュします。なぜでしょうか?
A: Mac OS X 10.3 で導入され、一般に公開された HITheme API のほとんど(下記のリストを参照)は、Mac OS X 10.2 では非公開であり、その引数リストが異なっていたためです。
HITheme API はすべてのバージョンの Mac OS X で使用可能なものではないため、弱いリンクを使用し、実行時には、呼び出し前に利用可能かどうかをテストする必要がありますが、問題もあります。最もよく利用されているテストメカニズムは、単に特定の API 名と NULL を照合しているに過ぎません(リスト 1 を参照)。
リスト 1: 弱くリンクされた API の一般的なランタイムチェック
if ( HIThemeGetTextDimensions != NULL )
HIThemeGetTextDimensions( ... );
else
GetThemeTextDimensions( ... );
しかし、Mac OS X 10.2 では、非公開ではあっても、大部分の HITheme API があるため、上記のテストでは HITheme API が実行されます。 残念ながら、それらの API が Mac OS X 10.2 で予想していた引数のリストは、Mac OS X 10.3 に導入されたときに最終的に公開された引数のリストと異なっています。 Mac OS X 10.3(以降)で想定している引数リストを使って、 Mac OS X 10.2 で HITheme API を呼び出そうとすると、Mac OS X 10.2 ではクラッシュを引き起こすことになります。
Mac OS X 10.2 の非公開の HITheme API の完全なリスト: -
HIThemeApplyBackground -
HIThemeDrawButton -
HIThemeDrawChasingArrows -
HIThemeDrawFocusRect -
HIThemeDrawGenericWell -
HIThemeDrawGrabber -
HIThemeDrawMenuBackground -
HIThemeDrawMenuBarBackground -
HIThemeDrawMenuItem -
HIThemeDrawMenuSeparator -
HIThemeDrawMenuTitle -
HIThemeDrawPaneSplitter -
HIThemeDrawPlacard -
HIThemeDrawPopupArrow -
HIThemeDrawScrollBarDelimiters -
HIThemeDrawSeparator -
HIThemeDrawTab -
HIThemeDrawTabPane -
HIThemeDrawTextBox -
HIThemeDrawTickMark -
HIThemeDrawTitleBarWidget -
HIThemeDrawTrack -
HIThemeDrawTrackTickMarks -
HIThemeDrawWindowFrame -
HIThemeGetButtonBackgroundBounds -
HIThemeGetButtonContentBounds -
HIThemeGetScrollBarTrackRect -
HIThemeGetTextDimensions -
HIThemeGetTrackBounds -
HIThemeGetTrackDragRect -
HIThemeGetTrackLiveValue -
HIThemeGetTrackPartBounds -
HIThemeGetTrackParts -
HIThemeGetTrackThumbPositionFromOffset -
HIThemeGetWindowRegionHit -
HIThemeHitTestScrollBarArrows -
HIThemeHitTestTrack
そのため、このような状況における正しい解決策は、HITheme API を呼び出す前に(リスト 2 を参照)、リスト 3 に示す GetHIToolboxVersion 関数を使用して HIToolbox のバージョンのチェックをすることです。 リスト 2: HIToolbox バージョンのチェック
if ( GetHIToolboxVersion() >= 0x130)
HIThemeGetTextDimensions( ... );
else
GetThemeTextDimensions( ... );
リスト 3: GetHIToolboxVersion.
UInt32 GetHIToolboxVersion()
{
CFBundleRef bundle;
CFStringRef versStr = NULL;
static UInt32 version = 0;
// 負荷の重い次のコードを一度だけ実行する ...
if (version != 0) return version;
bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
if ( bundle != NULL )
versStr = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle,
CFSTR("CFBundleShortVersionString"));
if ( versStr != NULL &&
CFGetTypeID(versStr) == CFStringGetTypeID())
{
int major = 0, minor = 0, bugfix = 0;
char sz[20];
CFStringGetCString(versStr, sz, sizeof(sz), kCFStringEncodingUTF8);
sscanf(sz, "%d.%d.%d", &major, &minor, &bugfix);
version = ( major << 8 ) + ( minor << 4 ) + bugfix;
}
return version;
}
ドキュメントの改訂履歴
掲載日: 2004-10-19
|