2011-02-01 22 views
5


मैं उपयोगकर्ता को उसी फ़ॉर्म के कई उदाहरण बनाने देना चाहता हूं (चलिए इसे फॉर्म 1 कहते हैं जो एक एमडीआई बाल रूप है)। तो मेरे पास दो प्रक्रियाएं हैं जहां मैं फॉर्म बनाते हैं।अजीब "TFrm1 नामक एक घटक पहले से मौजूद है" त्रुटि

procedure MyProcedure1;   // procedure 2 is similar. it also has a var called MyFrm 
var MyFrm: TFrm1; 
begin 
    ... 
    MyFrm:= TFrm1.create(MainForm); 
    MyFrm.BringToFront; 
    MyFrm.LoadFromFile(someFile); 
end; 

जैसा कि आप देख सकते हैं MyFrm स्थानीय var है। यह मेरे लिए ठीक है क्योंकि मुझे इसे बनाने के बाद प्रोग्राम को प्रोग्रामिक रूप से एक्सेस करने की आवश्यकता नहीं है। Frm1 नामक कोई अन्य वैश्विक चर नहीं है। MyFrm के ऑनक्लोज़ इवेंट में मेरे पास एक्शन है: = caFree;

उपरोक्त त्रुटि का कारण क्या हो सकता है? एक उपयोगकर्ता ने उस त्रुटि को भेजा। यह केवल एक बार हुआ और मैं इसे पुन: पेश नहीं कर सकता।


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

  1. "MyFrm: = TFrm1.create" में त्रुटि दिखाई लाइन।

  2. कुछ लोगों ने सुझाव दिया कि मुझे प्रोग्रामिंग रूप से अद्वितीय नाम को मेरे गतिशील रूप से बनाए गए रूपों में प्रोग्राम करने की आवश्यकता है। मैंने यह भी सोचा कि जब इसे बनाया गया है तो फॉर्म का नाम क्या होता है, इसलिए MyProcedure1 प्रक्रिया को कॉल करते समय मैंने कोड में कदम रखा।
    डेल्फी स्वचालित रूप से
    MyFrm.name = MyFrm तरह अद्वितीय नाम,
    MyFrm.name = MyFrm_1,
    MyFrm.name = MyFrm_2,
    MyFrm.name = MyFrm_3, और इतने पर देता है तो।

  3. MyFrm.Name LoadFromFile में नहीं बदला गया है। मैंने प्रक्रिया MyProcedure1 के अंत में 'MyFrm.Name' के मान को चेक किया है (ब्रेकपॉइंट); LoadFromFile के बाद। नाम अद्वितीय है।

  4. कुछ लोगों ने सुझाव दिया है कि, मैंने SetName प्रक्रिया को ओवरराइड किया है और TMyFrm का नाम चेक किया है। वास्तव में प्रत्येक रूप एक अद्वितीय नाम मिलता है।

    प्रक्रिया TMyFrm.SetName (कॉन्स वैल्यू: TComponentName);

    शोमेसेज (मान);
    विरासत में मिला;
    अंत;

  5. मेरे पास इस ऐप में कई रूप हैं लेकिन केवल मेनफॉर्म ऑटो-निर्मित है।

  6. मैं थ्रेड का उपयोग नहीं करता हूं। वैसे भी यह प्रासंगिक नहीं होगा क्योंकि फॉर्म उपयोगकर्ता द्वारा बनाए जाते हैं (इसलिए बहु-थ्रेडिंग अप्रासंगिक है जब तक कि उपयोगकर्ता एक ही समय में 2 रूपों को बना नहीं सकता)।

+2

एर, यह 'LoadFromFile' विधि क्या है? यह आपके में से एक होना चाहिए, जब तक यह XE में कुछ जोड़ा नहीं जाता है। –

+0

@ डेविड, मैंने 'लोडफ्रॉमफ़ाइल' का उल्लेख दो उत्तरों पर टिप्पणियों के कारण के रूप में किया है। चूंकि ओपी ने इसका उल्लेख नहीं किया है, मुझे लगता है कि यह 'LoadFromFile' नहीं है। ओपी द्वारा दिए गए कोड में –

+0

@Lieven, एकमात्र जगह जहां यह असफल हो सकती है वह 'LoadFromFile' है। यह जानने के बिना कि हम क्या अनुमान लगा रहे हैं। यदि @Altar हमें यह बताना चाहता है कि 'LoadFromFile' क्या करता है तो मुझे यकीन है कि यह सब स्पष्ट हो जाएगा। –

उत्तर

8

