2009-10-06 6 views
7

Я ищу, чтобы сделать пользовательское окно, которое будет выглядеть примерно так (не возражаете быстрый Photoshop):Как создать прозрачное окно с непрямоугольными кнопками?

alt text http://i35.tinypic.com/20ff803.png

Основная проблема, которую я не сделать окно прозрачным (хотя я предполагаю, что любой информация приветствуется!), но я хочу, чтобы иметь возможность нажимать только на видимую часть кнопок. Например, если я нажимаю только левую верхнюю часть кнопки «5», я хочу, чтобы он зарегистрировал щелчок на кнопке «1», а не кнопку «5», даже если я щелкнул в ограничивающей рамке кнопки 5. И если я нажимаю только на верхнем левом углу «1», я хочу, чтобы он щелкнул все, что находится под моим окном, а не на кнопке. Мне также нужно изменить размер этого окна, и изображения в кнопках должны изменяться с их помощью.

Я думал об использовании прозрачного NSWindow с прозрачными NSButtons, содержащими PNG с альфой для каждой кнопки, но я думаю, что перекрывающиеся кнопки будут проблемой.

Я также слышал о таких приложениях, как Bowtie, SweetFM и других, используя WebKit для отображения их интерфейсов. Если это возможно, по крайней мере, на 10,3, это было бы интересно, но я не знаю, как это будет работать.

Я осмотрел маски, области или что-то в этом роде, но ничего не нашел. Я обновлю этот пост, когда найду больше информации (если да!).

Любые подсказки о том, как действовать?

(Обратите внимание, что я работаю на 10,4 и идеал мне нужно поддерживать некоторые старые версии Mac OS X тоже.)

(Кроме того, я нашел «округлое окно» пример на разработчике Apple. Сайт но он больше не работает на 10.4, поэтому я не уверен, что это путь.)

Заранее благодарен!

UPDATE:

(см обновление 2, эта проблема уже решена)

Хорошо, теперь у меня немного другой (но не несвязанного) вопрос. То, что я до сих пор это:

Я выбрал для создания пользовательского элемента управления, что я буду иметь возможность использовать для каждого из моих кнопок:

1- Подкласс NSControl и переопределить DrawRect, MouseUp, mouseDragged и MouseDown , Таким образом, я могу получить поведение, которое я хочу, перетаскивая кнопку (переместите окно).

2- Загрузите изображения для каждого состояния кнопок (одна и та же, но одна из них затемняется) в NSImages и в случае необходимости нарисуйте их в режиме просмотра с помощью compositeToPoint:fromRect:operation:. Изображения: 185 x 185 пикселей PNG-файлы с альфой экспортирован из Photoshop.

3- Получить растровое представление в NSImage в:

NSBitmapImageRep *bitRep = [[NSBitmapImageRep imageRepWithData:[unpressedImage TIFFRepresentation]] retain]; 

ИЛИ

NSBitmapImageRep *bitRep = [[unpressedImage representations] objectAtIndex:0]; 

И, кажется, дают тот же результат. Я попробовал компоновку этого растрового изображения в моем окне, чтобы увидеть, имеет ли изображение одинаковый размер и выглядит как оригинал, и все кажется хорошим (вы поймете, почему я сделал это после этого перечисления ...).

4- В методах событий мыши, я использую растровое представление, чтобы получить альфа-компонент для конкретной точки:

NSPoint mouse = [self convertPoint:[theEvent locationInWindow] fromView:nil]; // Returns the correct x and y positions on the control (i.e: between 0 and 185 for each axis). 

NSColor *colorUnderMouse = [[[unpressedImage representations] objectAtIndex:0] colorAtX:mouse.x y:mouse.y]; 
float alpha = [colorUnderMouse alphaComponent]; 

