2015-03-20 8 views
12

मैं यह समझने की कोशिश कर रहा हूं कि जीडीआई + ग्राफिक्स कंटेनर विभिन्न ग्राफिक इकाइयों के साथ कैसे काम करते हैं। नीचे दिए गए कोड पर एक नज़र डालें। यह संकलित करता है, आप इसे एक नए नए रूप में पेस्ट कर सकते हैं।ग्राफिक कंटेनर कैसे काम करते हैं?

void Form2_Paint(object sender, PaintEventArgs e) 
{ 
    var gfx = e.Graphics; 

    System.Diagnostics.Debug.WriteLine("DpiX={0}, DpiY={1}", gfx.DpiX, gfx.DpiY); 

    gfx.PageUnit = GraphicsUnit.Inch; 

    var pen = new Pen(Color.Black, 0.01f); 

    // Create outer container, 2 inches in size with X and Y set to 0.1 inches 
    var outerContainer = gfx.BeginContainer(
     new RectangleF(0.1f, 0.1f, 2, 2), 
     new RectangleF(0, 0, 2, 2), 
     GraphicsUnit.Pixel); 

    // Draw the outer rectangle 
    gfx.DrawRectangle(pen, new Rectangle(0, 0, 2, 2)); 

    // Create inner container, 1 inch in size with X and Y set to 0.1 inches 
    var innerContainer = gfx.BeginContainer(
     new RectangleF(0.1f, 0.1f, 1, 1), 
     new RectangleF(0, 0, 1, 1), 
     GraphicsUnit.Pixel); 

    // Draw the inner rectangle 
    gfx.DrawRectangle(pen, new Rectangle(0, 0, 1, 1)); 

    gfx.EndContainer(innerContainer); 

    gfx.EndContainer(outerContainer); 
} 

ऊपर कोड नेस्टेड ग्राफिक कंटेनर का एक बहुत ही सरल उदाहरण है, मैंने कोई स्केलिंग परिवर्तन नहीं किया। यह कैसे प्रपत्र जब रंग हैंडलर ऊपर प्रयोग किया जाता है की तरह लग रहा है:

graphics container illustration

यह बहुत आसान है। अब, मैं यह वर्णन करने की कोशिश करूंगा कि समस्या क्या है।

public GraphicsContainer BeginContainer(
    RectangleF dstrect, 
    RectangleF srcrect, 
    GraphicsUnit unit 
) 

क्या मैं समझने में नाकाम रहने रहा हूँ GraphicsUnit unit तर्क है:

यह BeginContainer विधि का एक हस्ताक्षर है।

MSDN से

:

GraphicsUnit गणन कि कंटेनर लिए माप की इकाई को निर्दिष्ट की

सदस्य।

यह सत्य होने के लिए प्रतीत होता है!

जैसा कि आप मेरे कोड में देख सकते हैं मैं इनच इकाइयों का उपयोग कर रहा हूं: gfx.PageUnit = GraphicsUnit.Inch

लेकिन, जब मैं कंटेनर बना रहा हूं, तो मैं BeginContainer विधि: GraphicsUnit.Pixel पर इकाइयों के तर्क के रूप में गुजर रहा हूं। कंटेनर के निर्माण के बाद क्या होता है? इंच का उपयोग किया जा रहा है (जो मैं वास्तव में चाहता हूं)। लेकिन अगर मैं (या मिलीमीटर या कुछ भी अन्य) को तर्क के लिए पास करता हूं, पिक्सेल का उपयोग किया जाता है। तो, ऐसा लगता है कि जो कुछ मैं चाहता हूं उसे पूरा करने के लिए (इंच का उपयोग करें) मुझे पिक्सल निर्दिष्ट करना होगा?

इससे मुझे कोई समझ नहीं आता है। आप उपरोक्त कोड में BeginContainer विधियों में इकाइयों को बदलने का प्रयास कर सकते हैं और अजीब परिणाम देख सकते हैं। मैंने एमएसडीएन पढ़ा है और जो कुछ भी मैं इस पर इकट्ठा कर सकता हूं लेकिन मैं अभी भी अनजान हूं।

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

