2010-12-30 12 views
16

मैं एक बनावट खिड़की का उपयोग कर रहा हूं जिसमें शीर्षक बार के ठीक नीचे, इसके शीर्ष पर एक टैब बार है।विंडो को खींचने के लिए दृश्य को क्लिक करके खींचें?

मैंने ग्रेडिएंट को सही बनाने के लिए विंडो पर -setContentBorderThickness:forEdge: का उपयोग किया है, और यह सुनिश्चित करने के लिए कि शीट सही स्थिति से बाहर स्लाइड करें।

हालांकि काम नहीं कर रहा है, खिड़की को खींच रहा है। यह काम करता है अगर मैं उस क्षेत्र को क्लिक और ड्रैग करता हूं जो वास्तव में शीर्षक पट्टी है, लेकिन चूंकि टाइटल बार ग्रेडियेंट एक (संभावित रूप से/अक्सर खाली) टैब बार में फैलता है, तो यह वास्तव में बहुत कम क्लिक करने में आसान है और जब आप कोशिश करते हैं तो वास्तव में निराशाजनक लगता है खिड़की खींचने और महसूस करने के लिए नहीं चल रहा है।

मुझे NSToolbar पर ध्यान दिया गया है, जबकि शीर्षक बार के नीचे लगभग उसी स्थान पर कब्जा करते हुए, कर्सर खत्म होने पर खिड़की को खींचने की अनुमति देता है। यह कैसे लागू करता है?

धन्यवाद।

Tab Bar

उत्तर

16

मैंने पाया इस here:

-(void)mouseDown:(NSEvent *)theEvent {  
    NSRect windowFrame = [[self window] frame]; 

    initialLocation = [NSEvent mouseLocation]; 

    initialLocation.x -= windowFrame.origin.x; 
    initialLocation.y -= windowFrame.origin.y; 
} 

- (void)mouseDragged:(NSEvent *)theEvent { 
    NSPoint currentLocation; 
    NSPoint newOrigin; 

    NSRect screenFrame = [[NSScreen mainScreen] frame]; 
    NSRect windowFrame = [self frame]; 

    currentLocation = [NSEvent mouseLocation]; 
    newOrigin.x = currentLocation.x - initialLocation.x; 
    newOrigin.y = currentLocation.y - initialLocation.y; 

    // Don't let window get dragged up under the menu bar 
    if((newOrigin.y+windowFrame.size.height) > (screenFrame.origin.y+screenFrame.size.height)){ 
     newOrigin.y=screenFrame.origin.y + (screenFrame.size.height-windowFrame.size.height); 
    } 

    //go ahead and move the window to the new location 
    [[self window] setFrameOrigin:newOrigin]; 
} 

यह ठीक काम करता है, हालांकि मुझे लगता है मैं इसे सही ढंग से कर रहा हूँ नहीं 100% यकीन है। मुझे अब तक एक बग मिला है, और ऐसा लगता है कि ड्रैग एक सबव्यू (एक टैब स्वयं) के अंदर शुरू होता है और फिर पर्यवेक्षण (टैब बार) में प्रवेश करता है। खिड़की चारों ओर कूदता है। कुछ- hitTest: जादू, या संभवतः यहां तक ​​कि बस माउसअप पर प्रारंभिक स्थान को अमान्य करने से भी इसे ठीक करना चाहिए।

+0

संदेह के रूप में, माउसअप में "प्रारंभिक स्थान" चर को अमान्य कर रहा है: ईवेंट (बस y स्थिति को ऋणात्मक संख्या में सेट करके), फिर माउस पर एक गार्ड क्लॉज जोड़ना: ड्रग को ठीक करता है। – d11wtq

10

आप NSView विधि mouseDownCanMoveWindow अधिभावी YES वापसी करने की कोशिश की है?

+0

मुझे नहीं पता था, क्योंकि मुझे नहीं पता था कि इस तरह की एक विधि मौजूद है, धन्यवाद। हालांकि, ऐसा लगता है कि यह काम नहीं करता है। टैब बार एक बड़ा (लगभग पूरी विंडो) दृश्य का एक सबव्यूव है, अगर इससे कोई फर्क पड़ता है। – d11wtq

