2013-02-25 60 views
5

यह XE3 तक सभी डेल्फी में होता है:खिड़की को पुनर्जीवित करते समय एंकरों को तोड़ने के लिए वर्कअराउंड?

  1. एक फ़ॉर्म बनाएं और उस पर एक पैनल डाल दिया। पैनल को [akLeft, akTop, akRight, akBottom] पर एंकर करें, लेकिन इसके और सीमाओं के बीच स्थान छोड़ दें।
  2. एक बटन जोड़ें जो RecreateWnd()
  3. ऐप चलाएं। फॉर्म का आकार बदलें ताकि पैनल छिपा हुआ हो क्योंकि यह एंकरिंग के कारण आकार में 0 पिक्सेल से कम है। RecreateWnd बटन दबाएं।
  4. फॉर्म को फिर से आकार दें और ध्यान दें कि पैनल का एंकरिंग टूटा हुआ है।

जब तक मैं डेल्फी का उपयोग करके खुद को याद कर सकता हूं, तब तक एंकर हमेशा उपयोग करना असंभव था। फॉर्म का आकार बदलें, फिर इसे डॉक करें: विंडो फिर से बनाई गई है, आपका लेआउट टूटा हुआ है।

मुझे आश्चर्य है कि कुछ प्रकार के कामकाज हैं?

अद्यतन

दो समाधान, टिप्पणियों में उपलब्ध हैं एक सिद्ध और स्थिर लेकिन फार्म के साथ निमिष, एक और एक प्रयोगात्मक लेकिन संभवतः अधिक पूरी तरह से और साफ।

मैं थोड़ी देर के लिए किसी के लिए वोट नहीं दे रहा हूं, क्योंकि उनमें से एक मेरा है और मुझे यह भी यकीन नहीं है कि यह स्थिर है। इसके बजाय, मैं कुछ सार्वजनिक इनपुट की प्रतीक्षा करूंगा।

+0

"उपयोग करने के लिए असंभव" मुझे लगता है कि शीर्ष पर थोड़ा सा है। उपयोग के बहुत सारे मामले जहां फॉर्म के हैंडल को कभी भी पुनर्निर्मित नहीं किया जाता है। –

+0

मुझे ऐसा नहीं लगता है। यहां तक ​​कि जब आप प्रतीत होता है कि अब ऐसा नहीं करते हैं, तो एक महीने बाद आप कुछ ऐसा करते हैं जो पुन: उत्पन्न होता है और बैंग करता है, आपने बिना बगैर बग पेश किए हैं। एंकर अप्रत्याशित हैं। – himself

+0

हम्म हाँ, निश्चित रूप से, यही कारण है कि उनका बहुत उपयोग किया जाता है ... एंकर बहुत अच्छी तरह से काम करते हैं और कई वर्षों से मेरे और कई अन्य लोगों के लिए ऐसा करते हैं। स्पष्ट रूप से आपका लाभ अलग है, लेकिन इनका उपयोग करने में आपकी असमर्थता उन्हें हर किसी के लिए उपयोग करना असंभव नहीं बनाती है। –

उत्तर

4

दो विकल्प मैं जिनमें से इस्तेमाल किया जाता है और नीचे के साथ समस्याओं सही एंकर के लिए वास्तव में आदर्श है है कर रहे हैं:

  1. बुला या RecreateWnd(); के नाम से जाना पैदा कर रहा से पहले फिर से खिड़की बड़ा हो, उसके बाद यह छोटे बनाने फिर। हालांकि इसे फिर से छोटा करने से पहले आपको दिखाना होगा।
  2. फॉर्म की बाधाओं को सेट करें ताकि इसे फिर से आकार में नहीं बदला जा सके ताकि सामान छिप जाए।

एक उदाहरण है कि बड़े फार्म, उपयोग ऊंचाई और चौड़ाई बड़ा पर्याप्त ताकि पैनल छुपी नहीं है मूल्यों पाती है:

procedure TForm1.Button1Click(Sender: TObject); 
Var 
    OldWidth, OldHeight : integer; 
begin 
    OldWidth := Form1.Width; 
    OldHeight := Form1.Height; 
    Form1.Visible := false; 
    Form1.Width := 1000; 
    Form1.Height := 800; 
    RecreateWnd(); 
    Form1.Visible := true; 
    Form1.Width := OldWidth; 
    Form1.Height := OldHeight; 
end; 
+0

धन्यवाद। चाल मदद करता है। फिर भी, एंकरों से निपटना एक पिटा है ... – himself