Затем я печатаю альфа-значение для консоли, но я получаю очень странные результаты , Получение альфа-компонента и цвета под мышью, кажется, работает на первый взгляд (цвета и альфа возвращены в моем растровом изображении), но похоже, что цвет не сделан в правой части в bitRep, или изображение, содержащееся в bitRep искажен (он не искажается, когда я составлю bitRep на окне, хотя это очень странно). Снова я дважды проверил координаты x и y мыши в диапазоне (0,185) и что размер NSBitmapImageRep равен 185 x 185.

Сначала похоже, что NSBitmapImageRep перелистается горизонтально по сравнению с моим NSImage. Если я переверну свои координаты, возвращаемые значения выглядят в основном в порядке (большая часть формы, похоже, соответствует возвращаемым значениям), но все еще есть части изображения, которые возвращают неправильные значения.

Я смущен в этой точке и никогда не работал с NSBitmapImageRep, прежде чем, возможно, просто забыл указать некоторую информацию о формате моего изображения, из-за чего значения отключены. Может ли кто-нибудь прояснить это, пожалуйста?

Еще раз спасибо!

UPDATE 2:

Ok никогда не возражаете, я нашел проблему. Я использовал метод setColor: atX: y: для рисования цветной точки на битрейдере перед ее печатью в моем окне, и проблема была понятна как день: координата Y была обращена в битRep, но изображение печатается с помощью «хорошего "ориентация. Это означает, что битRep имеет «начальную» систему координат «в стиле Windows», а окно имеет декартовую систему координат (внизу слева). Простое изменение моей координаты Y зафиксировало проблемы, с которыми я получил альфа-компонент и цвет.

Это, должно быть, было написано где-то в документах, извините, что беспокоило вас из-за моего отсутствия исследований ...!

ответ

3

насчет перекрывая NSResponder методов событий (mouseUp:, mouseDown: и т.д.) в пользовательских кнопок (предположительно, вы бы подклассов NSControl или NSButton сделать это)? В этих методах вы можете правильно вычислить свой ограничивающий прямоугольник (или круг в этом случае) и выполнить простой тест с координатами щелчка, чтобы увидеть, нужно ли обрабатывать клик.

Вы также можете найти информацию по документам обработки событий Apple, в частности о mouse events и custom views.

+0

Спасибо, это было бы возможно для центральной кнопки, но с внешними кнопками, которые были бы более сложными и требовали бы кучу кода проверки границ ... что, если я по какой-то причине поменяю позиции моей кнопки?(это не личный проект, поэтому, к сожалению, это может быть изменено). Затем мне пришлось бы переписать большую часть моего ограничивающего кода проверки. Будет ли способ сделать это с помощью какой-то маски? Скажите, «дайте клику пройти, если растровое изображение прозрачно в этот момент»? – Form

+0

Я не думаю, что вы можете сделать это с помощью маски, как вы думаете (обнаружение прозрачности и т. Д.). Это довольно простые формы (частичные кружки для внешних кнопок под полным кругом для внутреннего). Вы можете получить доступ к текущим координатам и размерам элементов управления в коде и использовать их для вычисления границ попадания, чтобы вы не делали что-то жесткое. Используйте тот факт, что центральная кнопка находится на вершине в ваших интересах. –

+0

Можно использовать обнаружение прозрачности (альфа), и оно работает очень хорошо, и хотя метод, который я использую сейчас, составляет 10.4+, есть способ сделать это, используя что-то другое, чем colorAtX: y: до тех пор, пока у вас есть доступ к bitmapRep, как указал маджудз. – Form

2

Как сделать все это одним элементом управления?Это может сделать рисунок немного сложным, но похоже, что вы все равно производите рисунок.

Если вы сделали это как один элемент управления, вы можете сначала проверить и увидеть, находится ли точка клика в центре круга. Если это не так, все, что вам нужно сделать, это определить, в каком квадранте он должен знать, к какой «кнопке» он принадлежит (в то же время проверяя, что клик соответствует внутреннему кругу).

В качестве альтернативы вы можете создать прозрачный вид на своих кнопках, которые захватывают события щелчка и пересылают их на соответствующий элемент управления на основе только что указанной логики.