MainForm देते होना चाहिएTFrm1 में मालिक के रूप में। बनाएं मुख्यफॉर्म की घटकों की सूची में नव निर्मित फ़ॉर्म शामिल होगा। एक घटक यह सुनिश्चित करता है कि इस सूची में एक ही गैर-खाली नाम वाले किसी भी दो घटक नहीं हैं (अन्यथा FindComponent काम नहीं करेगा)। यह तंत्र तब भी काम करता है जब कोई घटक इसका नाम बदलता है।

जब तक आप TFrm1 में नाम निर्दिष्ट नहीं करते हैं। इसे सबसे अधिक संभावना है कि यह LoadFromFile विधि द्वारा सेट किया गया है, जिसका अर्थ है कि जब तक आप फ़ाइल की सामग्री नहीं बदलते तब तक आपके नाम पर अधिक प्रभाव नहीं पड़ता ।

एक वैध वर्कअराउंड मालिक के रूप में शून्य के साथ फॉर्म बनाने, फ़ाइल से फ़ॉर्म लोड करने, नाम को एक अद्वितीय मान या खाली स्ट्रिंग में बदलने के लिए है और अंत में MainForm.InsertComponent को कॉल करें।

procedure MyProcedure1;   
var MyFrm: TFrm1; 
begin 
    ... 
    MyFrm:= TFrm1.create(nil); 
    MyFrm.BringToFront; 
    MyFrm.LoadFromFile(someFile); 
    MyFrm.Name := ''; // or some unique name 
    MainForm.InsertComponent(MyFrm); 
end; 
+0

+1 अच्छा स्पष्टीकरण –

+0

हाय उवे। मैंने आपकी सलाह ली और मैंने पूरी Frm1 इकाई में 'नाम' की खोज की (मैंने मैन्युअल रूप से लोडफ्रॉमफ़ाइल का निरीक्षण किया - बस सुनिश्चित करने के लिए)। कोई भी 'नाम' संपत्ति सेट नहीं कर रहा है। – Ampere

+0

मैंने ऐसा किया लेकिन प्रक्रिया MyProcedure1 के अंत में। यह आपके विचार के समान ही है क्योंकि उस समय MyFrm गुंजाइश से बाहर हो गया है और कोई भी इसे एक्सेस नहीं करता है। – Ampere

3

MyFrm.Name दोनों मामलों के लिए एक ही है ...

सुनिश्चित करें की तुलना में MyFrm.Name अद्वितीय है ... क्योंकि प्रत्येक प्रपत्र विशिष्ट नामित किया जाना चाहिए

+0

डेल्फी स्वचालित रूप से गतिशील रूप से बनाए गए रूपों के लिए अद्वितीय नाम असाइन करते हैं। – Ampere

6

संदेश कारण होता है।

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

बनाएं कॉल के बाद

MyFrm.Name := MyFrm.Name + <something unique>; 

MyFrm.Name := ''; 

जोड़ें और आप ठीक

+4

नाम अद्वितीय या कुछ भी होने की आवश्यकता नहीं है। 'MyFrm.Name: =' 'बेहतर है यदि आपको नाम की परवाह नहीं है, क्योंकि आपको एक नया नाम जानने की आवश्यकता नहीं है और वीसीएल विशिष्टता के लिए नाम की जांच छोड़ने के लिए मिलता है। –

+1

नहीं। डेल्फी स्वचालित रूप से गतिशील रूप से बनाए गए रूपों के लिए एक अद्वितीय नाम असाइन करते हैं। – Ampere

+0

@ कॉस्मीन, ओह डर्न, यही मेरा मतलब था, लेकिन मेरे दिमाग में धागे मिश्रित हो गए। नाम को एक खाली स्ट्रिंग पर सेट करना वह है जो मैं हमेशा डेटामैड्यूल के लिए करता हूं जो कई बार तत्काल होते हैं। संपादित उत्तर –

0

जहां तक ​​इस रेखा के साथ मेरी अन्वेषण, हाँ की समस्या "पहले से मौजूद" नाम संपत्ति के लिए एक ही मूल्य के साथ संपादक की intances होने से उपजी है। जैसा कि एक और काम आसपास के रूप में संपादक (ओं) बनाते हैं। संपादक (ओं) के लिए TForm/TFrame/TPanel के आधार पर एक नया घटक बनाएं, जिसे आप चाहते हैं कि उपयोगकर्ता कई उदाहरण बना सके। आपको सृजन & किसी भी उप-नियंत्रण को हटाने, अपने गुणों को अपने कोड में सेट करने और मान निर्दिष्ट करने के लिए कोड करना होगा - V_Btn = new TBitBtn (this), V_Btn-> रंग = clTeal से V_Btn-> OnClick = Close_The_Window से कुछ भी । लेकिन कभी भी नई कक्षा में किसी भी घटक की नाम संपत्ति के लिए कोई मान निर्दिष्ट न करें और संपादक के उदाहरण बनाने के बाद संपादक की नाम संपत्ति सेट न करें। संपादक के लिए नाम संपत्ति का इलाज करें जैसे कि यह अस्तित्व में नहीं था। के बाद आप वर्ग बनाया है और अपनी परियोजना के लिए इसे जोड़ लिया है निम्नलिखित मान्य है:

