2009-10-06 48 views
7

我期待讓這將是這個樣子(不去管快速的Photoshop)的自定義窗口:如何用非矩形按鈕創建透明窗口?

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

主要的問題我已經是不使窗口透明(雖然我想任何信息是受歡迎的!),但我希望能夠只點擊按鈕的可見部分。例如,如果我點擊「5」按鈕左上方的外部,即使點擊了按鈕5的邊框,我希望它在「1」按鈕上註冊而不是「5」按鈕。如果我點擊「1」按鈕的左上方「角落」的外側,我希望它可以點擊我窗口下方的任何內容,而不是按鈕上的內容。我還需要能夠調整這個窗口的大小,並且按鈕中的圖片應該與它們一起調整大小。

我想使用與含有的PNG用α爲每個按鈕透明NSButtons透明NSWindow的,但我認爲重疊按鈕將是一個問題。

我也聽說過類似蝴蝶結,SweetFM並使用WebKit的施展接口的應用程序等。如果這是至少有可能的10.3,這將是有趣的,但我不知道如何也可以。

我環顧四周,點擊面具,地區或類似的東西,但我還沒有發現任何東西。我會更新這篇文章,因爲我發現更多的信息(如果我做的!)。

對如何進行任何提示?

(請注意,我在10.4和理想我需要支持一些老版本的Mac OS X的太工作。)

(另外,我發現了「圓窗」例如蘋果的開發。網站但它不會在10.4,所以我不知道這是要走的路提前跑了。)

謝謝!

UPDATE:

(見更新2,這個問題已經得到解決)

OK,現在我有一個稍微不同的(但不無關係)的問題。我所做的,到目前爲止是這樣的:

我選擇了做,我就可以用我的每個按鍵的自定義控制:

1子類的NSControl並重寫drawRect中,mouseUp事件,和的mouseDragged鼠標按下。通過這種方式,我可以在拖動按鈕(移動窗口)時獲得所需的行爲。

2-將每個按鈕的圖像狀態(相同的形狀,但其中一個變暗)加載到NSImages中,並在必要時使用compositeToPoint:fromRect:operation:將它們繪製到視圖中。這些圖像是185 X 185像素與從Photoshop出口阿爾法PNG文件。

3-獲取NSImage中的位圖表示:

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

OR

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

似乎都給予同樣的結果。我試圖將這個位圖代表合成到我的窗口,看看圖像是否與原始尺寸相同並且看起來不錯(你會看到爲什麼我在枚舉之後做了這件事......)。

4-在鼠標事件的方法,我用位圖表示獲取alpha分量的特定點:

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]; 

然後,我打印的Alpha值的控制檯,但我得到很奇怪的結果。在鼠標下獲取alpha組件和顏色看起來很乍看起來(返回的顏色和alpha位於我的位圖中),但看起來顏色不是在bitRep中的正確位置拍攝的, bitRep失真(當我在窗口上合成bitRep時,它不會失真,這很奇怪)。再一次,我仔細檢查了x和y鼠標座標在(0,185)範圍內,NSBitmapImageRep的大小也是185 x 185。

首先看起來NSBitmapImageRep與我的NSImage相比水平翻轉。如果我翻轉我的座標,返回的值似乎大部分都是正確的(大部分形狀似乎與返回的值相符),但仍有部分圖像返回錯誤的值。

我在這一點上毫無頭緒,從未與NSBitmapImageRep一起工作過,也許我只是忘記指定一些關於我的圖像的格式信息,這就是爲什麼值是關閉的。有人可以澄清這一點嗎?再次

謝謝!

更新2:

好沒關係,我發現這個問題。我使用setColor:atX:y:方法在打印到窗口之前在bitRep上繪製了一個彩色點,並且問題在白天清晰顯示:在bitRep中Y座標反轉,但圖像打印的是「good 「定位。這意味着bitRep具有「Windows風格」的左上角原點座標系,而窗口具有笛卡爾座標系(左下)原點。簡單地顛倒我的Y座標可以解決我獲得alpha分量和顏色的問題。

這一定是寫在文檔的某個地方,對不起,因爲我缺乏研究而打擾你......!

回答

3

