В AppStore достаточно много программ, использующих нестандартные заголовки. Не могу судить, пользовались ли они такими методами, но не исключаю такой возможности.
А вы не пробовали смотреть реализацию такого, скажем, в Google Chrome? Может, есть какой-то более-менее «прямой» способ без реверс-инженеринга внутренних классов? Ибо в Apple оооочень просят не юзать недокументированные API, потому что их приложение может легко сломаться в следующих версиях ОС (это касается больше iOS, но для Mac OS X тоже справедливо, в общем-то)
Ну вот здесь автор, вроде как, не использует недокументированные API напрямую, а просто берет superView от самого верхнего view, доступного «просто так» — такое, ИМХО, непросто отловить при автоматическом анализе приложения. Ну а на использование method_exchangeImplementations, насколько я помню, не было ограничений вплоть до iOS 5, в котором, вроде как, исходя из комментариев к этому топику, его больше не рекомендуют использовать.
1. Приватные API в этом примере никто не использует. Имеет место быть рантайм подстановка стандартного метода drawRect: родительского объекта. _drawTitleStringIn — приватный метод, его подстановка — не очень красивое решение, без него, кстати, можно легко обойтись тем же drawRect:
2. Пропустят. Моё приложение в AppStore использует этот принцип для кастомизации окна. BookReader, если что.
А в чём сложность это сделать «легально», просто используя несложный подкласс NSWindow? Примеров масса. В Адресная книга и iCal, я думаю, так и реализовано.
Т.е. смысл использования недокументированного API в данном случае сомнителен (по крайней мере для меня).
Возможно, дело именно в том, что автор юзает не просто Cocoa, а Qt+Cocoa и у него какие-то сложности с тем, чтобы задавать другой класс вместо NSWindow..?
Тут вопрос в простоте. Реализовывать свой сабкласс от NSWindow было быдостаточно дорогим удовольствием, кроме того, для внедрения его в уже готовый проект потребовалось бы много времени.
И да, как заметили ниже, я исходил из ограничений Qt, и очень не хотелось модифицировать пересобирать весь фреймворк ради изменения цвета заголовка окна.
Сложность вот в чем: если вы используете borderless window, окно перестаёт быть resizable. Для MacOS X 10.4-10.6 это не было проблемой, так как ресайзер находился в нижнем правом углу и было раз плюнуть прилепить свой обработчик ресайза. В MacOS X 10.7 Lion ресайз окна происходит со всех сторон, при этом при наведении мыши на край окна нужно менять курсор на стрелочки. Я не хочу сказать, что это невозможно, это возможно, но геморройно. Легче подменить райнтайм метод и сделать все что нужно, даже убрать titlebar.
Сорри, но вы не в теме. Я не знаю какой вам кайф писать о том, в чем не разбираетесь, но хоть бы удосужились посмотреть что делает пример по вашей ссылке.
А делает он в основном следующее:
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.
Не кипятитесь, я нисколько не сомневаюсь в Вашей компетенции, уступлю (если это так важно) — я не гордый.
lymes просто показал, что приведённый Вами способ использует всё тот же NSThemeFrame, но при этом не делается никаких проверок. Тут тоже, можно сказать, используются недокументированные возможности — как минимум, некоторые факты из жизни NSThemeFrame. Хоть и неявно.
Неа, не опровергает. Объясню почему: в приведенном вами примере не используется borderless window, а используется некий костыль, прилепленный к тому же приватному NSThemeFrame.
Этот костыль (кастомнй тайтлбар на основе NSView),
— добавляет оверхед в интерфейс,
— точно так же затрагивает приватную часть окна (NSThemeFrame)
Чистое же решение, классический пример кастомизации NSWindow — это объект с флагом NSBorderlessWindowMask в маске стилей. И в этом случае код имплементации окна для Лайон действительно займёт намного больше.
И да, чуть не забыл, в Лайон borderless окна не могут быть full-screen. Из-за этого приведенный автором статьи пример кастомизации окна остаётся чуть ли не единственно приемлемым.
Если это иконка самого приложения (которая будет отображаться в Finder'е), то в .pro файле надо написать что-то типа того:
macx: ICON = myicon.icns
Сам файл .icns можно сделать в любом редакторе, его поддерживающем, так же существуют онлайн-конвертеры, которым можно скормить несколько png файлов разного размера и получить на выходе .icns для программы.
Если же нужно установить иконку для конкретного окна, то всё ещё проще — QWidget::setWindowIcon() или QApplication::setWindowIcon().
А вообще, это очень хорошо описано в документации.
Кастомизация заголовка окна в Mac OS X