+3

मेरा अगला विचार माउस ईवेंट को '[स्वयं विंडो]' पास करने के लिए 'माउसडाउन:' (एनएससींट्रोल विधि) को ओवरराइड करना था, और सुनिश्चित करें कि विंडो 'MovableByWindowBackground' है, लेकिन यह अभी भी मेरे लिए काम नहीं करता है। माफ़ कीजिये। – Richard

+0

कोई नाटक नहीं। आप सही रास्ते पर थे। जांच के लिए धन्यवाद! :) – d11wtq

21

मैंने mouseDownCanMoveWindow समाधान (https://stackoverflow.com/a/4564146/901641) की कोशिश की लेकिन यह मेरे लिए काम नहीं किया। मैंने उस विधि से छुटकारा पा लिया और इसके बजाय इसे मेरे विंडो सबक्लास में जोड़ा:

- (BOOL)isMovableByWindowBackground { 
    return YES; 
} 

जो एक आकर्षण की तरह काम करता था।

+9

स्विफ्ट में: 'window.movableByWindowBackground = true'। – twe4ked

+3

@ ओडिन - मुझे लगता है कि 'window.movableByWindowBackground = हाँ;' ओब्जे-सी में काम करता है, लेकिन मुझे लगता है कि मैं विधि ओवरराइडिंग मार्ग चला गया क्योंकि मैं विशेष रूप से 'एनएसविंडो' का उप-वर्ग बनाने की तलाश में था जो इस विशेषता को हमेशा प्रदर्शित करता था। – ArtOfWarfare

+0

आप शायद सही हैं, मैंने बस किसी और के लिए समाप्त किया जो स्विफ्ट का उपयोग करके इस पृष्ठ पर जाता है। उत्तर के लिए धन्यवाद :) – twe4ked

10

यह दो चरणों के बाद मेरे लिए काम करता है:

  1. उपवर्ग NSView, mouseDownCanMoveWindow ओवरराइड हाँ वापस जाने के लिए।
  2. सबक्लास एनएसविंडो, isMovableByWindowBackground को YES वापस करने के लिए ओवरराइड करें।
+2

यदि आप अपनी विंडो" बनावट "बनाते हैं तो आप चरण दो को छोड़ सकते हैं। (आईबी में एक चेकबॉक्स है।) –

+5

आपको एनएसविंडो को उप-वर्ग करने की आवश्यकता नहीं है, क्योंकि आप व्यू कंट्रोलर में '[self.view.window setMovableByWindowBackground: YES]' को कॉल कर सकते हैं। ऐसा लगता है कि एनएसविंडो का 'isMovableByWindowBackground' उत्परिवर्तनीय है जबकि NSView के' MouseDownCanMoveWindow' केवल पढ़ने के लिए है। – VinceFior

4

यह काफी आसान है:

ओवरराइड mouseDownCanMoveWindow संपत्ति

override var mouseDownCanMoveWindow:Bool { 
    return false 
} 
6

MacOS 10.11 के रूप में, यह करने के लिए सबसे आसान तरीका नया -[NSWindow performWindowDragWithEvent:] विधि का उपयोग करने के लिए है:

@interface MyView() { 
    BOOL movingWindow; 
} 
@end 

@implementation MyView 

... 

- (BOOL)mouseDownCanMoveWindow 
{ 
    return NO; 
} 

- (void)mouseDown:(NSEvent *)event 
{ 
    movingWindow = NO; 

    CGPoint point = [self convertPoint:event.locationInWindow 
           fromView:nil]; 

    // The area in your view where you want the window to move: 
    CGRect movableRect = CGRectMake(0, 0, 100, 100); 

    if (self.window.movableByWindowBackground && 
     CGRectContainsPoint(movableRect, point)) { 

     [self.window performWindowDragWithEvent:event]; 
     movingWindow = YES; 
     return; 
    } 

    // Handle the -mouseDown: as usual 
} 

