الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

التحكم في حجم الخلية دون التأثير على الخط

بدأه c_vita في 23 يناير 2012 · 7 رد · 1,247 مشاهدة · في لغة Delphi
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم جميعا

كيف يمكنني التحكم في ارتفاع السطر وعرض العمود في TDBgrid مع استقلالية التحكم في مواصفات الخط ؟؟

جزاكم الله خيرا

#2

السلام عليكم...

بالنسبة إلى تغيير عرض الأعمدة فإنه لا توجد مشكلة لأن المكون TDBGrid لديه الخاصية Columns التي تستطيع من خلالها الوصول إلى أي عمود لتحديد مواصفاته. مثلاً الكود التالي يعمل على جعل العمود رقم 2 بعرض 120 بكسل:

DBGrid1.Columns[2].Width := 120;

أما بالنسبة إلى ارتفاع الصفوف فيحتاج الأمر إلى بعض التحايل لأن المكون TDBGrid لا يعرض أية خصائص أو وظائف للتعامل مع الصفوف. نستطيع هنا أن نستعمل أسلوباً يسمى "ابتذال أو استخراج الوظائف و الخصائص المحمية" (Protected Hack)، و الفكرة تتلخص فيما يلي:

العديد من أصناف الكائنات (Classes) في دلفي تحتوي على وظائف و خصائص "محمية" (Protected Methods and Properties). و هي وظائف و خصائص لا يمكن استدعاؤها من جانب الكائنات (Objects) المنشأة من ذلك الصنف (Class)، و لكن عند إنشاء صنف مشتق من ذلك الصنف المحتوي على تلك الوظائف و الخصائص فإن الصنف المشتق يرث تلك الخصائص و الوظائف (كخصائص و وظائف محمية أيضاً). ذلك يعني أنه يمكن الوصول إلى الخصائص و الوظائف المحمية في صنف معين من أي وحدة برمجية (Unit) يوجد بها صنف مشتق من ذلك الصنف.

لتطبيق هذا المبدأ على المكون TDBGrid (في الوحدة DBGrids) فإننا نجده مشتق من الصنف TCustomDBGrid (في الوحدة DBGrids أيضاً) و هذا الصنف بدوره مشتق من الصنف TCustomGrid (في الوحدة Grids). فإذا نظرنا إلى تركيب الصنف TCustomGrid سنجد فيه خاصيتين متعلقتين بارتفاع الصفوف، هما الخاصية DefaultRowHeight و الخاصية RowHeights. و هما معرفتان على أنهما محميتان (ضمن الجزء Protected من تعريف الصنف)، و ذلك يعني بالضرورة أن المكون TDBGrid يحتوي على هاتين الخاصيتين كخاصيتين محميتين.

إذن لو قمنا بتعريف صنف مشتق من الصنف TDBGrid ضمن وحدة برمجية (Unit) تابعة لمشروعنا فإننا سنتمكن من الوصول إلى تلكما الخاصيتين المحميتين.

الكود سيكون كالتالي مثلاً:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, Grids, DBGrids, ADODB, StdCtrls;

type

  TMyDBGrid = class(TDBGrid);

  TForm1 = class(TForm)
    ADOTable1: TADOTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
//
// ...
//
  end;

لاجظ وجود السطر:

TMyDBGrid = class(TDBGrid);

الذي يعني أننا فمنا بتعريف صنف (Class) باسم TMyDBGrid مشتق من الصنف TDBGrid، و بالتالي يمكننا الوصول إلى كافة الخصائص و الوظائف المحمية للصنف TDBGrid من داخل الكود الخاص بنا من خلال الصنف المشتق TMyDBGrid. ذلك يعني أن نقوم بعملية تحويل نوعي (Type Casting) للكائن DBGrid1 لنتعامل معه كأنه من النوع TMyDBGrid. فمثلاً لضبط ارتفاعات جميع الصفوف في الـ DBGrid1 على 50 نستعمل الخاصية DefaultRowHeight كالتالي:

TMyDBGrid(DBGrid1).DefaultRowHeight := 50;

و لضبط ارتفاع الصف رقم 3 نستعمل الخاصية RowHeights كالتالي:

TMyDBGrid(DBGrid1).RowHeights[3] := 50;

* إذا أردت أن تقوم بعمل نفس الطريقة في وحدة برمجية (Unit) أخرى فلا تستعمل نفس الاسم المشتق TMyDBGrid و إلا فلن يعمل الكود. استعمل اسماً مختلفاً لكل وحدة.

أعتذر عن الإطالة و لكن أردت أن أوضح طريقة عمل الفكرة.

نرجو الاستفادة و السلام.

1

وَ قُلِ اعْمَلُوا فَسَيَرَى اللهُ عَمَلَكُمْ وَ رَسُولُهُ وَ الْمُؤْمِنُونَ

صدق الله العظيم

#3

السلام عليكم

اجابتك كانت اكثر مما كنت اتوقع .. وابشرك : هذا الاجابة تذكرني بمنهج النبي (ص) في تعليم اصحابه

في الحديث

عَنِ ابْنِ عَبَّاسٍ ، أَنَّ رَجُلا سَأَلَ رَسُولَ اللَّهِ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ عَنْ مَاءِ الْبَحْرِ ، فَقَالَ : يَا رَسُولَ اللَّهِ ، إِنَّا لَنَرْكَبُ الْبَحْرَ عَلَى أَرْمَاثٍ لَنَا ، وَتَحْضُرُنَا الصَّلاةُ وَلَيْسَ مَعَنَا مَاءٌ إِلا لِشِفَاهِنَا ، أَفَنَتَوَضَّأُ بِمَاءِ الْبَحْرِ ؟ ، فَقَالَ رَسُولُ اللَّهِ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ : " هُوَ الطُّهُورُ مَاؤُهُ ، وَالْحِلُّ مَيْتَتُهُ " ، قَالَ الرَّبِيعُ : الأَرْمَاثُ : الْخَشَبُ .

فالنبي (ص) لم يكتفي بقول نعم وإنما اعطي الاجابة الشافية.

سأجرب و اعود اليك بالنتائج

تحياتي .....

#4

السلام عليكم -

الاخ ناجي نفعك الله بما علّمك.. آآآآمين

ملاحظة : تأخري بسبب انشغالي, ارجوا التقبل.

جربت ما ذكرته بالاعلي وتم ما اريد لكن الجديد هو:

عند زيادة ارتفاع الخلية يبقى محتوى الخلية بالاعلى القيت نظرة على obiect inspetor لكن لم اجد ما يساعدني على ضبط محتويات الخلية افقيا ورأسيا

آمل ان يكون ذلك متاحا.

ملاحظة : اذا كان الحل يفهم من شرحك بالاعلى فما هي الخاصية التى يمكن التعامل معها؟؟

جزاك الله خيرا

وتقبل تحياتي....

#5

السلام عليكم...

ما يجعل المكون DBGrid في دلفي رائعاً (مقارنة بـ VB مثلاً) أنه يمكنك التحكم به بشكل كامل و بأية طريقة تريدها، و السر - لا تخبر أحداً :lol: - يكمن في إجراء الحدث OnDrawColumnCell (لا تخلط بينه و بين الحدث OnDrawDataCell الموجود فقط للتوافق مع نسخ دلفي القديمة).

* المسألة فقط هي - حسب كلامك أنت في إحدى مشاركاتك في المنتدى:

اقتباس
أن البرمجة تعتمد على خيال المبرمج والحالة التي لديه والادوات التي يستطيع استعمالها لكتابة الكود