तो, ऊपर दिए गए सभी प्रश्न, मेरा प्रश्न है: इस विधि में unit तर्क का उद्देश्य क्या है?

+0

परिणाम क्या होना चाहिए? एक 1 पिक्सेल आकार आयताकार? मैं * सोचता हूं * आयताकार जो आप कन्स्ट्रक्टर में उपयोग कर रहे हैं उसके साथ कुछ करने के लिए। यह भ्रमित हो जाता है। – LarsTech

+0

@ लार्स आयताकार इंच इकाइयों में हैं। मैं मूल रूप से मिलीमीटर में अधिक "सामान्य दिखने वाले" आंकड़े रखता था लेकिन मुझे लगा कि डीपीआई डॉट्स प्रति इंच होने के कारण इंच को डीबग करना आसान हो सकता है। फॉर्म पर आप जो आयताकार देखते हैं वे बिल्कुल कंटेनरों का आकार हैं। – bokibeg

उत्तर

8

दुर्भाग्यवश, जीडीआई + जहां तक ​​मैं विंडोज़ में सबसे खराब दस्तावेज एपीआई में से एक को बता सकता हूं। वेब पर कुछ ब्राउज़िंग बहुत कम लोगों को वास्तव में इसका उपयोग कर रही है, और आपके प्रश्न में कोई अंतर्दृष्टि नहीं है।

और भी दुर्भाग्यवश, जीडीआई + एपीआई मूल रूप से .NET Graphics ऑब्जेक्ट पर सीधे कॉपी की गई थी। यहां तक ​​कि दस्तावेज़ीकरण अधिकांश भाग के लिए सिर्फ क्रियापद प्रतिलिपि बनाई गई थी। के बीच समानता नोट करें।नेट Graphics.BeginContainer Method (RectangleF, RectangleF, GraphicsUnit) और विंडोज Graphics.BeginContainer(const RectF, const RectF, Unit) method पेज।

आगे मामलों को मुश्किल करने के लिए, वहाँ है this blog entry जो tantalizingly पढ़ता है:

एक और उदाहरण ग्राफिक्स कक्षा में सहेजें और BeginContainer तरीकों, जो बहुत अलग ढंग से प्रदर्शन है, फिर भी एक ही MSDN प्रलेखन कि बीच अंतर करने में विफल रहता है है दो कॉल

और नरकिप; लेकिन इन दोनों विधियों को वास्तव में अलग कैसे किया जाता है, इस बारे में किसी भी विवरण में जाने में विफल रहता है।

अब, वह सब कुछ प्रयोग के साथ, ने कहा, मुझे लगता है कि मैं मापदंडों और व्यवहार डीकोड किया है:

  • unit पैरामीटर srcrect पैरामीटर
  • के लिए इस्तेमाल किया इकाइयों निर्दिष्ट करने के लिए इस्तेमाल किया जा करने के लिए प्रकट dstrect मानकों वर्तमान में Graphics वस्तु
  • नए कंटेनर अपने Graphics.PageUnitGraphicsUnit.Display
  • का डिफ़ॉल्ट मान के लिए वापस सेट के साथ हवाएँ के लिए उपयोग में इकाइयों में निर्दिष्ट किया जाता है

मुझे कोई दस्तावेज में उपरोक्त पहले दो बिंदुओं का संकेत नहीं मिला। यह केवल प्रयोग और सावधानीपूर्वक अवलोकन के माध्यम से था कि मैंने यह सीखा, और स्पष्ट रूप से मेरे निष्कर्ष को वापस करने के लिए वास्तविक दस्तावेज़ीकरण के बिना, मैं अभी भी इसके बारे में 100% निश्चित नहीं हूं।

वहाँ BeginContainer() विधि के दस्तावेज में तीसरे बिंदु के एक संकेत है:

ग्राफिक्स राज्य BeginContainer विधि द्वारा स्थापित डिफ़ॉल्ट ग्राफिक्स राज्य के प्रतिपादन गुणों में शामिल हैं; जब विधि कहा जाता है तो किसी भी प्रतिपादन-गुणवत्ता वाले राज्य में परिवर्तन डिफ़ॉल्ट मानों पर रीसेट होते हैं।