TMyeditor* Editor_01 = new TMyeditor(Main_Form); 
TMyeditor* Editor_02 = new TMyeditor(Main_Form); 
    Editor_01->Parent = Tab_Sheet_Addresses; 
    Editor_02->Parent = Tab_Sheet_Billing; 

अपने संपादक वर्ग कोड करने के लिए आप undergoe होगा और अधिक प्रयास के लिए और अधिक जटिल डिजाइन अवधारणा। हालांकि यह दृष्टिकोण "पहले से मौजूद" त्रुटि को हल करेगा। के रूप में यह है कि तुम क्या आगे मैं इसे साथ मदद करने के लिए यह मामला होना चाहिए लिखना अपने कोड & के साथ क्या करना चाहते हो सकता है का एक विस्तार है

  End of answer. 

निम्नलिखित मूल प्रश्न के tangental है।

void RegisterClassesWithStreamingSystem(void) 
{ 
    // Make sure that as part of the startup 
    // code TMyEditor is registered 
    // with the streaming system. 
    #pragma startup RegisterClassesWithStreamingSystem 
    Classes::RegisterClass(__classid(TMyEditor)); 
} 

: निम्नलिखित आप कुशलता से स्टोर करने के लिए, संपादक (s) और इस तरह के उपयोगकर्ता के स्क्रीन, थीम आदि पर स्थिति के रूप में अपनी प्रकाशित गुण पुनः प्राप्त आप ऊपर मार्ग चला गया है/जोड़ने की अनुमति देता है निम्नलिखित अब आप कंपोनेंट टॉस्ट्रिंग < ---> स्ट्रिंगटो कॉम्पोनेंट [* 1] संपादक (ओं) कर सकते हैं। अब आप प्रत्येक संपादक का एक सरल डेटाबेस बना सकते हैं [* 2] और रनटाइम पर संपादक को फिर से बना सकते हैं। & सहेजना लगभग पूरी तरह से TReader/TWriter ऑब्जेक्ट्स द्वारा किया जाता है। {यह लायक जबकि Treader/TWriter जो डेल्फी मदद फ़ाइल में शामिल है के बारे में पढ़ने के लिए है}

[presupposing आप TMyEditor के उदाहरणों आप Editor_01 & Editor_02 और बुलाया बचाने के लिए आप डाटासेट बना लिया है करना चाहते हैं और हालांकि यह संभावना है किया जाना चाहिए था - यह एक TClientDataSet नाम "सीडीएस"]

//How to write the Editors 
String_Version_Of_Editor = ComponentToString(Editor_01); 
CDS->Insert(); 
CDS->FieldByName("Data")->AsString = String_Version_Of_Editor; 
CDS->Post(); 
String_Version_Of_Editor = ComponentToString(Editor_02); 
CDS->Insert(); 
CDS->FieldByName("Data")->AsString = String_Version_Of_Editor; 
CDS->Post(); 

//How to read, create an instance of, set the Owner of 
//(allowing for automatic destruction/deletion 
// if desired, Vis-à-vis Let the compiler/runtime package handle that), 
//& setting the form's Parent 
AnsiString String_Version_Of_Editor; 
TWinControl* New_Editor; 
String_Version_Of_Editor = CDS->FieldByName("Data")->AsString; 
//The next line creates/constructs the new editor 
New_Editor = StringToComponent(String_Version_Of_Editor); 
//The next line sets the new editor's Owner to Main_Form 
//It also assigns Main_Form the responsibility of object cleanup 
Main_Form->Insert(New_Editor); 
//The next line sets the Editor's Parent causing it to be part of the 
//displayed user interface (it has been invisble since creation) 
New_Editor->Parent = Tab_Sheet_Addresses; 
//Move on to the next editor; 
CDS->Next(); 
String_Version_Of_Editor = CDS->FieldByName("Data")->AsString; 
New_Editor = StringToComponent(String_Version_Of_Editor); 
Main_Form->Insert(New_Editor); 
New_Editor->Parent = Tab_Sheet_Billing; 

