2013-08-28 4 views
5

में चलाती है मैंने हाल ही में अपने डब्ल्यूपीएफ एप्लिकेशन में एक विंडो जोड़ा है जिसे डेस्कटॉप के किनारे पर "ऐप बार" के रूप में डॉक किया जा सकता है। कोड जो मैं डॉकिंग करने के लिए उपयोग कर रहा हूं this स्टैक ओवरफ्लो पोस्ट से आया था।ऐप बार विंडो डॉकिंग पोस्टियन से दूर चली जाती है, फिर डॉकिंग स्थिति

इस कार्यक्रम से संबंधित तीन उपयोगकर्ता सेटिंग्स परिभाषित हैं। एक किनारा है जहां खिड़की डॉक किया गया है, अन्य दो Left & Top गुणों के मान हैं। विचार यह है कि जब खिड़की बंद हो जाती है, या प्रोग्राम बंद हो जाता है, तो प्रोग्राम उसी स्थिति और स्थान पर वापस खुल जाएगा जब प्रोग्राम पुनरारंभ होता है।

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

private void AppBarWindow_Activated(object sender, EventArgs e) { 
    if (Settings.Default.AppBarWindowEdge != ABEdge.None) { 
     AppBarFunctions.SendShellActivated(this); 
    } 
} 

private void AppBarWindow_Closing(object sender, CancelEventArgs e) { 
    Settings.Default.AppBarWindowLeft = Left; 
    Settings.Default.AppBarWindowTop = Top; 
    Settings.Default.Save(); 

    AppBarFunctions.SetAppBar(this, ABEdge.None); 

    // Other, app specific code . . . 
} 

private void AppBarWindow_LocationChanged(object sender, EventArgs e) { 
    if (Settings.Default.AppBarWindowEdge != ABEdge.None) { 
     AppBarFunctions.SendShellWindowPosChanged(this); 
    } 
} 

private void AppBarWindow_SourceInitialized(object sender, EventArgs e) { 
    if (Settings.Default.AppBarWindowEdge != ABEdge.None) { 
     SizeWindow(Settings.Default.AppBarWindowEdge == ABEdge.None ? ABEdge.Left : ABEdge.None); 
    } 
} 

private void AppBarWindow_SizeChanged(object sender, SizeChangedEventArgs e) { 
    if (Settings.Default.AppBarWindowEdge != ABEdge.None) { 
     AppBarFunctions.SendShellWindowPosChanged(this); 
    } 
} 

private void SizeWindow(ABEdge originalEdge) { 
    // App specific code to compute the window's size . . . 

    if (originalEdge != Settings.Default.AppBarWindowEdge) { 
     AppBarFunctions.SetAppBar(this, Settings.Default.AppBarWindowEdge); 
    } 

    Settings.Default.AppBarWindowLeft = Left; 
    Settings.Default.AppBarWindowTop = Top; 
    Settings.Default.Save(); 
} 

मैं कार्यों को शामिल किया है SHAppBarrMessage जब खिड़की सक्रिय होता है, या जब अपनी स्थिति और आकार परिवर्तन कॉल करने के लिए, जैसा कि मैंने this acrticle में पढ़ें:

यहाँ खिड़की से कुछ कोड है। कॉल पर व्यवहार पर कोई प्रभाव नहीं पड़ता है, इसलिए मैं उन्हें हटा सकता हूं।

मुझे पता है किऔर Loading विंडो को प्रदर्शित होने से पहले ईवेंट कहा जाता है लेकिन विंडो हैंडल के बाद और लेआउट & माप पास पूरा हो चुका है। ऐसा लगता है कि, हालांकि, AppBarFunctions.SetAppBar पर कॉल से पहले खिड़की प्रदान की जाती है, यही कारण है कि मैं इसे प्रकट करता हूं और फिर जगह में जाता हूं।

मैंने विंडो के कन्स्ट्रक्टर में सेटिंग्स में सहेजे गए मानों के लिए Left और Top गुणों को सेट करके विंडो को डॉक किए गए स्थान में स्थानांतरित करने का भी प्रयास किया है। यह काम नहीं किया, या तो। वास्तव में, यह बदतर था, क्योंकि खिड़की को पहली बार डॉक की स्थिति में खींचा गया था, फिर स्पष्ट रूप से उस डेस्कटॉप किनारे से दूर स्थानांतरित करने के लिए स्थानांतरित कर दिया गया था, और उसके बाद डॉक किए गए स्थान पर वापस चले गए।

