Комментарии 22
В App Store, интересно, пропустят, если использовать приватные API? Что-то мне подсказывает, что нет
В AppStore достаточно много программ, использующих нестандартные заголовки. Не могу судить, пользовались ли они такими методами, но не исключаю такой возможности.
А вы не пробовали смотреть реализацию такого, скажем, в Google Chrome? Может, есть какой-то более-менее «прямой» способ без реверс-инженеринга внутренних классов? Ибо в Apple оооочень просят не юзать недокументированные API, потому что их приложение может легко сломаться в следующих версиях ОС (это касается больше iOS, но для Mac OS X тоже справедливо, в общем-то)
> это касается больше iOS
Они не просят, они просто отклоняют такие приложения
Они не просят, они просто отклоняют такие приложения
Ну вот здесь автор, вроде как, не использует недокументированные API напрямую, а просто берет superView от самого верхнего view, доступного «просто так» — такое, ИМХО, непросто отловить при автоматическом анализе приложения. Ну а на использование method_exchangeImplementations, насколько я помню, не было ограничений вплоть до iOS 5, в котором, вроде как, исходя из комментариев к этому топику, его больше не рекомендуют использовать.
1. Приватные API в этом примере никто не использует. Имеет место быть рантайм подстановка стандартного метода drawRect: родительского объекта. _drawTitleStringIn — приватный метод, его подстановка — не очень красивое решение, без него, кстати, можно легко обойтись тем же drawRect:
2. Пропустят. Моё приложение в AppStore использует этот принцип для кастомизации окна. BookReader, если что.
2. Пропустят. Моё приложение в AppStore использует этот принцип для кастомизации окна. BookReader, если что.
Было бы интересно почитать про хитрости взаимодействия Qt с Cocoa
А в чём сложность это сделать «легально», просто используя несложный подкласс NSWindow? Примеров масса. В Адресная книга и iCal, я думаю, так и реализовано.
Т.е. смысл использования недокументированного API в данном случае сомнителен (по крайней мере для меня).
Т.е. смысл использования недокументированного API в данном случае сомнителен (по крайней мере для меня).
Возможно, дело именно в том, что автор юзает не просто Cocoa, а Qt+Cocoa и у него какие-то сложности с тем, чтобы задавать другой класс вместо NSWindow..?
Тут вопрос в простоте. Реализовывать свой сабкласс от NSWindow было быдостаточно дорогим удовольствием, кроме того, для внедрения его в уже готовый проект потребовалось бы много времени.
И да, как заметили ниже, я исходил из ограничений Qt, и очень не хотелось модифицировать пересобирать весь фреймворк ради изменения цвета заголовка окна.
И да, как заметили ниже, я исходил из ограничений Qt, и очень не хотелось модифицировать пересобирать весь фреймворк ради изменения цвета заголовка окна.
Сложность вот в чем: если вы используете borderless window, окно перестаёт быть resizable. Для MacOS X 10.4-10.6 это не было проблемой, так как ресайзер находился в нижнем правом углу и было раз плюнуть прилепить свой обработчик ресайза. В MacOS X 10.7 Lion ресайз окна происходит со всех сторон, при этом при наведении мыши на край окна нужно менять курсор на стрелочки. Я не хочу сказать, что это невозможно, это возможно, но геморройно. Легче подменить райнтайм метод и сделать все что нужно, даже убрать titlebar.
Я детально не изучал этот вопрос. Но гугл в первых же ссылках приводит пример — github.com/indragiek/INAppStoreWindow.
Небольшой подкласс NSWindow со всеми вытекающими. Пример программы оттуда же работает без каких-либо проблем.
Небольшой подкласс NSWindow со всеми вытекающими. Пример программы оттуда же работает без каких-либо проблем.
Сорри, но вы не в теме. Я не знаю какой вам кайф писать о том, в чем не разбираетесь, но хоть бы удосужились посмотреть что делает пример по вашей ссылке.
А делает он в основном следующее:
NSView *themeFrame = [contentView superview]; // берем NSThemeFrame
NSView *firstSubview = [[themeFrame subviews] objectAtIndex:0]; // берем первую дочернюю NSView
[_titleBarView setAutoresizingMask:(NSViewMinYMargin | NSViewWidthSizable)];
[self _recalculateFrameForTitleBarView];
[themeFrame addSubview:_titleBarView positioned:NSWindowBelow relativeTo:firstSubview]; // добавляем самодельный тайтлбар к NSThemeFrame под первой дочерней NSView
если учесть, что настоящий titlebar не обязательно может быть первым в NSThemeFrame, и никакой проверки по рантайм классу не сделано, то этот пример можно смело выкидывать на свалку говнокода.
А делает он в основном следующее:
NSView *themeFrame = [contentView superview]; // берем NSThemeFrame
NSView *firstSubview = [[themeFrame subviews] objectAtIndex:0]; // берем первую дочернюю NSView
[_titleBarView setAutoresizingMask:(NSViewMinYMargin | NSViewWidthSizable)];
[self _recalculateFrameForTitleBarView];
[themeFrame addSubview:_titleBarView positioned:NSWindowBelow relativeTo:firstSubview]; // добавляем самодельный тайтлбар к NSThemeFrame под первой дочерней NSView
если учесть, что настоящий titlebar не обязательно может быть первым в NSThemeFrame, и никакой проверки по рантайм классу не сделано, то этот пример можно смело выкидывать на свалку говнокода.
Ух, как Вы грозно. Я не понимаю, зачем быть в какой-то «теме», чтобы увидеть, что первый же приведённый пример по ссылке — это NSWindow с полностью кастомным «легальным» заголовком, и он ровно опровергает Ваши доводы про «ресайз» в 10.7.
Не кипятитесь, я нисколько не сомневаюсь в Вашей компетенции, уступлю (если это так важно) — я не гордый.
Не кипятитесь, я нисколько не сомневаюсь в Вашей компетенции, уступлю (если это так важно) — я не гордый.
Неа, не опровергает. Объясню почему: в приведенном вами примере не используется borderless window, а используется некий костыль, прилепленный к тому же приватному NSThemeFrame.
Этот костыль (кастомнй тайтлбар на основе NSView),
— добавляет оверхед в интерфейс,
— точно так же затрагивает приватную часть окна (NSThemeFrame)
Чистое же решение, классический пример кастомизации NSWindow — это объект с флагом NSBorderlessWindowMask в маске стилей. И в этом случае код имплементации окна для Лайон действительно займёт намного больше.
Этот костыль (кастомнй тайтлбар на основе NSView),
— добавляет оверхед в интерфейс,
— точно так же затрагивает приватную часть окна (NSThemeFrame)
Чистое же решение, классический пример кастомизации NSWindow — это объект с флагом NSBorderlessWindowMask в маске стилей. И в этом случае код имплементации окна для Лайон действительно займёт намного больше.
Очень интересно про Qt. У меня здоровенная софтина на Qt и хочется ей кастомизировать заголовок.
А пока, увы, даже иконку сделать не получается =((
А пока, увы, даже иконку сделать не получается =((
Иконка делается элементарно.
Если это иконка самого приложения (которая будет отображаться в Finder'е), то в .pro файле надо написать что-то типа того:
Сам файл .icns можно сделать в любом редакторе, его поддерживающем, так же существуют онлайн-конвертеры, которым можно скормить несколько png файлов разного размера и получить на выходе .icns для программы.
Если же нужно установить иконку для конкретного окна, то всё ещё проще — QWidget::setWindowIcon() или QApplication::setWindowIcon().
А вообще, это очень хорошо описано в документации.
Если это иконка самого приложения (которая будет отображаться в Finder'е), то в .pro файле надо написать что-то типа того:
macx: ICON = myicon.icns
Сам файл .icns можно сделать в любом редакторе, его поддерживающем, так же существуют онлайн-конвертеры, которым можно скормить несколько png файлов разного размера и получить на выходе .icns для программы.
Если же нужно установить иконку для конкретного окна, то всё ещё проще — QWidget::setWindowIcon() или QApplication::setWindowIcon().
А вообще, это очень хорошо описано в документации.
Яхууу! Спасибо, не буду париться написанием своего солюшена :)
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Кастомизация заголовка окна в Mac OS X