من خلال إجراء الحدث OnDrawColumnCell يمكن التحكم في الـ DBGrid حتى على مستوى الخلايا المفردة. مثلاً تمييز درجات الطلبة الراسبين، تمييز الديون المتجاوزة لحد معين، تمييز أسماء أو بيانات ذات أهمية معينة ... إلخ. سواء بتمييز النص أو الخلفية، أو كيفما تشاء.

عند كتابة كود الحدث OnDrawColumnCell قد تحتاج في بعض الحالات إلى كتابة بعض الكود أكثر من الحالات الأخرى - حسب الحالة التي تعالجها - لكن ذلك لا يهم إذا كنت تريد تقديم برنامج يعمل بالكفاءة التي تريدها! كما أن البرمجة غالباً هي كتابة أكواد !!!!

المعذرة على الإطالة. الكود التالي يعمل على توسيط النص في كافة خلايا الـ DBGrid، لكن يمكنك تخصيصه ليشمل صفاً معيناً أو عموداً معيناً أو إضافة بعض الكماليات إليه:

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
    SizeDif, ATop, ALeft: Integer;
begin
    if gdSelected in State then begin
        // تمييز الخلية المحددة
        DBGrid1.Canvas.Brush.Color := clHighlight;
        DBGrid1.Canvas.Font.Color := clHighlightText;
        end
    else begin
        // بقية الخلايا
        DBGrid1.Canvas.Brush.Color := DBGrid1.Color;
        DBGrid1.Canvas.Font.Color := DBGrid1.Font.Color;
    end;

    // حساب الموقع أفقياً
    SizeDif := ((Rect.Right - Rect.Left) - DBGrid1.Canvas.TextWidth(Column.Field.AsString)) div 2;
    ALeft := Rect.Left + SizeDif;
    // حساب الموقع رأسياً
    SizeDif := ((Rect.Bottom - Rect.Top) - DBGrid1.Canvas.TextHeight(Column.Field.AsString)) div 2;
    ATop := Rect.Top + SizeDif;
    // طباعة محتوى الخلية
    DBGrid1.Canvas.TextRect(Rect, ALeft, ATop, Column.Field.AsString);
end;

* ملاحظة: قد يؤدي الكود إلى تغيير بعض التنسيقات التي تضبطها بالخصائص فتحتاج إلى تنسيق النص بالكود، لكن هذا نادر.

نرجو الاستفادة و السلام.

وَ قُلِ اعْمَلُوا فَسَيَرَى اللهُ عَمَلَكُمْ وَ رَسُولُهُ وَ الْمُؤْمِنُونَ

صدق الله العظيم

#6

السلام عليكم

اخي ناجي جزاك الله خيرا

سأجرب واعود اليك بالنتائج .....

#7

السلام عليكم

اخونا ناجي : عذراً لأني لم ارد مباشرة بسبب بعض الاولويات في كتابتي للتطبيق الذي اعمل عليه

الان:

- قرأت الكوت قبل نسخه لأفهم الافكار جيدا .

- ثم لصقته كما هو واجريت اللازم .

- بعد ذلك توقفت عند الاشياء الجديد واستعملت المفتاح السحري F1 لأعرف تفاصيل اكثر- على سبيل المثال Trect لم اتعامل معه من قبل- فأنا لا احب النسخ واللصق دون العلم بفكرة العمل.

- ثم قرأت الكود مرة جديدة في ضوء ما عرفته من Help .

- اخيراً بدأت التجارب ..

والنتائج كثيرة ما يهمني منها الان هي معرفة الحدث المناسب لجعل ارتفاع الصفوف يساوي ...

في ال onforcreate لا يعمل !! فما الافضل.

تحياتي.....

#8

وعليكم السلام ورحمة الله وبركاته

المشكلة ليست في الحدث بذاته

إنما ينبغي تعديل ذلك بعد فتح الاتصال بالجدول:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Table1.Open;
  TMyDBGrid(DBGrid1).DefaultRowHeight := 30;
end;

بالتوفيق.

1

مواضيع مشابهة