+0

मुझे आश्चर्य है कि "मुख्य" पैनल का उपयोग करने से फ्लैशिंग के आसपास काम करने में मदद मिल सकती है। मेरा मतलब है कि एक पैनल 'alClient' पर सेट है और * सभी * सामग्री को पकड़ रहा है। फिर, मनोरंजन से पहले, आप फॉर्म के बजाय पैनल को बड़ा करेंगे। कुछ झिलमिलाहट अभी भी दिखाई दे सकती है, लेकिन शायद फॉर्म को बढ़ाने के समय से कम हद तक। –

0

बाहर कर देता है समारोह जो सब कुछ टूट जाता है UpdateAnchorRules है। TControl स्टोर FOriginalParentSize और FAnchorRules में इसका मूल आकार है, और इसका उपयोग माता-पिता के आकार के रूप में स्वत: आकार बदलने के लिए करता है। UpdateAnchorRules() वर्तमान मूल आकार और वर्तमान नियंत्रण Width और Height लेता है और उन्हें FOriginalParentSize और FAnchorRules में सहेजता है।

यदि सब कुछ ठीक से काम करता है जो सामान्य आकार के दौरान कोई प्रभाव नहीं पड़ेगा, क्योंकि नियंत्रण और उसके माता-पिता के आकार के अनुसार आकार बदलता है।

लेकिन जब नियंत्रण Width एंकरिंग, विंडोज के कारण शून्य से कम है, और इसके परिणामस्वरूप डेल्फी अभी भी 0 मानता है। यदि उस बिंदु पर UpdateAnchorRules कहा जाता है, तो यह मूल चौड़ाई के लिए 0 मान से बाहर, गलत-से-समझौता करता है। इसके बाद लेआउट मरम्मत से परे है।यह के रूप में WinAPI CreateWindow में पहली:

जो कुछ भी एक खिड़की संभाल बनाना शामिल कॉल UpdateAnchorRules बाहर बदल जाता है दो बार (यदि यह कहा जाता है नहीं कर रहा है, Width माता पिता Width के लिए उचित संबंध में अद्यतन करने की मूल आकार संरक्षित की वजह से जारी है) लौटने से पहले WM_SIZE प्रेषित करता है (और WM_SIZE हैंडलर UpdateAnchorRules पर कॉल करता है), और दूसरे, स्पष्ट रूप से निर्माण के बाद CreateHandle में।

ऐसा लगता है कि जब तक हम UpdateAnchorRules को CreateHandle की अवधि के लिए अक्षम कर सकते हैं, हम सफल होंगे। लेकिन UpdateAnchorRules पर CreateHandle में स्पष्ट कॉल हैं, जिसका अर्थ है कि किसी ने सोचा था कि को सृजन के बाद एंकर नियमों के समायोजन के लिए की आवश्यकता है।

तो शायद मुझे कुछ याद आ रहा है, और इसे अक्षम करके कुछ तोड़ देगा?

वैसे भी, UpdateAnchorRules को अक्षम करने के दो तैयार तरीके हैं: FAnchorMove सेट करने के लिए या csLoading सेट करने के लिए। सबसे पहले कोई अच्छा नहीं है क्योंकि कोड है जो इसे RecreateWnd के माध्यम से मिडवे साफ़ करता है और फिर UpdateAnchorRules को फिर से कॉल करता है।

type 
    TComponentHack = class helper for TComponent 
    public 
    procedure SetCsLoading(Value: boolean); 
    end; 

procedure TComponentHack.SetCsLoading(Value: boolean); 
var i: integer; 
begin 
    if Value then 
    Self.FComponentState := Self.FComponentState + [csLoading] 
    else 
    Self.FComponentState := Self.FComponentState - [csLoading]; 
    for i := 0 to Self.ComponentCount-1 do 
    if Self.Components[i] is TControl then 
     TControl(Self.Components[i]).SetCsLoading(Value); 
end; 

procedure SafeRecreateWnd(); 
begin 
    MyControl.SetCsLoading(true); 
    try 
    MyControl.RecreateWnd(); //or any operation which triggers it -- such as docking or making the window visible first time after RecreateWnd() 
    finally 
    MyControl.SetCsLoading(false); 
    end; 
end; 

अस्वीकरण:

मुझे पता नहीं और क्या csLoading सेट के साथ TControl आपरेशन चला कर ध्वस्त किया जा सकता है

दूसरा एक काम करता है और यहाँ एक समाधान है।

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