سؤال

لدي تطبيق ينشئ ملفات التعريف (EMFS). يستخدم الجهاز المرجعي (AKA الشاشة) لتقديم هذه ملفات التعريف هذه، لذلك DPI من تغييرات التعريف اعتمادا على ما الجهاز الذي يعمل عليه الرمز قيد التشغيل.

دعونا نقول رمزي ينوي إنشاء ملف تعريف يبلغ 8.5 في x 11 داخل. باستخدام محطة عمل التطوير الخاصة بي كمرجع، في نهاية المطاف مع EMF

  • RCLFRAME من {0، 0، 21590، 27940} (أبعاد ملف التعريف، بألف من ملم)
  • Szldevice من {1440، 900} (أبعاد الجهاز المرجعي، بالبكسل)
  • a szlmillimeters من {416، 260} (أبعاد الجهاز المرجعي، في مم)

حسنا، لذلك يخبرني RCLFRame أن حجم EMF يجب أن يكون

  • 21590/2540 = 8.5 في نطاق واسع
  • 27940/2540 = 11 في طويل القامة

الحق علي. باستخدام هذه المعلومات، يمكننا تحديد DPI الفيزيائي لشاشتي أيضا، إذا كانت الرياضيات الخاصة بي صحيحا:

  • (1440 * 25.4) / 416 = 87.9231 DPI الأفقي
  • (900 * 25.4) / 260 = 87.9231 DPI العمودي

المشكلة

أي شيء يلعب مرة أخرى هذه التعريف - تحويل EMF-To-PDF، صفحة "ملخص" عند النقر بزر الماوس الأيمن على EMF في مستكشف Windows، وما إلى ذلك - يبدو أن اقتطاع قيمة DPI المحسوبة، وعرض 87 بدلا من 87.9231 (حتى 88 سيكون على ما يرام).

ينتج عن هذا صفحة بحجم طبيعي بحجم 8.48 في × 10.98 في (باستخدام 87 نقطة في البوصة) بدلا من 8.5 في x 11 في (باستخدام 88 نقطة في البوصة) عند تشغيل ملف التعريف.

  • هل من الممكن تغيير DPI من الجهاز المرجعي بحيث يتم تشغيل المعلومات المخزنة في ملف التعريف المستخدمة لحساب DPI إلى عدد صحيح لطيف؟
  • هل يمكنني إنشاء سياقتي الخاصة وتحديد DPI؟ أو هل يجب علي حقا استخدام طابعة للقيام بذلك؟

شكرا لأي نظرة ثاقبة.

هل كانت مفيدة؟

المحلول

أنا فضولي حول كيفية علم Windows بالحجم الفيزيائي لشاشتك. يجب أن تكون قد تغيرت التكوين في مكان ما؟ ربما يمكنك تغييرها إلى قيم أكثر ملاءمة تقسم بشكل جيد.

كما هو ضمني باسم، يجب توصيل "سياق الجهاز" بجهاز النظام. ومع ذلك، لا يحتاج هذا إلى أن يكون برنامج تشغيل الأجهزة، فقد يكون محاكي الجهاز مثل برنامج تشغيل طباعة كاتب PDF. لقد رأيت واحدة على الأقل يتيح لك تعيين DPI تعسفي.

نصائح أخرى

لقد تعلمت الآن أكثر مما كنت أهتم بأنه عرف عن التعريف.

1. بعض من Metafile يعمل زائد منشئ الفئة بشكل سيء وسيعمل على قيمة DPI مقطوعة.

النظر فيما يلي:

protected Graphics GetNextPage(SizeF pageSize)
{
    IntPtr deviceContextHandle;
    Graphics offScreenBufferGraphics;
    Graphics metafileGraphics;
    MetafileHeader metafileHeader;

    this.currentStream = new MemoryStream();
    using (offScreenBufferGraphics = Graphics.FromHwnd(IntPtr.Zero))
    {
        deviceContextHandle = offScreenBufferGraphics.GetHdc();
        this.currentMetafile = new Metafile(
            this.currentStream,
            deviceContextHandle,
            new RectangleF(0, 0, pageSize.Width, pageSize.Height),
            MetafileFrameUnit.Inch,
            EmfType.EmfOnly);

        metafileGraphics = Graphics.FromImage(this.currentMetafile);

        offScreenBufferGraphics.ReleaseHdc();
    }

    return metafileGraphics;
}

إذا مرت في SizeF من {8.5، 11}، قد تتوقع الحصول على Metafile هذا لديه rclFrame من {21590، 27940}. تحويل بوصة إلى ملليمترات ليست صعبة، بعد كل شيء. ولكن ربما لن تفعل ذلك. اعتمادا على قرارك، GDI +، يبدو، سيستخدم قيمة DPI مقطوعة عند تحويل المعلمة بوصة. للحصول عليه بشكل صحيح، يجب أن أفعل ذلك بنفسي في مئات ملليمتر، الذي يمر GDI + فقط لأن هذا هو كيف يتم تخزينه بطريقة مخزنة في رأس ملف التعريف:

this.currentMetafile = new Metafile(
    this.currentStream,
    deviceContextHandle,
    new RectangleF(0, 0, pageSize.Width * 2540, pageSize.Height * 2540),
    MetafileFrameUnit.GdiCompatible,
    EmfType.EmfOnly);

خطأ التقريب # 1 حل rclFrame من بلدي metafile هو الصحيح الآن.

2. DPI على Graphics التسجيل المثيل إلى Metafile هو دائما خطأ.

