إنشاء قائمة DELPHI الغريبة
المترجم: البريد الإلكتروني لي جونيو: [email protected]،[email protected]
قوائم مخصصة، نص، خطوط / دلفي 4، 5
قائمة مخصصة، نص، سطر/دلفي 4، 5
القوائم الفاخرة، الخ.
قوائم غريبة، الخ.
القوائم المخصصة والنص المستدير والخطوط الخاصة
قوائم مخصصة ونص مستدير وخطوط خاصة
قبل دلفي 4، كان من الصعب تخصيص القائمة (إضافة صورة نقطية، تغيير الخط، وما إلى ذلك)، لأن رسم المالك (أي الرسم المخصص) - على الرغم من أنه تم تنفيذه بواسطة Windows - لم يتم كشفه بواسطة فئة TMainMenu منذ دلفي 4،. ومع ذلك، فقد تم تصحيح هذا الوضع، ويمكننا أن نشق طريقنا مع القوائم.
قبل دلفي 4، كان من الصعب تخصيص قائمة (مثل إضافة صورة BMP، تغيير الخط، وما إلى ذلك) لأن حدث الرسم الخاص بالمالك (أي حدث الرسم المخصص) - على الرغم من أنه يتم تنفيذه بواسطة Windows، إلا أنه لا يظهر في فئة TMainMenu منذ دلفي 4،
لقد تغير هذا الوضع، وأصبح لدينا الآن القدرة على تخصيص القوائم.
سوف تسلط هذه المقالة الضوء على بعض التقنيات التي يمكنك استخدامها لتخصيص مظهر القوائم في تطبيقات دلفي الخاصة بك. سنناقش موضع النص، وحجم القائمة، وتعيين الخط، واستخدام الصور النقطية والأشكال لتحسين مظهر القائمة، في هذه المقالة كما يتميز أيضًا بتقنيات إنشاء نص تمت استدارته وخطوط مخصصة، ويتم عرض كافة التقنيات التي تمت مناقشتها في هذه المقالة في PROjects المتوفرة للتنزيل.
ستركز هذه المقالة على بعض التقنيات التي يمكنك استخدامها لتخصيص مظهر القوائم في تطبيقات DELPHI الخاصة بك، وسنغطي موضع النص وحجم القائمة وإعدادات الخط والتحسينات باستخدام ملفات BMP والتحكم في الشكل . ولأغراض المتعة فقط، ستحتوي هذه المقالة أيضًا على صورة مقربة لتقنيات تدوير النص والخطوط المخصصة. تم تصحيح كافة التقنيات التي تمت مناقشتها في هذه المقالة في ملفات المشروع ويمكن تنزيلها عبر الإنترنت.
الخطوط والأحجام المخصصة
ضبط الخط والحجم
لإنشاء قائمة مخصصة، قم بتعيين خاصية OwnerDraw لمكون القائمة -TMainMenu أو TPopupMenu - إلى True، وقم بتوفير معالجات الأحداث لأحداث OnDrawItem وOnMeasureItem الخاصة به، على سبيل المثال، يتم تعريف معالج الأحداث OnMeasureItem كما يلي:
لإنشاء قائمة مخصصة، قم بتعيين الخاصية OwnerDraw لمكون TmainMenu أو TpopupMenu إلى TRUE، وقم بإنشاء إجراءات الأحداث OnDrawItem وOnMeasureItem الخاصة بها. على سبيل المثال، يمكن الإعلان عن إجراء حدث OnMeasureItem كما يلي:
الإجراء TForm1.Option1MeasureItem(Sender: TObject;
ACanvas: TCanvas؛ var Width, Height: Integer);
قم بتعيين متغيرات العرض والارتفاع لضبط حجم عنصر القائمة. معالج الأحداث OnDrawItem هو المكان الذي يتم فيه تنفيذ كل العمل الشاق؛ فهو المكان الذي ترسم فيه القائمة وتقوم بإجراء أي إعدادات خاصة لرسم خيار القائمة بخط Times New Roman ، على سبيل المثال، يجب عليك القيام بشيء مثل هذا:
قم بتعيين متغيرات العرض والارتفاع لعنصر القائمة في إجراء الحدث أعلاه إلى الأحجام المناسبة. يتم تشغيل كافة الأشياء الرئيسية بواسطة حدث OnDrawItem؛ وهذا هو المكان الذي ستعيد فيه رسم القائمة وإجراء أي إعدادات خاصة. على سبيل المثال، لإعادة رسم عنصر قائمة بخط Times New Roman، يمكنك القيام بما يلي:
الإجراء TForm1.Times1DrawItem(Sender: TObject;
ACanvas: TCanvas؛ ARect: TRect؛
يبدأ
ACanvas.Font.Name := 'تايمز نيو رومان'؛
ACanvas.TextOut(ARect.Left+1, ARect.Top+1,
(المرسل باسم TMenuItem).Caption)؛
نهاية؛
ومع ذلك، فإن هذا الرمز معيب. إذا تم تشغيله، فسيتم رسم التسمية التوضيحية للقائمة بمحاذاة الحد الأيسر من القائمة. وهذا ليس سلوك Windows الافتراضي؛ لذلك، هناك مساحة لوضع الصور النقطية وعلامات الاختيار في القائمة. يجب عليك حساب المساحة اللازمة لعلامة الاختيار هذه باستخدام رمز مثل ذلك الموضح في الشكل 1. ويوضح الشكل 2 القائمة الناتجة.
لكن هذا الرمز معيب. إذا قمت بتشغيل هذا الرمز، فسيتم محاذاة التسمية التوضيحية لعنصر القائمة إلى يسار عنصر القائمة، وهذا ليس هو السلوك الافتراضي لنظام التشغيل Windows، وعادةً ما تكون هناك مسافة على الجانب الأيسر من القائمة لصورة BMP والتحديد علامة. لذلك، يجب عليك استخدام الكود لحساب مقدار المساحة المطلوبة لوضع علامة التحديد، كما هو موضح في الشكل 1. ويبين الشكل 2 القائمة قيد التنفيذ.
الإجراء TForm1.Times2DrawItem(Sender: TObject;
ACanvas: TCanvas؛ ARect: TRect؛
فار
dwCheck: عدد صحيح؛
MenuCaption: سلسلة؛
يبدأ
// احصل على أبعاد علامة الاختيار.
احصل على عدد البكسل المطلوب لشعار التحديد
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// ضبط الموضع الأيسر.
ضبط الوضع الأيسر
ARect.Left := ARect.Left + LoWord(dwCheck) + 1;
MenuCaption := (المرسل كـ TMenuItem).Caption;
// اسم الخط هو تسمية القائمة.
ACanvas.Font.Name := 'تايمز نيو رومان'؛
// ارسم النص.
رسم النص
DrawText(ACanvas.Handle، PChar(MenuCaption)،
الطول (MenuCaption)، ARect، 0)؛
نهاية؛
الشكل 1: يقوم معالج الأحداث OnDrawItem بوضع نص عنصر القائمة بشكل صحيح.
[حذف المترجم جميع الأشكال، كما هو موضح أدناه]
الشكل 2: قائمة مرسومة بخطوط مخصصة.
إذا كان النص كبيرًا جدًا بحيث لا يمكن رسمه في القائمة، فسيقوم Windows بقصه ليناسبه، لذلك، يجب عليك تعيين حجم عنصر القائمة بحيث يمكن رسم النص بالكامل. وهذا هو دور معالج الأحداث OnMeasureItem الموضح في الشكل 3 .
إذا كان النص طويلاً جدًا، فسيقوم Windows تلقائيًا بقصه ليناسب النص. لذلك، يجب تغيير حجم القائمة بحيث يمكن عرض النص بأكمله. يجب أن يكون الشيء نفسه صحيحًا في حدث OnMeasureItem، والذي يمكن رؤيته في الشكل 3.
الإجراء TForm1.Times2MeasureItem(Sender: TObject;
ACanvas: TCanvas؛ var Width, Height: Integer);
يبدأ
ACanvas.Font.Name := 'تايمز نيو رومان'؛
ACanvas.Font.Style := [];
// العرض هو مساحة فحص القائمة
هذا الطول هو طول علامة اختيار القائمة
// بالإضافة إلى عرض نص العنصر.
بالإضافة إلى طول عنصر القائمة
العرض := GetSystemMetrics(SM_CXMENUCHECK) +
ACanvas.TextWidth((المرسل كـ TMenuItem).Caption) + 2;
الارتفاع := ACanvas.TextHeight(
(المرسل باسم TMenuItem).Caption) + 2;
نهاية؛
الشكل 3: يضمن معالج الأحداث OnMeasureItem أن العنصر يناسب قائمته.
الأشكال والصور النقطية المخصصة
إعداد الرسومات والصور النقطية
من الممكن أيضًا تخصيص عناصر القائمة عن طريق تضمين صور نقطية أو أشكال أخرى لإضافة صورة نقطية، ما عليك سوى تعيين ملف صورة نقطية إلى خاصية TMenuItem.Bitmap - باستخدام Object Inspector في وقت التصميم، أو باستخدام التعليمات البرمجية في وقت التشغيل كتسمية توضيحية لعنصر القائمة، يمكنك استخدام معالج الأحداث OnDrawItem الموضح في الشكل 4. ويوضح الشكل 5 النتيجة.
من الممكن إعداد قوائم باستخدام الصور النقطية والرسومات الأخرى. لإضافة صورة نقطية، ما عليك سوى تعيين ملف BMP إلى خاصية الصورة النقطية لـ TmenuItem في Object Inspector في وقت التصميم، أو من الممكن أيضًا استخدام التعليمات البرمجية في وقت التشغيل. لاستبدال عنوان القائمة بمستطيل ملون، يمكنك استخدام الحدث OnDrawItem، كما هو موضح في الشكل 4. تظهر النتائج في الشكل 5.
الإجراء TForm1.ColorDrawItem(Sender: TObject;
ACanvas: TCanvas؛ ARect: TRect؛
فار
dwCheck: عدد صحيح؛
لون القائمة: TColor؛
يبدأ
// احصل على أبعاد علامة الاختيار.
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
ARect.Left := ARect.Left + LoWord(dwCheck);
// تحويل التسمية التوضيحية لعنصر القائمة إلى لون.
تحويل عنوان عنصر القائمة إلى اللون
لون القائمة :=
StringToColor((المرسل كـ TMenuItem).Caption);
// تغيير لون فرشاة القماش.
تغيير لون فرشاة القماش
ACanvas.Brush.Color := MenuColor;
// يرسم المستطيل إذا تم تحديد العنصر.
يرسم مستطيلاً إذا تم تحديد عنصر القائمة
// ارسم الحدود.
رسم الحدود
إذا تم تحديده بعد ذلك
ACanvas.Pen.Style := psSolid
آخر
ACanvas.Pen.Style := psClear;
ACanvas.Rectangle(ARect.Left، ARect.Top،
ARect.Right، ARect.Bottom)؛
نهاية؛
الشكل 4: استخدام الحدث OnDrawItem لرسم مستطيلات ملونة على عناصر القائمة.
الشكل 5: قائمة تحتوي على مستطيلات ملونة كعناصر.
هناك مشكلة واحدة فقط. إذا كنت تستخدم دلفي 5، فيجب عليك تعيين خاصية AutoHotkeys الخاصة بالقائمة إلى maManual. إذا تركتها كإعداد افتراضي، maAutomatic، فسوف تضيف دلفي حرف علامة العطف (&) إلى التسمية التوضيحية، مما سيؤدي إلى كسر هذا. الحل الآخر هو إزالة علامة الضم باستخدام وظيفة StripHotKey.
الأسلوب الأكثر شيوعًا هو أنه إذا كنت تستخدم دلفي 5، فيجب عليك تعيين خاصية AutoHotkeys الخاصة بالقائمة على maManual. إذا لم تقم بذلك وتركت القيمة الافتراضية maAutomatic، ستقوم دلفي تلقائيًا بإضافة علامة العطف إلى العنوان، مما سيؤدي إلى كسر الكود. الحل الآخر هو استخدام الدالة StripHotKey لإزالة علامة الضم.
هناك طريقة أخرى لاستخدام الأحداث OnDrawItem وOnMeasureItem وهي كتابة النص عموديًا في القائمة (كما هو موضح في الشكل 7)، للقيام بذلك، يجب عليك إنشاء خط تمت استدارته، وهذا ممكن فقط باستخدام وظيفة Windows API CreateFont أو CreateLogFont (انظر نصيحة "النص الذي تمت استدارته" لاحقًا في هذه المقالة). ثم يجب عليك رسمه في معالج الأحداث OnDrawItem. يتم تشغيل هذا الحدث في كل مرة يتم فيها رسم عنصر قائمة، لذلك إذا تم رسم القائمة 20 عنصرًا، سيتم رسمه 20 مرة لجعله أسرع، سيتم رسم النص الرأسي فقط عند تحديد عنصر القائمة (نظرًا لوجود عنصر قائمة واحد فقط محدد في المرة الواحدة). يوضح الشكل 6 كيفية تنفيذ ذلك باستخدام التعليمات البرمجية ويبين الشكل 7 نتيجة وقت التشغيل.
الاستخدام الآخر لأحداث OnDrawItem وOnMeasureItem هو كتابة نص رأسي بجوار القائمة (كما هو موضح في الشكل 7). للقيام بذلك، عليك إنشاء خط مستدير. الطريقة الوحيدة هي استخدام الدالة CreateFont أو CreateLogFont الخاصة بـ Windows API (راجع تقنية "النص الذي تمت استدارته" لاحقًا في هذه المقالة). لذلك عليك إعادة رسمه في حدث OnDrawItem. يتم تنفيذ هذا الحدث عند سحب عنصر القائمة، لذلك إذا كانت القائمة تحتوي على 20 عنصرًا، فسيتم تنفيذها 20 مرة. ولجعل الأمر أسرع، يمكن إعادة رسم النص الرأسي في كل مرة يتم فيها تحديد عنصر قائمة (على الرغم من تحديد عنصر قائمة واحد فقط في كل مرة). ويبين الشكل 6 كيفية تنفيذ التعليمات البرمجية، بينما يوضح الشكل 7 النتائج.
الإجراء TForm1.VerticalDrawItem(Sender: TObject;
ACanvas: TCanvas؛ ARect: TRect؛
فار
lf : TLogFont;
OldFont:HFont;
clFore, clBack: LongInt;
المستطيل: TRect؛
dwCheck : LongInt;
ارتفاع القائمة: عدد صحيح؛
يبدأ
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// سيتم ذلك مرة واحدة، عند تحديد العنصر.
سيتم تنفيذ ذلك عند تحديد عنصر القائمة
إذا تم تحديده ثم ابدأ
// إنشاء خط مستدير.
إنشاء خط استدارة
fillChar(lf, SizeOf(lf), 0);
lf.lfHeight := -14;
lf.lfEscapement := 900;
lf.lfOrientation := 900;
lf.lfWeight := Fw_Bold;
StrPCopy(lf.lfFaceName, 'Arial');
// حدد هذا الخط للرسم.
حدد هذا الخط للرسم
OldFont := SelectObject(ACanvas.Handle,
CreateFontIndirect(lf));
// تغيير ألوان المقدمة والخلفية.
تغيير الألوان الأمامية والخلفية
clFore := SetTextColor(ACanvas.Handle, clSilver);
clBack := SetBkColor(ACanvas.Handle, clBlack);
// احصل على ارتفاع القائمة.
الحصول على ارتفاع القائمة
ارتفاع القائمة := (ARect.Bottom-ARect.Top) *
((المرسل باسم TMenuItem). الأصل باسم TMenuItem).Count؛
Rectang := Rect(-1, 0, dwCheck-1, MenuHeight);
// ارسم النص.
رسم النص
ExtTextOut(ACanvas.Handle, -1, MenuHeight, Eto_Clipped,
@Rectang، "صنع في بورلاند"، 15، لا شيء)؛
// يعود إلى حالته الأصلية.
العودة إلى الحالة الأصلية
حذفObject(SelectObject(ACanvas.Handle, OldFont));
SetTextColor(ACanvas.Handle, clFore);
SetBkColor(ACanvas.Handle, clBack);
نهاية؛
// ارسم نص القائمة الحقيقي.
ارسم نص عنصر القائمة الحقيقي
ARect.Left := ARect.Left + LoWord(dwCheck) + 2;
رسم النص (ACanvas.Handle،
PChar((المرسل كـ TMenuItem).التسمية التوضيحية)،
الطول (((المرسل كـ TMenuItem).Caption)، ARect، 0)؛
نهاية؛
الشكل 6: استخدام OnDrawItem لرسم نص رأسي في القائمة.
الشكل 7: قائمة تحتوي على نص عمودي.
إحدى التفاصيل الصعبة هي معرفة مكان البدء في رسم النص، حيث يجب أن يبدأ من أسفل العنصر الأخير في القائمة، وللحصول على موضعه، نحصل على ارتفاع عنصر القائمة، باستخدام:
يجب أن تعرف من أين تبدأ رسم النص. يجب أن يبدأ في أسفل العنصر الأخير في القائمة. للحصول على هذا الموضع، نحصل على ارتفاع عنصر القائمة كما يلي:
أركت.أعلى - أركت.أسفل
وضربه بعدد العناصر في القائمة:
وضربها في عدد عناصر القائمة:
(((المرسل كـ TMenuItem).الأصل كـ TMenuItem).العدد)
استدارة النص
استدارة النص
تسمح لك واجهة برمجة تطبيقات Windows برسم النص في أي زاوية للقيام بذلك في دلفي، يجب عليك استخدام وظيفة API CreateFont أو يتم تعريف CreateFontIndirect كما هو موضح في الشكل 8.
تتيح لك واجهة برمجة تطبيقات Windows رسم النص بأي زاوية. للقيام بذلك في دلفي، يجب عليك استخدام وظيفتي API CreateFont أو CreateFontIndirect. يوضح الشكل 8 كيفية الإعلان عن CreateFont.
وظيفة إنشاء الخط (
nHeight, // الارتفاع المنطقي للخط.
nWidth, // متوسط عرض الأحرف المنطقي.
nEscapement، // زاوية الهروب
nOrientation، // زاوية اتجاه الخط الأساسي.
fnWeight: عدد صحيح؛ // وزن الخط
fdwItalic, // علامة السمة المائلة هل هي مائلة؟
fdwUnderline, // علامة السمة المسطرة ما إذا كان سيتم التسطير
fdwStrikeOut, // علامة سمة Strikeout لتحديد ما إذا كان يجب استخدام سمة Strikeout
fdwCharSet // معرف مجموعة الأحرف
fdwOutputPrecision, // دقة الإخراج.
fdwClipPrecision, // دقة القطع.
fdwQuality, // جودة الإخراج.
fdwPitchAndFamily: DWORD;
lpszFace: PChar // مؤشر لسلسلة اسم المحرف.
): HFONT;
الشكل 8: إعلان Object Pascal لوظيفة CreateFont Windows API.
على الرغم من أن هذه الدالة تحتوي على العديد من المعلمات، إلا أنك ستحتاج عادةً إلى تغيير سمة واحدة أو اثنتين فقط من سمات النص، وفي مثل هذه الحالات، يجب عليك استخدام الدالة CreateFontIndirect بدلاً من ذلك، فهي تأخذ وسيطة واحدة فقط - سجل من النوع TLogFont، كما هو موضح في الشكل 9.
على الرغم من أن هذه الوظيفة تأخذ العديد من المعلمات، إلا أنك عادةً ما تحتاج فقط إلى تغيير خاصية أو اثنتين من خصائص النص. في هذه الحالة، يمكنك استخدام الدالة CreateFontIndirect بدلاً من ذلك. فهو يتطلب معلمة واحدة فقط - معلمة نوع السجل لـ TlogFont، كما هو موضح في الشكل 9.
tagLOGFONTA = سجل معبأ
الارتفاع: لونجينت؛
lfWidth: لونجينت؛
lfEscapement: Longint;
lfOrientation: لونجينت؛
الوزن: لونجينت؛
lfمائل: بايت؛
lfتسطير: بايت؛
lfStrikeOut: بايت؛
lfCharSet: بايت؛
lfOutPrecision: بايت؛
lfClipPrecision: بايت؛
lfQuality: بايت؛
lfPitchAndFamily: بايت؛
lfFaceName: الصفيف[0..LF_FACESIZE - 1] من AnsiChar؛
نهاية؛
TLogFontA = tagLOGFONTA;
TLogFont = TLogFontA;
الشكل 9: سجل TLogFont.
بالنظر إلى هذا السجل، ستلاحظ أن أعضائه يطابقون معلمات وظيفة CreateFont، وتتمثل ميزة استخدام مجموعة الوظيفة/السجل في أنه يمكنك ملء أعضاء السجل بخط معروف باستخدام وظيفة GetObject API، وتغيير الأعضاء الذين تريدهم. تريد، وإنشاء الخط الجديد.
إذا نظرت عن كثب إلى نوع السجل هذا، فستجد أن أعضائه متشابهون جدًا مع معلمات وظيفة CreateFont. تتمثل ميزة استخدام مجموعة الوظيفة/السجل هذه في أنه يمكنك استخدام وظيفة GetObject API لملء قيم الأعضاء لهذا السجل بخط معروف، ثم تغيير قيمة العضو التي تريد تغييرها لإنشاء خط جديد.
لرسم نص تم تدويره، العضو الوحيد الذي يجب عليك تغييره هو lfEscapement، الذي يضبط زاوية النص بعشر الدرجات، لذا، إذا كنت تريد رسم النص عند 45 درجة، فيجب عليك تعيين lfEscapement على 450.
لرسم نص تم تدويره، العنصر الوحيد الذي تحتاج إلى تغييره هو lfEscapement، الذي يضبط زاوية الخط بعشر الدرجة. لذلك، إذا كنت تريد أن تدور الشخصية بمقدار 45 درجة، فيجب عليك ضبطها
الهروب هو 450.
لاحظ أن هناك علامات لرسم نص مائل وتسطير وشطب، ولكن لا توجد علامة لرسم نص غامق ويتم ذلك مع العضو lfWeight، وهو رقم بين 0 و1000. 400 هو نص عادي، والقيم أعلى من ذلك. ارسم نصًا غامقًا، والقيم الموجودة أسفله ترسم نصًا فاتحًا.
لاحظ أن هناك عددًا لا بأس به من العلامات لوضع النص بشكل مائل وتسطيره وتمييزه، ولكن لا توجد علامات لإنشاء نص غامق. وذلك لأنه يتم استخدام العضو lfWeight بدلاً من ذلك، وقيمة هذا العضو تتراوح بين 0 و1000. 400 هي القيمة العادية، وأي شيء فوق ذلك يكون غامقًا، وأي شيء أقل من ذلك يكون رفيعًا.
يقوم الكود الموجود في الشكل 10 برسم النص بزوايا تتراوح من 0 درجة إلى 360 درجة، بفواصل زمنية تبلغ 20 درجة، وهو معالج أحداث OnPaint الخاص بالنموذج، لذا تتم إعادة رسم النص في كل مرة يتم فيها رسم النموذج.
يقوم الكود الموجود في الشكل 10 برسم الأحرف كل 20 درجة من 0 إلى 360 درجة. يتم تشغيل ذلك في حدث OnPaint الخاص بالنموذج، بحيث تتم إعادة رسم النص في كل مرة يتم فيها رسم النموذج. ويمكن رؤية التأثير في الشكل 11.
الإجراء TForm1.FormPaint(Sender: TObject);
فار
أولدفونت، نيوفونت: hFont؛
لوغفونت: تيلوغفونت؛
ط: عدد صحيح؛
يبدأ
// احصل على مقبض خط القماش.
الحصول على المقبض لكائن خط النموذج
OldFont := Canvas.Font.Handle;
أنا := 0;
// رسم شفاف.
تعيين خاصية الشفافية
SetBkMode(Canvas.Handle,Transparent);
// املأ بنية LogFont بالمعلومات
املأ بنية LogFont بالمعلومات
// من الخط الحالي.
من الخط الحالي
GetObject(OldFont, Sizeof(LogFont), @LogFont);
// تتراوح الزوايا من 0 إلى 360.
من 0 إلى 360 درجة
بينما أنا <3600 أبدأ
// اضبط ميزان الهروب على زاوية جديدة.
ضبط اتجاه النص على زاوية جديدة
LogFont.lfEscapement := i;
// إنشاء خط جديد.
إنشاء خط جديد
NewFont := CreateFontIndirect(LogFont);
// حدد الخط المراد رسمه.
حدد الخطوط للإخراج
SelectObject(Canvas.Handle, NewFont);
// ارسم النص في منتصف النموذج.
نص الإخراج في منتصف النموذج
TextOut(Canvas.Handle, ClientWidth div 2,
ClientHeight div 2، 'Rotated Text'، 21)؛
// تنظيف.
واضح
حذفObject(SelectObject(Canvas.Handle, OldFont));
// زيادة الزاوية بمقدار 20 درجة.
يزيد كل 20 درجة
شركة (ط، 200)؛
نهاية؛
نهاية؛
الشكل 10: رمز لرسم نص يتم تدويره بفواصل زمنية قدرها 20 درجة.
الشكل 11: النص تم تدويره بمقدار 360 درجة.
تم تعيين خط النموذج على Arial، وهو خط TrueType. يعمل هذا الرمز فقط مع خطوط TrueType؛ ولا تدعم الأنواع الأخرى من الخطوط تدوير النص للحصول على إعدادات الخط الحالية وملء بنية TLogFont، يجب عليك استخدام وظيفة GetObject API. يوضح الكود الموجود في الشكل 12 كيفية ملء وعرض إعدادات TLogFont لخط النموذج.
تم تعيين خط هذا النموذج إلى Arial، وهو خط TrueType. يعمل هذا الرمز فقط ضمن خطوط TrueType؛ ولا تدعم الخطوط الأخرى تدوير النص. للحصول على إعدادات الخط الحالية وملء بنية TlogFont، يجب عليك استخدام وظيفة GetObject API. في الكود الموجود في الشكل 12، يمكنك معرفة كيفية ملء وعرض إعدادات TlogFont في النموذج.
الإجراء TForm1.Info1Click(Sender: TObject);
فار
لوغفونت: تيلوغفونت؛
يبدأ
// املأ بنية LogFont بالمعلومات
املأ قيم الأعضاء في بنية LogFont
// من الخط الحالي.
من الخط الحالي
GetObject(Canvas.Font.Handle, Sizeof(LogFont), @LogFont);
// عرض معلومات الخط.
إظهار معلومات الخط
باستخدام LogFont قم بإجراء ShowMessage(
'lfHeight: ' + IntToStr(lfHeight) + #13 +
'lfWidth: ' + IntToStr(lfWidth) + #13 +
'lfEscapement: '+IntToStr(lfEscapement) + #13 +
'lfOrientation: ' + IntToStr(lfOrientation) + #13 +
'lfWeight: ' + IntToStr(lfWeight) + #13 +
'lfItalic: ' + IntToStr(lfItalic) + #13 +
'lfUnderline: ' + IntToStr(lfUnderline) + #13 +
'lfStrikeOut: ' + IntToStr(lfStrikeOut) + #13 +
'lfCharSet: ' + IntToStr(lfCharSet) + #13 +
'lfOutPrecision: ' + IntToStr(lfOutPrecision) + #13 +
'lfClipPrecision: ' + IntToStr(lfClipPrecision) + #13 +
'lfQuality: ' + IntToStr(lfQuality) + #13 +
'lfPitchAndFamily: '+IntToStr(lfPitchAndFamily) + #13 +
'lfFaceName: ' + string(lfFaceName));
نهاية؛
الشكل 12: الحصول على سمات الخط وعرضها.
بمجرد حصولك على الإعدادات في بنية TLogFont، فإن التغيير الوحيد المتبقي هو ضبط lfEscapement على الزاوية المطلوبة وإنشاء خط جديد باستخدام CreateFontIndirect قبل استخدام هذا الخط الجديد، يجب تحديده باستخدام SelectObject من هذا الخط الجديد إلى مقبض خط اللوحة القماشية، قبل رسم النص، بعد رسم النص، يجب تحديد الخط القديم، وحذف الخط الجديد. إذا لم يتم حذفه، فسيكون هناك تسرب للذاكرة، و- إذا تم تنفيذ الروتين عدة مرات - فسوف تنفد موارد Windows (خاصة 95/98) ويتعطل.
بمجرد قيامك بإعداد بنية TlogFont، كل ما عليك فعله هو تغيير قيمة lfEscapement إلى القيمة المستهدفة واستخدام CreateFontIndirect لإنشاء خط جديد. قبل استخدام هذا الخط الجديد، يجب عليك استخدام SelectObject لتحديده. أسلوب آخر هو استخدام مقبض كائن الخط الجديد هذا إلى مقبض كائن الخط في لوحة الرسم القماشية للنموذج قبل رسم النص. بعد رسم النص، تبدأ العملية، ويجب تحديد الخط القديم وحذف الخط الجديد. إذا لم تتم إزالة الخط الجديد، فسوف يتسبب في تسرب الذاكرة، و---- إذا تم تنفيذ البرنامج عدة مرات------ فسوف تنفد موارد Windows (خاصة 95/98)، و
يتحطم.
خطوط أنيقة
خطوط شعبية
عندما ترسم خطوطًا، لا يهم عادةً وحدات البكسل الفردية؛ فكل ما عليك فعله هو تعيين نمط الخط، ويتم رسمه بواسطة Windows. ومع ذلك، في بعض الأحيان، تحتاج إلى القيام بشيء خاص ورسم نمط خط لا يوفره Windows باستخدام وظيفة Windows API المسماة LineDDA، والمحددة في الشكل 13.
عندما تقوم برسم الخطوط، عادةً ما تكون وحدات البكسل الفردية غير مهمة؛ فما عليك سوى تعيين نوع الخط وسيترك الأمر لنظام التشغيل Windows لرسمه. ومع ذلك، في بعض الأحيان، قد ترغب في تنفيذ بعض أنواع الخطوط الخاصة التي لا يوفرها Windows. يمكن تحقيق ذلك باستخدام وظيفة API تسمى LineDDA، والتي يمكن رؤية تعريفها في الشكل 13.
الدالة LineDDA(
nXStart, // إحداثي x لنقطة بداية الخط.
نقطة البداية الإحداثية X
nYStart، // إحداثي y لنقطة بداية الخط.
Y تنسيق نقطة البداية
nXEnd, // إحداثي x لنقطة نهاية السطر.
نقطة النهاية الإحداثية X
YEnd : عدد صحيح؛ // إحداثي y لنقطة نهاية الخط.
Y تنسيق نقطة النهاية
// عنوان وظيفة رد الاتصال المحددة بالتطبيق.
عنوان وظيفة رد الاتصال المعرفة من قبل التطبيق
lpLineFunc: TFNLineDDAProc;
lpData : LPARAM // عنوان البيانات المعرفة بالتطبيق.
عنوان البيانات المحددة بالتطبيق
): BOOL;
الشكل 13: تعريف Object Pascal لوظيفة Windows API، LineDDA.
المعلمات الأربع الأولى هي نقاط البداية والنهاية للخط. المعلمة الخامسة هي وظيفة رد الاتصال التي سيتم استدعاؤها في كل مرة يتم فيها رسم بكسل تم تمريره إلى وظيفة رد الاتصال. يمكنك تمرير أي عدد صحيح أو مؤشر إلى الوظيفة، لأنه LParam (في Win32، تتم ترجمته إلى Longint).
المعلمات الأربع الأولى هي نقاط البداية والنهاية للخط. المعلمة الخامسة هي وظيفة رد اتصال سيتم استدعاؤها في كل مرة يتم فيها رسم بكسل. يمكنك الكتابة عن عملية الرسم الخاصة بك هنا. يتم تحديد المعلمة الأخيرة من قبل المستخدم ويمكن تمريرها إلى وظيفة رد الاتصال. يمكنك تمرير أي عدد صحيح أو مؤشر إلى هذه الوظيفة لأنه كذلك
نوع Lparam (في WIN32، يتم تفسيره على أنه نوع Longint). يجب أن تستخدم وظيفة رد الاتصال هذه نموذجًا كما يلي:
الإجراء CallBackDDA(x, y: Integer;
UserParam: LParam);
حيث x وy هما إحداثيات النقطة المرسومة، وUserParam هو المعلمة التي تم تمريرها إلى الوظيفة. يجب تعريف هذه الوظيفة كـ stdcall. يرسم الروتين في الشكل 14 خطًا من الصور النقطية، ويوضح الشكل 15 النتيجة.
هنا X وY هي نقاط الإحداثيات التي يتم رسمها، وUserParam هو معلمة. يجب تعريف هذه الوظيفة فرعيًا على أنها stdcall. يرسم البرنامج في الشكل 14 خط BMP، ويعرض الشكل 15 النتائج.
يكتب
TForm1 = الفئة (TForm)
ImageList1: TImageList;
الإجراء FormPaint(Sender: TObject);
إجراء FormResize(Sender: TObject);
نهاية؛
فار
Form1: TForm1؛
الإجراء CallDDA(x, y: Integer; Form: TForm1);
تطبيق
{ $R *.DFM }
الإجراء CallDDA(x, y: Integer; Form: TForm1);
يبدأ
إذا كان x mod 13 = 0
Form.ImageList1.Draw(Form.Canvas, x, y, 0);
نهاية؛
الإجراء TForm1.FormPaint(Sender: TObject);
يبدأ
LineDDA(0, 0, ClientWidth, ClientHeight,
@CallDDA, Integer(Self));
نهاية؛
الإجراء TForm1.FormResize(Sender: TObject);
يبدأ
يبطل؛
نهاية؛
الشكل 14: رمز لرسم خط من الصور النقطية.
الشكل 15: نافذة بخط مخصص.
يعالج هذا الروتين حدث OnPaint الخاص بالنموذج، ويستدعي LineDDA، لذلك في كل مرة يجب رسم النموذج، فإنه يعيد رسم الخط. وهناك حدث آخر تتم معالجته وهو OnResize، الذي يبطل منطقة عميل النموذج، لذلك يجب إعادة رسم الخط عندما يقوم شخص ما بتغييره. حجم وظيفة رد الاتصال LineDDA، CallDDA، بسيطة للغاية. عند كل نقطة 13 يتم استدعاؤها، فإنها ترسم الصورة النقطية المخزنة في ImageList وظيفة رد الاتصال، حتى تتمكن من الوصول إلى بيانات المثيل.
يعالج هذا البرنامج حدث OnPaint الخاص بالنموذج، ويستدعي LineDDA، لذلك يقوم بإعادة رسم الخط في كل مرة يتم فيها رسم النموذج. حدث آخر هو OnResize، الذي يبطل منطقة العميل الخاصة بالنموذج بحيث يتم إعادة رسم الخطوط عندما يقوم شخص ما بتغيير حجمها. وظيفة رد الاتصال LineDDA وCallDDA بسيطة للغاية. كلما تم الاتصال به 13 مرة، فإنه سيتم رسم الصورة النقطية المخزنة في ImageList. ربما لاحظت أنه يتم تمرير SELF كمعلمة أخيرة لوظيفة رد الاتصال، حتى تتمكن من الوصول إلى بيانات البرنامج.
خاتمة
ختاماً
منذ أن تم الكشف عن رسم المالك في TMainMenu في Delphi 4، كان هناك العديد من الطرق لزيادة قوائمك باستخدام التقنيات التي ناقشناها هنا، يمكنك بسهولة تحسين قوائم تطبيق Delphi الخاص بك بنصوص مخصصة وصور نقطية وألوان.
الآن بعد أن ظهر رسم المالك في TmainMenu في دلفي 4، يمكن أن يكون له طرق عديدة لتوسيع وظائف القائمة الخاصة بك. باستخدام التقنيات التي ناقشناها أعلاه، يمكنك بسهولة تحسين وظيفة قائمة تطبيق DELPHI الخاص بك باستخدام النص المخصص والصور النقطية والألوان.