代码之家  ›  专栏  ›  技术社区  ›  Form

如何创建带有非矩形按钮的透明窗口?

  •  7
  • Form  · 技术社区  · 17 年前

    我正在寻找一个定制窗口,它看起来像这样(更不用说快速photoshop):

    alt text

    我的主要问题是没有使窗口透明(尽管我想任何信息都是受欢迎的!),但我希望能够只点击按钮的可见部分。例如,如果我单击“5”按钮左上方的外部,我希望它注册单击“1”按钮而不是“5”按钮,即使我在按钮5的边界框中单击。如果我点击“1”按钮左上角的外侧,我希望它点击窗口下方的任何东西,而不是按钮。我还需要能够调整这个窗口的大小和按钮中的图片应该与他们一起调整大小。

    我曾考虑使用一个透明的NSWindow,其中包含每个按钮带有alpha的PNG的透明NSButtons,但我认为重叠的按钮将是一个问题。

    我还听说过一些应用程序,如Bowtie、SweetFM和其他使用WebKit显示界面的应用程序。如果这是一个可能性,至少10.3,这将是有趣的,但我也不知道这将如何工作。

    我四处寻找点击面具、区域或类似的东西,但我还没有找到任何东西。当我发现更多信息时,我会更新这篇文章(如果我这样做了!)。

    (请注意,我正在处理10.4和 理想的

    (另外,我在苹果的开发网站上找到了“rounded window”的例子,但它已经不再在10.4上运行了,所以我不确定这是正确的选择。)

    提前谢谢!

    (请参阅更新2,此问题现已修复)

    好的,现在我有一个稍微不同的(但不是无关的)问题。到目前为止,我所做的是:

    我选择制作一个自定义控件,可以用于我的每个按钮:

    1-子类NSControl和override drawRect、mouseUp、mouseDragged和mouseDown。这样,我可以在拖动按钮(移动窗口)时获得所需的行为。

    2-将每个按钮状态的图像(形状相同,但有一个变暗)加载到NSImage中,并使用 compositeToPoint:fromRect:operation: 185x185 从Photoshop导出。

    3-获取NSImage的位图表示:

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

    或

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

    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 ,或中包含的图像 比特雷普 是扭曲的(当我合成 但是在窗户上,这很奇怪)。我再次检查了x和y鼠标坐标是否在(0185)范围内,以及鼠标的大小 NSBitmapImageRep 也是185x185。

    首先,它看起来像 与我的 NSImage . 如果我翻转坐标,返回的值看起来基本正常(大部分形状似乎与返回的值相符),但图像中仍有部分返回错误的值。

    在这一点上,我毫无头绪,从来没有和你一起工作过

    再次感谢!

    没关系,我发现了问题。在我的窗口上打印之前,我使用setColor:atX:y:方法在bitRep上绘制了一个彩色点,问题很清楚:bitRep中的y坐标是反向的,但图像是以“良好”方向打印的。这意味着bitRep具有“窗口样式”左上角原点坐标系,而窗口具有笛卡尔坐标系(左下角)原点。简单地反转Y坐标,就解决了获取alpha分量和颜色的问题。

    6 回复  |  直到 6 年前
        1
  •  3
  •   Marc W    17 年前

    重写 NSResponder mouseUp: , mouseDown: ,等等)在自定义按钮中(可能是子类化 NSControl 或 NSButton 做这些?在这些方法中,您可以正确地计算边界矩形(本例中为圆形),并使用单击的坐标进行简单的命中测试,以查看是否应该处理单击。

    你也可以在苹果的事件处理文档中找到一些帮助,特别是关于 mouse events custom views .

        2
  •  2
  •   Dave DeLong    17 年前

    把它变成一个单独的控件怎么样?这可能会使绘图有点复杂,但看起来您正在进行自定义绘图。

    如果将其作为单个控件来执行,则可以首先检查并查看单击点是否在中心圆内。如果不是,那么您所要做的就是确定它位于哪个象限,以知道它属于哪个“按钮”(同时验证单击是否与外圈相符)。

        3
  •  2
  •   mahboudz    17 年前

    与Marc 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)
    

    这为你打开了一些可能性,比如在你的内圆周围有一个不属于任何象限或中间圆的惰性环。当然,总有其他方法来做这些事情,而不必诉诸像素争论:-)

        4
  •  1
  •   Peter Hosey    17 年前

    如果使用NSBezierPath在代码中生成形状,则测试单击是否在其中一个形状内是一行:发送形状a containsPoint:

    我会让它成为一个拥有五条路径的单一视图。绘制时,最后绘制一个中心;当响应鼠标事件时,请先点击测试。根据您的需要,为该视图提供每个片段一个操作属性,并可选地为每个片段提供一个目标。

        5
  •  1
  •   uliwitness    13 年前

    您需要做两件事:

    1. 重写NSView的hitTest:方法,以便在单击位于图像外部时返回NIL,因此该视图中的单击将被忽略并传递到与其重叠的视图。
    2. Override mouseDown:并在其中实现您自己的鼠标跟踪循环(使用NSEventTrackingRunLoopMode),该循环还检查该点是否位于不透明区域。NSBitmapImageRep或NSImage有一个colorAtX:y:方法或类似于hat的方法,可以用于后者。
        6
  •  0
  •   WINSergey    13 年前

    Mu解决方案仅适用于非相交按钮。我有一个非矩形按钮,它必须将图像从灰色变为绿色。

    sample button 我像这样改变规则渐变按钮

    properties

    就这些。希望这能帮助别人。