2

Как и в ответе Marc W, в вашем собственном методе вы можете проверить альфа-значение щелчка на растровом изображении и проигнорировать, если альфа ниже определенного значения.

Чтобы получить растровое изображение, read this.

Теперь вы должны иметь указатель растровый, как это (псевдокод - вы должны будете заполнить штук):

pixels = CGBitmapContextGetData(ctx); // there's actually two ways to get pixels in the above Apple tech note 

Затем, вы можете сделать это, чтобы получить пиксель вы заинтересованы, и проверить:

// I'm assuming each pixel is 24 bits of color and one byte of alpha 
#define getRed(p) ((p) & 0x000000FF) 
#define getGreen(p) ((p) & 0x0000FF00) >> 8 
#define getBlue(p) ((p) & 0x00FF0000) >> 16 
#define getAlpha(p) ((p) & 0xFF000000) >> 24 

CGPoint pixPt; 
long pixel; 
pixPt = getMouseClick(); 

pixel = pixels[pixPt.x + pixPt.y * bytesPerRow]; 

if (getAlpha(pixel) < 25) 
    // you've clicked on transparent pixels, alpha of 10% or less (alpha ranges from 0-255) 

Это открывает некоторые возможности для вас, например, имея кольцо вокруг вашего внутреннего круга, который является инертным и не будет принадлежать ни одному из квадрантов или среднего круга. Конечно, всегда есть другие способы делать эти вещи, не прибегая к пиксельным ошибкам :-)

+0

Это похоже на то, что я хотел бы сделать, таким образом, если форма моего контроля изменится, он должен автоматически настраиваться. Есть ли способ проверки непрозрачности изображения в определенной точке изображения кнопки? (Я думаю, что было бы меньше работать для подкласса NSButton вместо подкласса NSView и рисования вручную, но если не удастся проверить альфа с кнопкой, я, скорее всего, займусь NSView). – Form

+0

Я добавляю информацию об обработке растровых изображений обратно в свой ответ. – mahboudz

+0

Большое спасибо, я посмотрю, что я могу с этим сделать! – Form

1

Если вы создаете фигуры в коде с помощью NSBezierPath, проверка того, является ли клик внутри одной из форм, является однострочным: отправьте форму containsPoint:.

Я бы сделал это единственным видом, которому принадлежат пять путей. Когда вы рисуете, нарисуйте центр последним; при ответе на событие мыши, сначала нажмите его. Дайте этому представлению одно свойство действия для каждого сегмента и, возможно, одну цель на сегмент, в зависимости от того, что вам нужно.

+0

Ваше решение очень интересно, я не знал, что вы могли бы попробовать тест NSBezierPaths, как это. Это, безусловно, пригодится. Но в моем случае (с изменением форм, являющимся неотрицательной способностью), я думаю, что было бы много переписать, если я когда-нибудь что-то изменил. Сначала я попробую альфа-тестирование растрового изображения, и если это не сработает, я надеюсь, что я это сделаю. Спасибо, что нашли время ответить на мой вопрос! – Form

1

Вы должны были бы сделать две вещи:

  1. переопределение NSView-х Трассировка: метод возвращать NIL всякий раз, когда щелчок вне изображения, поэтому щелчок в этой точке зрения игнорируется и passedto зрения, перекрывающей ее.
  2. Переопределите mouseDown: и реализуйте свой собственный контур отслеживания мыши там (используя NSEventTrackingRunLoopMode), который также проверяет, находится ли точка в непрозрачной области. NSBitmapImageRep или NSImage имеет метод colorAtX: y: или что-то вроде шляпы, которую вы можете использовать для последнего.
0

Решение Mu работает только на непересекающихся кнопках. У меня есть прямоугольная кнопка, которая должна менять изображения от серого до зеленого.

sample button меняю регулярные кнопки градиента, как этого

properties

вот и все. Надеюсь, это поможет кому-то.

Смежные вопросы