स्टार्टअप पर शुरू होने पर आगे बढ़ने के बाद मैं इस विंडो को डॉक किए गए स्थिति में कैसे दिखूं?

संपादित करें:

मुझे लगता है कि मैं इस समस्या का कारण मिल गया है। AppBarFunctions क्लास कोड में ABSetPos विधि में, DoResize पर विंडो को (UI थ्रेड) पर कॉल करने के ठीक पहले एक टिप्पणी है। टिप्पणी में लिखा है:

// This is done async, because WPF will send a resize after a new appbar is added. 
// if we size right away, WPFs resize comes last and overrides us. 

तो जाहिरा तौर पर WPF या Windows स्थान से बाहर खिड़की बढ़ रहा है खिड़की के लिए आरक्षित किया जा रहा है, और मैं फिर इसे वापस ले जाने में मैं अपने कोड & मैं में ट्रेस अंक का एक बहुत जोड़ा। देख सकते हैं कि उस चाल को तब तक प्रस्तुत नहीं किया जाता है जब तक कि उस कदम को नहीं बनाया जाता है (कोड में टिप्पणी में उल्लिखित एक)। खिड़की प्रदान करने के बाद, यह मेरे कोड द्वारा डॉक स्थिति में स्थानांतरित हो जाता है।

AppBarFunctions कक्षा पहले से ही खोल से संदेशों के लिए वॉशिंग के लिए एक विंडो प्रक्रिया हुक जोड़ती है। अगर मैं WM_WINDOWPOSCHANGED के लिए चेक जोड़ता हूं, तो क्या मैं किसी भी तरह से संदेश संसाधित होने से रोक सकता हूं?या हो सकता है कि मैं Windows/WPF द्वारा किए गए कदम के लिए Left और Top गुणों के मानों को बदल सकता हूं ताकि खिड़की समाप्त हो जहां मैं इसे बनना चाहता हूं?

उत्तर

5

मुझे खिड़की को डॉक किए गए क्षेत्र से आगे बढ़ने का एक तरीका मिला है। असल में, मैं जिस कोड का उपयोग कर रहा हूं वह पहले से ही ABN_* अधिसूचना संदेशों को देखने के लिए विंडो प्रक्रिया हुक विधि का उपयोग करता है। मैंने WM_WINDOWPOSCHANGING संदेशों को देखने के लिए इस विधि में कोड जोड़ा।

यहाँ कोड मैंने लिखा है:

public IntPtr WindowProcedureHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { 
    if (msg == (int) WinMessages.WM_WINDOWPOSCHANGING) { 
     if (IsDocked && !IsDragging) { 
      WindowPos pos = (WindowPos) Marshal.PtrToStructure(lParam, typeof(WindowPos)); 

      // Keep this window in its docked position. 
      pos.x = (int) DockedPosition.X; 
      pos.y = (int) DockedPosition.Y; 
      pos.cx = (int) DockedSize.Width; 
      pos.cy = (int) DockedSize.Height; 

      Marshal.StructureToPtr(pos, lParam, false); 
      handled = true; 
     } 

    } else if (msg == CallbackId) { 
     if (wParam.ToInt32() == (int) ABNotify.ABN_WINDOWPOSCHANGED) { 
      SetDockedPosition(Window, this, true); 
      handled = true; 
     } 
    } 
    return IntPtr.Zero; 
} 

जब खिड़की बढ़त & खोल के साथ पंजीकृत करने के लिए डॉक किया गया है, यह डॉकिंग आयत कॉल से SHAppBarMessage/ABM_SETPOS को लौट याद रखता है। जब विधि WM_WINDOWPOSCHANGED संदेश प्राप्त करती है, तो यह देखने के लिए जांच करता है कि खिड़की किनारे पर डॉक की गई है और उसे खींचा नहीं जा रहा है। यदि ऐसा है, तो यह किसी प्रबंधित ऑब्जेक्ट में अप्रबंधित स्मृति से WINDOWPOS संरचना को मार्शल करता है, विंडो & विंडो के आकार को वापस डॉक स्थिति & आकार पर सेट करता है, और इसे वापस अप्रबंधित स्मृति में मार्शल करता है। इसके बाद यह सही & निकास के लिए संभाला जाता है।

यह पूरी तरह से काम करता है & वापस अपने डॉक की गई स्थिति & से दूर उछल से खिड़की रहती है। और खिड़की के Dispatcher धागे पर डॉक की गई स्थिति में एक कदम शेड्यूल करने के लिए कोई जरूरत नहीं है।

संबंधित मुद्दे