NSAlert สามารถใช้สร้างหน้าต่างลอยได้หรือไม่?

ฉันมีแอปพลิเคชัน Cocoa ที่แสดงการแจ้งเตือนแอปพลิเคชันโมดอลโดยใช้คลาส NSAlert ฉันต้องการให้หน้าต่างการแจ้งเตือนลอยอยู่เหนือหน้าต่างแอปพลิเคชันอื่นๆ ทั้งหมด สามารถทำได้ด้วย NSAlert หรือฉันต้องติดตั้งหน้าต่างของตัวเอง

ฉันไม่รู้ว่าสำคัญหรือไม่ แต่แอปพลิเคชันนี้เป็นแอปพลิเคชันตัวแทน (LSUIElement เป็นจริง) ที่ใช้งานเป็น NSStatusItem (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแอป รวมถึงซอร์สโค้ด ดู ‹here>)

นี่คือรหัสที่แสดงการแจ้งเตือน:

- (void)showTimerExpiredAlert {
    [NSApp activateIgnoringOtherApps:YES];

    NSAlert *alert = [[NSAlert alloc] init];
    [alert setAlertStyle:NSInformationalAlertStyle];
    [alert setMessageText:NSLocalizedString(@"Menubar Countdown Complete", @"Expiration message")];
    [alert setInformativeText:NSLocalizedString(@"The countdown timer has reached 00:00:00.",
                                                @"Expiration information")];
    [alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button title")];
    [alert addButtonWithTitle:NSLocalizedString(@"Restart Countdown...", @"Restart button title")];

    NSInteger clickedButton = [alert runModal];
    [alert release];

    if (clickedButton == NSAlertSecondButtonReturn) {
        // ...
    }
}

ฉันได้ลองใส่สิ่งนี้ก่อนการโทร runModal:

[[alert window] setFloatingPanel:YES];

ฉันได้ลองสิ่งนี้แล้ว:

[[alert window] setLevel:NSFloatingWindowLevel];

แต่ไม่มีสิ่งใดที่ทำให้หน้าต่างอยู่เหนือหน้าต่างอื่นหากฉันคลิกหน้าต่างของแอปพลิเคชันอื่น ฉันสงสัยว่า runModal ไม่ให้เกียรติการตั้งค่าอย่างใดอย่างหนึ่งเหล่านั้น


person Kristopher Johnson    schedule 19.04.2009    source แหล่งที่มา
comment
เมื่อใดก็ตามที่เรียกใช้ runModal มันจะรีเซ็ตระดับหน้าต่าง ไม่แน่ใจว่าจะช่วยได้หรือไม่...   -  person cobbal    schedule 19.04.2009


คำตอบ (2)


ฉันทำลายสมองของฉันเกี่ยวกับสิ่งนี้เมื่อไม่นานมานี้

วิธีเดียวที่ฉันจะทำให้สิ่งนี้ใช้งานได้ (เรียงลำดับ) คือไปที่คลาสย่อย NSApplication และแทนที่ -sendEvent ใน -sendEvent คุณต้องเรียกใช้ super ก่อน จากนั้นให้ดำเนินการดังนี้:

id *modalWindow = [self modalWindow];
if (modalWindow && [modalWindow level] != MY_DESIRED_MODAL_WINDOW_LEVEL)
    [modalWindow setLevel: MY_DESIRED_MODAL_WINDOW_LEVEL];

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

ใช่แล้ว น่าเสียดายที่คุณควรเขียน NSAlert เวอร์ชันของคุณเองจะดีกว่า หากคุณใส่ใจเกี่ยวกับความเป็นไปได้นี้จริงๆ ฉันจะแจ้งข้อบกพร่องเกี่ยวกับเรื่องนี้ มันค่อนข้างแปลกที่ [[alert window] setLevel: someLevel] ไม่ได้รับเกียรติจาก NSApplication และเป็นเรื่องเสียเปล่าที่ต้องสร้าง NSAlert ขึ้นมาใหม่ด้วยฟีเจอร์เค้าโครงอัตโนมัติเล็กๆ น้อยๆ ทั้งหมดเพื่อให้สามารถทำเช่นนี้ได้

person Dirk Stoop    schedule 19.04.2009

สิ่งที่ฉันทำคือละทิ้ง NSAlert และโหลดการแจ้งเตือน NSWindow จาก NIB แทน

นี่คือรหัสที่แสดงหน้าต่าง:

- (void)showAlert {
    NSWindow *w = [self window];
    [w makeFirstResponder:nil];
    [w setLevel:NSFloatingWindowLevel];
    [w center];
    [w makeKeyAndOrderFront:self];
}

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

มีอะไรอีกบ้างที่ฉันควรทำ?

person Kristopher Johnson    schedule 21.04.2009