วิธียอมรับการคลิกเมาส์สำหรับส่วนหนึ่งและปล่อยให้คลิกผ่านส่วนที่เหลือของ NSWindow

ฉันมีโค้ดด้านล่างสำหรับคลาสย่อย NSWindow มีมุมมองภาพเคลื่อนไหวที่สามารถปรับขนาดได้ และฉันต้องการยอมรับการคลิกเมื่อมีการคลิกที่จุดที่ถูกต้องและปฏิเสธ (คลิกผ่าน) หากอยู่ภายนอก

โค้ดด้านล่างใช้งานได้ดี ยกเว้นหน้าต่างที่ไม่อนุญาตให้คลิกผ่าน

- (void)mouseDragged:(NSEvent *)theEvent {
  if (allowDrag) {
    NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
    NSRect windowFrame = [self frame];
    NSPoint newOrigin = windowFrame.origin;

    // Get the mouse location in window coordinates.
    NSPoint currentLocation = [theEvent locationInWindow];
    // Update the origin with the difference between the new mouse location and the old mouse location.
    newOrigin.x += (currentLocation.x - initialMouseLocation.x);
    newOrigin.y += (currentLocation.y - initialMouseLocation.y);

    if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height)) {
        newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
    }

    // Move the window to the new location
    [self setFrameOrigin:newOrigin];
  }
}



- (void)mouseDown:(NSEvent *)theEvent
{
    screenResolution = [[NSScreen mainScreen] frame];

   initialMouseLocation = [theEvent locationInWindow];

    float scale = [[NSUserDefaults standardUserDefaults] floatForKey:@"widgetScale"]/100;

    float pX = initialMouseLocation.x;
    float pY = initialMouseLocation.y;
    float fX = self.frame.size.width;
    float fY = self.frame.size.height;

    if (pX>(fX-fX*scale)/2 && pX<(fX+fX*scale)/2 && pY>(fY+fY*scale)/2) {
        allowDrag = YES;
    } else {
        allowDrag = NO;
    }
}

person Tibidabo    schedule 03.03.2013    source แหล่งที่มา


คำตอบ (2)


ใน Cocoa คุณมีสองตัวเลือกพื้นฐาน: 1) คุณสามารถทำให้ทั้งหน้าต่างผ่านการคลิกผ่านด้วย [window setIgnoresMouseEvents:YES] หรือ 2) คุณสามารถทำให้บางส่วนของหน้าต่างของคุณโปร่งใส และการคลิกจะผ่านไปตามค่าเริ่มต้น

ข้อจำกัดคือเซิร์ฟเวอร์หน้าต่างจะตัดสินใจว่าแอปใดจะส่งเหตุการณ์ไปในครั้งเดียว หลังจากที่ได้ส่งมอบกิจกรรมไปยังแอปของคุณแล้ว ไม่มีทางใดที่จะทำให้กิจกรรมนั้นกลับมาและส่งไปยังแอปอื่นได้

วิธีแก้ปัญหาหนึ่งที่เป็นไปได้อาจเป็นการใช้ Quartz Event Taps. แนวคิดก็คือคุณทำให้หน้าต่างของคุณเพิกเฉยต่อเหตุการณ์ของเมาส์ แต่ตั้งค่าการแตะเหตุการณ์ที่จะเห็นเหตุการณ์ทั้งหมดสำหรับเซสชันการเข้าสู่ระบบ หากคุณต้องการให้เหตุการณ์ที่ผ่านหน้าต่างของคุณหยุดที่หน้าต่างของคุณจริงๆ คุณจะต้องดำเนินการด้วยตนเองแล้วจึงละทิ้งไป คุณไม่ปล่อยให้กิจกรรมดำเนินต่อไปในแอปที่จะไปถึง ฉันคาดหวังว่าสิ่งนี้คงจะยุ่งยากมากในการทำสิ่งที่ถูกต้อง ตัวอย่างเช่น คุณไม่ต้องการสกัดกั้นเหตุการณ์สำหรับหน้าต่างของแอปอื่นที่อยู่ตรงหน้าของคุณ

หากเป็นไปได้ ฉันขอแนะนำให้คุณใช้เทคนิคที่รองรับโกโก้ ฉันคิดว่าคุณคงอยากให้การคลิกผ่านหน้าต่างของคุณเท่านั้นโดยที่มันโปร่งใสอยู่แล้ว เพราะไม่เช่นนั้นผู้ใช้จะรู้ได้อย่างไรว่าพวกเขากำลังคลิกอะไร

person Ken Thomases    schedule 03.03.2013
comment
น่าเสียดายที่ไม่มีอะไรทำงานอย่างที่ฉันคาดไว้ เมื่อฉันปรับขนาดมุมมองของหน้าต่างด้วยแอนิเมชั่นพื้นฐาน มันจะทำให้ส่วนที่โปร่งใสมาก แต่ส่วนเหล่านั้นยังคงยอมรับการคลิกเมาส์ได้ เนื่องจากความโปร่งใสดั้งเดิมไม่สำคัญกับเลเยอร์แอนิเมชั่น นอกจากนี้ยังต้องเป็นมิตรกับ App Store ด้วย ดังนั้นกับดักเหตุการณ์จึงไม่ดี ฉันได้ส่งแอปตามที่เป็นอยู่แล้ว โดยมีข้อผิดพลาดหากได้รับการร้องเรียนจำนวนมากอาจเป็นสิ่งที่ดีที่สุดถ้าฉันเพียงแค่ปรับขนาดหน้าต่างที่ล้อมรอบให้มีขนาดเท่ากับมุมมองที่ปรับขนาด ขอบคุณนะ - person Tibidabo; 09.03.2013
comment
ฉันไม่รู้ในระหว่างแอนิเมชั่น แต่หลังจากปรับขนาดแอนิเมชั่นเสร็จแล้วให้ลองเรียกใช้ -[NSWindow invalidateShadow] นั่นควรตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์หน้าต่างอัปเดตแนวคิดเกี่ยวกับรูปร่างของหน้าต่าง - person Ken Thomases; 09.03.2013

โปรดเรียกใช้ CHILD WINDOW แบบซ้อนทับแบบโปร่งใสเพื่อยอมรับการควบคุมและสร้างหน้าต่างหลัก -setIgnoresMouseEvents:YES ตามที่ Ken กำกับ

ฉันใช้กลอุบายนี้กับแอปของฉันชื่อ "โอเวอร์เลย์"

person Jiulong Zhao    schedule 23.10.2013