أنظر لهذا metafileGraphics متغير الذي حددته عن طريق الاتصال Graphics.FromImage() على ملف التعريف؟ حسنا، يبدو أن ذلك Graphics سيكون لديك مثيل دائما DPI من 96 نقطة في البوصة. (إذا اضطررت للتخمين، فهو دائما تعيين على منطقي DPI، وليس بدني واحد.)

يمكنك أن تتخيل أن الفرق التي تلا ذلك عندما ترسم على Graphics مثيل يعمل تحت 96 نقطة في البوصة والتسجيل إلى Metafile مثيل يحتوي على 87.9231 DPI "المسجل" في رأسه. (أقول "سجلت" لأنها محسوبة من القيم الأخرى. "بكسل" (تذكر، يتم تحديد أوامر GDI المخزنة في ملف التعريف بكسل) أكبر، وبالتالي فإنك لعنة ومتمتم لماذا مكالمتك لرسم شيء واحد ينتهي طويلا بوصة كونه واحد وشيء ما بين بوصة طويلة.

الحل هو توفير أسفل Graphics نموذج:


metafileGraphics = Graphics.FromImage(this.currentMetafile);
metafileHeader = this.currentMetafile.GetMetafileHeader();
metafileGraphics.ScaleTransform(
    metafileHeader.DpiX / metafileGraphics.DpiX,
    metafileHeader.DpiY / metafileGraphics.DpiY);

ليس هذا صاح يبدو أنه يعمل.

"التقريب" خطأ # 2 حل - عندما أقول رسم شيء في "1 بوصة" في 88 نقطة في البوصة، وكان هذا بكسل أفضل $٪ $ ^! سجلت باسم بكسل # 88.

3. szlMillimeters يمكن أن تختلف بعنف؛ سطح المكتب البعيد يؤدي الكثير من المرح.

لذلك، اكتشفنا (لكل رابطة لكل علامة)، في بعض الأحيان، يستعلم نظام التشغيل Windows EDID من شاشتك ويعرف فعليا مدى حجمه جسديا. يستخدم GDI + بشكل مفيدHORZSIZE إلخ) عند ملء szlMillimeters منشأه.

الآن تخيل أنك تذهب إلى المنزل لتصحيح رمز سطح المكتب البعيد هذا. دعنا نقول أن الكمبيوتر المنزلي الخاص بك يحدث مراقب عريض 16: 9.

من الواضح أن Windows لا يمكنه الاستعلام عن EDID من شاشة بعيدة. So it uses the age-old default of 320 x 240 mm, which would be fine, except that it happens to be a 4:3 aspect ratio, and now the exact same code is generating a metafile on a display that supposedly has non- البكسلات المادية المربعة: DPI الأفقي DPI المختلفة مختلفة، ولا أستطيع أن أتذكر آخر مرة رأيت فيها ذلك يحدث.

الحل البديل لهذا الآن هو: "حسنا، لا تعمل تحت سطح المكتب البعيد."

4. أداة EMF-TO-PDF التي كنت أستخدمها لها خطأ في التقريب عند النظر إلى rclFrame رأس.

كان هذا السبب الرئيسي لمشكلتي التي أثارت هذا السؤال. كان Metafile الخاص بي "صحيحا" طوال الوقت (حسنا، صحيح بعد إصلاح أول قضيتين)، وكان كل هذا البحث عن إنشاء ملف تعريف "عالي الدقة" كان رنجة حمراء. صحيح أن بعض الإخلاص يتم فقد عند تسجيل ملف التعريف على جهاز عرض منخفض الدقة؛ وذلك لأن أوامر GDI المحددة في ملف التعريف محددة في البكسل. لا يهم أنه تنسيق متجه ويمكنه التوسع لأعلى أو لأسفل، فقد بعض المعلومات خلال التسجيل الفعلي عندما تقرر GDI + ما "بكسل" لالتقاط عملية ل.

اتصلت بالمورد وأعطوني نسخة تصحيح.

تقريب الخطأ # 3 حلها.

5. جزء "الموجز" في مستكشف Windows يحدث حتى يتم اقتطاع القيم عند عرض DPI المحسوب.

يحدث ذلك فقط أن هذه القيمة المقطوعة تمثل نفس القيمة الخاطئة التي تستخدمها أداة EMF-TO-PDF داخليا. بصرف النظر عن هذا، فإن هذا Quirk لا يسهم أي شيء مفيد للمناقشة.

الاستنتاجات

نظرا لأن سؤالي كان حول Futzing مع DPI على سياقات الجهاز، فإن Mark's هي إجابة جيدة.

لاحظ أنني أركض مع 120 نقطة في البوصة على WXP طوال الوقت (الخطوط الكبيرة) والتي تعني MetafileGraphics.DPIX إرجاع 120.

لا يبدو أن ملف EMF يسجل ما كان DPI من السياق المرجعي (120 في هذه الحالة، 96 من أجل معظم الأشخاص الآخرين).

لجعل الأمور أكثر إثارة للاهتمام، من الممكن إنشاء EMF عبر الرسم على صورة نقطية في الذاكرة التي لديها SetResolution () تعيين، على سبيل المثال، 300DPI. في هذه الحالة، أعتقد أن عامل التحجيم يجب أن يكون 300 وليس ما يجب أن يستخدمه الشاشة (86.x) أو Windows (120).

يبدو أن القيم في صفحة الملخص مخطئة. يتم حسابها على النحو التالي:

Size = round(precize_size)+1
Resolution = trunc(precize_resolution)

حيث يتم احتساب إعداد القيم دون تقريب أو اقتطاع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top