जो लोग उपरोक्त पढ़ लिया है, जो चतुर का उल्लेख किया है होगा कि उपरोक्त कोड में New_Editor प्रकार का है TWincontrol नहीं TMyEditor हैं करने के लिए आवंटित । हालांकि मैं इस किया था तथ्य संशय का विषय है डेल्फी में Treader वस्तु जो वास्तव में एक घटक वस्तु उदाहरण के लिए एक स्ट्रिंग परिवर्तित करने का काम कर रही है/निर्माण करती किसी भी वस्तु जो RegisterClass के माध्यम से स्ट्रीमिंग वर्ग के साथ पंजीकृत किया गया है बनाता है कि लोगों का ध्यान आकर्षित करने के लिए। इस तरीके से स्पष्ट रूप से नाम के नामकरण के माध्यम से संपादक की स्पष्ट रचना से बचा जाता है। यहां तक ​​कि उस की आवश्यकता नहीं है अगर TWinControl * परे प्रकाशित गुण TMyEditor के दायरे से बाहर तक पहुँचा नहीं कर रहे हैं - - उदाहरण TMyEditor सोचा TMyEditor और उसके वंशज ही परिवर्तन के डिजाइन कोड के लिए आवश्यक करने के लिए दिया जाता है TMyEditor * करने के लिए TWinControl * बदलने के लिए है उन चरों तक पहुंच है जिनके मूल्यों को संपादित किया जा रहा है और इस जानकारी को संपादक को प्रदान करने की आवश्यकता नहीं है। (यदि डेटा मॉड्यूल से काम करना है, तो डेटामोड्यूल के हेडर को टीएमईडिटर में शामिल करें)।

साइड नोट: आपके पास यह जानने के लिए उपयोगिता हो सकती है कि डेटाबेस से कौन सी कक्षा पढ़ी गई थी ताकि आप उस उदाहरण को कह सकें जहां यह संबंधित है। अपने कोड में यह #include <typeinfo> करने के लिए। उदाहरण: यदि आप डेटाबेस के लिए TMyEditor, TMyEditor_Generation_01, TMyEditor_Generation_02, आदि लिखा के उदाहरण है, तो आप पर निम्न बातें उदाहरणों यूजर इंटरफेस में प्लेसमेंट के लिए कार्यावधि में पढ़ जांच करने के लिए अनुमति देगा:

if (typeid(New).name() == "TMyEditor *") 
    New_Editor->Parent = Tab_Sheet_Addresses; 
    else 
    if (typeid(New).name() == "TMyEditor_Generation_01 *") 
    New_Editor->Parent = Tab_Sheet_Billing; 
    else 
    if (typeid(New).name() == "TMyEditor_Generation_02 *") 
     New_Editor->Parent = Tab_Sheet_Other_Editor; 

typeid (_ _) .name() एक स्ट्रिंग लौटाएगा जो कक्षा का नाम है, इस मामले में "*" भी शामिल होगा।

उपर्युक्त किसी भी डेटाबेस में संग्रहीत करने के लिए ऑब्जेक्ट्स को पुनर्निर्मित करने और पुनर्निर्मित करने की अनुमति देता है। डेटाबेस के भीतर प्रविष्टियों को संबंधित होने की आवश्यकता नहीं है। डेल्फी के कोड में दफन किए गए ट्रेडर ऑब्जेक्ट रनवेटाइम पर तय करेंगे कि वे क्या हैं और सही कन्स्ट्रक्टर का उपयोग करते हैं।

[* 1] नोट: ComponentToString और StringToComponent delpi/C++ मदद फ़ाइल में उदाहरण हैं।

[* 2] नोट: क्या सहेजा जा रहा है प्रकाशित गुण है, इसलिए अपने संपादक कक्षा में किसी भी मूल्यों आप संग्रहीत और पुनः प्राप्त करना चाहते हैं जो पहले से ही विरासत में मिला और प्रकाशित की __published अनुभाग में घोषित किया जाना चाहिए नहीं कर रहे हैं आपकी नई कक्षा वे आइटम कस्टम ऑब्जेक्ट्स भी हो सकते हैं, जिनके लिए आप _property को परिभाषित करने में पढ़ने/लिखने के उपयोग विनिर्देशकों के लिए कोड कस्टम विशिष्ट विधियों/कार्यों की संभावना होगी। मैं विकास के दौरान अपने कोड की जांच करने में आसानी के लिए किसी भी जटिल वस्तु को स्ट्रिंग मान में अनुवाद करने का सुझाव दूंगा।

+2

इनमें से किसी के पास पूछे गए प्रश्न के साथ कुछ भी नहीं है, जो ** रनटाइम ** पर किसी फॉर्म के कई उदाहरण बनाने में समस्या के बारे में था। सवाल डिजाइन समय संपादक, संपत्ति संपादकों, कक्षाओं को पंजीकृत करने, या आपके पूरे उत्तर में कुछ और के साथ बिल्कुल कुछ नहीं करता है। –

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