पहली नज़र में, यह वाक्य कह रहा है कि केवल "प्रतिपादन-गुणवत्ता वाले राज्य परिवर्तन" रीसेट हैं। लेकिन अधिक ध्यान से पढ़ते हुए, कोई देखता है कि राज्य के उस हिस्से को विशेष रूप से विशेष रूप से बुलाया जा रहा है, क्योंकि में शामिल है जो रीसेट किया गया है। दी, एक और अधिक सावधान पढ़ने अपने किसी भी अतिरिक्त समझ :(हासिल नहीं है, लेकिन कम से कम एक देख सकते हैं वाक्य सब कुछ कि रीसेट है पर अंतिम शब्द के रूप में नहीं लिया जाना चाहिए।


तो चीजों को सही तरीके से काम करने की कुंजी उन इकाइयों को निर्दिष्ट करना होगा जिन्हें आप काम करना चाहते हैं (उदाहरण के लिए GraphicsUnit.Inch) रास्ते के प्रत्येक चरण पर: BeginContainer() पर कॉल में, कंटेनर बनाने से पहले प्रारंभिक सेटिंग्स में (लेकिन यहां, केवल srcrect को जिस तरह से व्याख्या किया जा रहा है उसे नियंत्रित करें), और उसके बाद अंततः BeginContainer() के बाद, Graphics.PageUnit संपत्ति को फिर से सेट करें।

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

एक उदाहरण के रूप में, यहाँ एक टुकड़ा है, जहां मैं कंटेनर के लिए प्रारंभिक Graphics राज्य के लिए इंच, और मिलीमीटर का उपयोग करें:

gfx.PageUnit = GraphicsUnit.Inch; 

using (Pen blackPen = new Pen(Color.Black, 0.01f)) 
using (Pen redPen = new Pen(Color.Red, 0.01f)) 
{ 
    gfx.DrawRectangle(blackPen, .25f, .25f, 2, 2); 

    var outerContainer = gfx.BeginContainer(
     new RectangleF(.25f, .25f, 2, 2), 
     new RectangleF(0, 0, 2 * 25.4f, 2 * 25.4f), 
     GraphicsUnit.Millimeter); 

    gfx.PageUnit = GraphicsUnit.Millimeter; 
    gfx.DrawRectangle(redPen, .25f * 25.4f, .25f * 25.4f, 1.5f * 25.4f, 1.5f * 25.4f); 

    gfx.EndContainer(outerContainer); 
} 

कि इस छवि का उत्पादन:

nested rectangles

तो मैं मैं कंटेनर के बाहर 2x2 इंच आयत खींचने में सक्षम हूं, और फिर कंटेनर के अंदर मैं 1.5x1.5 इंच आयताकार खींचता हूं, लेकिन मिलीमीटर का उपयोग करके ऐसा करता हूं (पैरामीटर में स्पष्ट रूप से परिवर्तित करना, बस इसे स्पष्ट करने के लिए मैं खुद क्या कर रहा हूँ)।

+1

महान जवाब! मिमी और इंच के बीच आपका रूपांतरण सुझाव साबित करता है कि 'इकाई' वास्तव में केवल 'srcrect' पर लागू होती है। इकाइयों को प्रदर्शित करने के लिए रीसेट के साथ संयुक्त यह अजीब व्यवहार बताता है। मैं थोड़ी अधिक प्रयोग करूँगा लेकिन ** कम से कम ** मैं सही ढंग से फ़ंक्शन का उपयोग करूँगा और अजीब समय पर प्रिंटर को भेजी जाने वाली बड़ी गड़बड़ी का जोखिम नहीं उठाऊंगा। उम्मीद है कि ये सवाल डीडीआई + एपीआईएस डीकोडिंग के सिरदर्द से बचाने के लिए Googleable होंगे। – bokibeg

0

शायद, आपको बिल्कुल परवाह करने की आवश्यकता नहीं है।

मैं Graphics.BeginContainer पर भी सही तर्क पारित करने में विफल रहा। हालांकि, Transform विधियों (ResetTransform अंत में) का उपयोग करके समस्या को हल करने के लिए पूरी तरह से काम किया।

तो, पहले कंटेनरों को समझने की कोशिश करने से पहले Transform विधियों पर विचार करें।

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