- (void)mouseDragged:(NSEvent *)event 
{ 
    if (movingWindow) return; 

    // Handle the -mouseDragged: as usual 
} 

@end 

यहां, -performWindowDragWithEvent: सही बीहा को संभालेगा मेनू बार को ओवरलैप न करने का वायर, और मैकोज़ 10.12 और बाद में किनारों पर भी स्नैप करेगा। अपने दृश्य के निजी इंटरफ़ेस के साथ BOOL movingWindow इंस्टेंस वैरिएबल को शामिल करना सुनिश्चित करें ताकि आप -mouseDragged: ईवेंट से बच सकें, जब आप यह निर्धारित कर लें कि आप उन्हें संसाधित नहीं करना चाहते हैं।

यहां, हम यह भी जांच रहे हैं कि -[NSWindow movableByWindowBackground]YES पर सेट है ताकि यह दृश्य गैर-चलने योग्य-विंडो-पृष्ठभूमि विंडो में उपयोग किया जा सके, लेकिन यह वैकल्पिक है।

+0

यह विधि मेरी परियोजना के लिए काम करती है। सिवाय इसके कि movableRect में कोई भी माउस इवेंट आगे बढ़ेगा, भले ही उपरोक्त दृश्य ** ** देखें। – Lax

+0

@Lax आप यह देखना चाहते हैं कि ड्रैगिंग व्यू के ऊपर दिखाई देने वाला आपका दृश्य सही ढंग से परीक्षण कर रहा है - क्या वे दोनों माउस डाउन इवेंट प्राप्त कर रहे हैं? –

0

आप अपने विंडो में एक NSTableView मिला, चयन साथ सक्षम, अधिभावी mouseDownCanMoveWindow संपत्ति काम नहीं करेंगे।

@interface WindowDraggableTableView : NSTableView 
@end 

@implementation WindowDraggableTableView 
{ 
    BOOL _draggingWindow; 
    NSEvent *_mouseDownEvent; 
} 

- (void)mouseDown:(NSEvent *)event 
{ 
    if (self.window.movableByWindowBackground == NO) { 
     [super mouseDown:event]; // Normal behavior. 
     return; 
    } 

    _draggingWindow = NO; 
    _mouseDownEvent = event; 
} 

- (void)mouseDragged:(NSEvent *)event 
{ 
    if (self.window.movableByWindowBackground == NO) { 
     [super mouseDragged:event]; // Normal behavior. 
     return; 
    } 

    assert(_mouseDownEvent); 
    _draggingWindow = YES; 
    [self.window performWindowDragWithEvent:_mouseDownEvent]; 
} 

- (void)mouseUp:(NSEvent *)event 
{ 
    if (self.window.movableByWindowBackground == NO) { 
     [super mouseUp:event]; // Normal behavior. 
     return; 
    } 

    if (_draggingWindow == YES) { 
     _draggingWindow = NO; 
     return; // Event already handled by `performWindowDragWithEvent`. 
    } 

    // Triggers regular table selection. 
    NSPoint locationInWindow = event.locationInWindow; 
    NSPoint locationInTable = [self convertPoint:locationInWindow fromView:nil]; 
    NSInteger row = [self rowAtPoint:locationInTable]; 
    if (row >= 0 && [self.delegate tableView:self shouldSelectRow:row]) 
    { 
     NSIndexSet *rowIndex = [NSIndexSet indexSetWithIndex:row]; 
     [self selectRowIndexes:rowIndex byExtendingSelection:NO]; 
    } 
} 

@end 

भी भूल नहीं है और साथ ही इसी खिड़की movableByWindowBackground गुण सेट करने के लिए:

आप एक NSTableView उपवर्ग बना सकते हैं और निम्नलिखित माउस घटनाओं को ओवरराइड (और प्रयोग performWindowDragWithEvent:Dimitri answer में उल्लेख किया है) के बजाय की जरूरत है:

self.window.movableByWindowBackground = YES; 
संबंधित मुद्दे