2017-02-08 8 views
5

से ऊपर लिखित रेखा मैंने कुछ अन्य पोस्टों को इस तरह के समान देखा है, लेकिन वे जो जवाब देते हैं वे सवाल का सही जवाब नहीं दे रहे हैं। क्षमा करें अगर कुछ छिपा हुआ है जो मुझे नहीं मिला ...कंसोल एप्लिकेशन - वर्तमान कार्य लाइन

मैं अपने मौजूदा कंसोल के ऊपर कुछ प्रिंट करने के लिए कंसोल। राइटलाइन() का उपयोग करना चाहता हूं। उदाहरण के लिए, मेरा ऐप "हैलो वर्ल्ड" प्रिंट करता है और एक धागा शुरू होता है कि (5 सेकंड में) प्रिंट होगा लाइन, जहां मैं इनपुट कुछ करने की जरूरत है, इस तरह से ऊपर "मैं सिर्फ 5 सेकंड इंतजार कर रहे थे":

Hello world 
Please input something: _ 

फिर 5 सेकंड पारित करेंगे और यह इस तरह दिखेगा:

Hello world 
I just waited 5 seconds 
Please input something: _ 

अब तक मैंने कंसोल का उपयोग करने का प्रयास किया है। SetCursorPosition (0, Console.Cur sorTop - 1) लेकिन यह सिर्फ लाइन पर प्रिंट करता है "कृपया कुछ इनपुट करें: _" और यदि मैं कंसोल का उपयोग करता हूं। कर्सरटॉप - 2 इसके बजाय यह "[2] सीमा से बाहर" कहता है (कोई विचार क्यों नहीं है) और यदि मैं उपयोग करता हूं Console.CursorTop - 2 इसके तहत प्रिंट "इनपुट कुछ करें: _" ... तो मेरे सवाल यह है कि कैसे "कृपया इनपुट कुछ: _" मैं रेखा से ऊपर कुछ प्रिंट करना

+1

मुझे यह भी नहीं लगता कि यह संभव है, है ना? एक कंसोल एक "एक बार लिखा है, यह वहां है" सौदा का प्रकार, नहीं? – jleach

+1

@ jdl134679 मैंने एक प्रोग्राम देखा है –

+1

@ jdl134679: मानक आउटपुट स्ट्रीम हाँ, लेकिन यदि आप चाहें तो कंसोल के चरित्र बफर को संशोधित कर सकते हैं। – Joey

उत्तर

0

आप गाड़ी-रिटर्न उपयोग कर सकते हैं (\r, या यू + 000 डी) कर्सर को वर्तमान लाइन की शुरुआत में वापस करने के लिए, और उसके बाद वहां क्या ओवरराइट करें।

// A bunch of spaces to clear the previous output 
Console.Write("\r        "); 
Console.WriteLine("\rI just waited 5 seconds"); 
Console.Write("Please input something: "); 

हालांकि तरह, उपयोगकर्ता पहले से टाइपिंग शुरू कर दिया है, तो यह अब और काम करेंगे नहीं (जैसा कि आप सभी वे टाइप किया है ऊपर लिख नहीं हो सकता है, और वे खो देंगे क्या वे स्क्रीन पर टाइप किया है, हालांकि यह स्मृति में अभी भी वहाँ है।

ठीक से इस का समाधान करने के लिए आप वास्तव में सांत्वना के चरित्र बफर को संशोधित करने की जरूरत है। आप वर्तमान पंक्ति एक लाइन से ऊपर सब कुछ ले जाते हैं, और फिर अपने संदेश डालने के लिए है। आप को स्थानांतरित करने के Console.MoveBufferArea उपयोग कर सकते हैं एक क्षेत्र ऊपर। फिर आपको वर्तमान कर्सर की स्थिति को सहेजने की आवश्यकता है, कर्सर को ऊपर की रेखा की शुरुआत में ले जाएं, अपना संदेश लिखें, और कर्सर को रीसेट करें सहेजे गए एक को फिर से osition।

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

+0

हाँ जैसा कि आप कहते हैं, यह काम नहीं करेगा क्योंकि प्रिंट होने पर मैं कुछ लिखने के माध्यम से आधा रास्ता हो सकता हूं। –

5

बस कर्सर को स्थानांतरित करना पर्याप्त नहीं है, समस्या यह है कि आप टेक्स्ट डाल रहे हैं। यह संभव है, Console.MoveBufferArea() विधि आपको कंसोल के अंतर्निहित स्क्रीन बफर तक पहुंच प्रदान करती है और आपको टेक्स्ट और विशेषताओं को दूसरी पंक्ति में ले जाने देती है।

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

कुछ नमूना कोड वहां पहुंचने के लिए:

static string TimedReadline(string prompt, int seconds) { 
    int y = Console.CursorTop; 
    // Force a scroll if we're at the end of the buffer 
    if (y == Console.BufferHeight - 1) { 
     Console.WriteLine(); 
     Console.SetCursorPosition(0, --y); 
    } 
    // Setup the timer 
    using (var tmr = new System.Timers.Timer(1000 * seconds)) { 
     tmr.AutoReset = false; 
     tmr.Elapsed += (s, e) => { 
      if (Console.CursorTop != y) return; 
      int x = Cursor.Left; 
      Console.MoveBufferArea(0, y, Console.WindowWidth, 1, 0, y + 1); 
      Console.SetCursorPosition(0, y); 
      Console.Write("I just waited {0} seconds", seconds); 
      Console.SetCursorPosition(x, y + 1); 
     }; 
     tmr.Enabled = true; 
     // Write the prompt and obtain the user's input 
     Console.Write(prompt); 
     return Console.ReadLine(); 
    } 
} 

नमूना उपयोग:

static void Main(string[] args) { 
    for (int ix = 0; ix < Console.BufferHeight; ++ix) Console.WriteLine("Hello world"); 
    var input = TimedReadline("Please input something: ", 2); 
} 

नोट Console.Top संपत्ति पर परीक्षण, यह सुनिश्चित करता है कुछ भी नहीं काफी गलत हो जाता है कि जब उपयोगकर्ता ने बहुत अधिक टेक्स्ट टाइप किया और स्क्रॉल को मजबूर कर दिया या कंसोल। रीडलाइन() टाइमर द्वारा चुने गए सटीक समय पर पूरा हो गया। यह सुनिश्चित करना कि सभी संभावित मामलों में यह थ्रेड-सुरक्षित है, करना मुश्किल है, कंसोल के दौरान निश्चित रूप से परेशानी होगी। रीडलाइन() कर्सर क्षैतिज रूप से उसी समय चलती है जब विलम्बित ईवेंट हैंडलर चलता है। मैं आपको your own Console.ReadLine() method लिखने की सलाह देता हूं ताकि आप लॉक डाल सकें और आत्मविश्वास महसूस कर सकें कि यह हमेशा सुरक्षित रहता है।

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