什麼覆蓋您的自定義按鈕NSResponder事件方法(mouseUp:mouseDown:等),(想必你會繼承NSControlNSButton使這些)?在這些方法中,您可以正確計算您的邊界矩形(在這種情況下爲圓形),並使用點擊座標進行簡單的點擊測試,以查看點擊是否應該處理。

您也許能夠在Apple的事件處理文檔中找到一些幫助,特別是關於mouse eventscustom views

+0

謝謝,這將是該中心按鈕的可能性,但與外面的按鈕,會比較困難,需要一堆的邊界檢查代碼...如果我改變什麼我的按鈕的位置由於某種原因?(這不是一個個人項目,所以這可能會有所改變,不幸的是)然後我不得不重寫大部分的邊界檢查代碼......有沒有辦法用某種掩碼來做到這一點?說「讓點擊通過,如果位圖透明在這一點上」? – Form 2009-10-06 20:40:47

+0

我不認爲你可以像你想的那樣使用面具(透明度檢測等)。這些都是非常基本的形狀(內圈下方的外部按鈕的部分圓圈)。您可以在代碼中訪問控件的當前座標和尺寸,並使用它們來計算命中範圍,以便不對任何東西進行硬編碼。使用中心按鈕位於最佳位置的事實。 – 2009-10-06 21:27:23

+0

它可以使用透明度(alpha)檢測,它工作得很好,雖然我現在使用的方法是10.4+,但有一種方法可以使用除colorAtX之外的其他方法來執行此操作:y:只要您有權訪問就像mahboudz指出的那樣。 – Form 2009-10-09 13:28:26

2

如何使它成爲一個單一的控制?這可能會使繪圖有點複雜,但看起來您仍然在進行自定義繪製。

如果你沒有它作爲一個單一的控制,你可以先檢查,看看點擊點爲中心的圓內。如果不是,那麼你所要做的就是確定它在哪個象限以瞭解它屬於哪個「按鈕」(同時還要驗證點擊是否在外圈內)。

或者,您可以創建在你的按鈕,透明的觀點,即捕獲點擊事件,並將它們轉發到基於我剛纔指定的邏輯適當的控制。

2

馬克·W公司的反應類似,在自己的事件的方法,你可以檢查所點擊的位圖的Alpha值,而忽略如果alpha大於一定值低。

爲了得到位,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並進行繪製的工作會更少,但如果無法使用按鈕檢查Alpha,我很可能會使用NSView)。 – Form 2009-10-07 02:21:01

+0

我將位圖處理信息添加回我的回覆中。 – mahboudz 2009-10-07 05:34:49

+0

非常感謝,我會看到我能用它做什麼! – Form 2009-10-07 14:25:30

1

如果您使用NSBezierPath在代碼中生成形狀,測試點擊是否在其中一個形狀內是單線:發送形狀containsPoint:消息。

我會想辦法讓這個擁有五個路徑的單一視圖。繪圖時,最後繪製中心;當響應鼠標事件時,首先進行命中測試。根據您的需要,爲此視圖提供每個細分的一個操作屬性,並且還可以選擇每個細分的一個目標。

+0

你的解決方案非常有趣,我不知道你可以像這樣測試NSBezierPaths。它一定會派上用場。但在我的情況下(隨着形狀的變化不可忽略的可行性),我認爲如果我改變了某些東西,這將會是很多重寫。我會先嚐試位圖alpha測試,如果這不起作用,我希望它能做到這一點。感謝您花時間回答我的問題! – Form 2009-10-07 13:32:54

1

你需要做兩件事情:

  1. 覆蓋的NSView的則hitTest:方法返回NIL只要點擊在圖像之外,使該視圖中的點擊被忽略,passedto重疊它的視圖。
  2. 覆蓋鼠標按下:和實現自己的鼠標跟蹤環路在那裏(使用NSEventTrackingRunLoopMode)也檢查點是否是在非透明區域。 NSBitmapImageRep或NSImage有一個colorAtX:y:方法或類似帽子的東西,你可以使用後者。
0

慕解決方案僅適用於非相交按鈕。我有非矩形按鈕,必須將圖像從灰色變爲綠色。

sample button 我改變這樣

properties

多數民衆贊成定期漸變按鈕。希望這可以幫助別人。