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

نظام تشغيل إفتراضي مصغر على#C

بدأه Tarek Jihad في 25 ديسمبر 2013 · 7 رد · 1,511 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

 

تحتوي لغة #C على الكثير من المواضيع والمفاهيم. لذلك لا بد من الإستفادة قدر الإمكان من هذه اللغة والتقنية الجميلة

فيما يلي تصور مبدئي لعمل نظام تشغيل إفتراضي (محاكي لنظام تشغيل وليس نظام تشغيل فعلي)، يعمل على أساس نظام التشغيل ويندوز، أي لا يتعامل هو نفسه مع الهاردوير.

وإنما هدفنا هو الإستفادة من تقنيات #C وخدمات ويندوز لتطبيق ما استطعنا من المفاهيم في بناء نظام تشغيل مصغر.

 

من الأمور التي يجب على النظام أدائها:

 

1. إستخدام Sql Server لإنشاء وتعديل وحفظ وحذف المجلدات والملفات. ( أي لن نتعامل مع نظام الملفات الخاص بجهازنا وإنما سنقوم بإنشاء نظام ملفات افتراضي مخزن على قاعدة البيانات)

2. إستخدام تقنيات +GDI لإنشاء وإدارة واجهات المستخدم.

3. تطبيق مفاهيم التحليل النصي Parsing لإنشاء Terminal or Command Prompt مصغرة.

4. محاولة إنشاء بعض التطبيقات الصغيرة المفيدة لهذا النظام، بالإستفادة من مفاهيم نظم التشغيل الأصلية مثل Threading, Networking.

5. أي فكرة جديدة مرحب بها هنا، للإستفادة العامة

 

الصورة التالية عبارة عن بداية مشروع صغير جداً قمت ببناءه واسميته CSOS أي (C Sharp Operating System)، بإمكانك تجربته من المرفقات.

بالطبع عن البدء بالعمل سيكون هناك تنظيم للكود وفصل للطبقات. إذا كان الموضوع يهمك، شاركنا بأفكارك.

 

akbw0za.png?1

 

... With best wishes

CSOS.rar

1

• • •


[ ربيّ احفظ سوريا الحبيبة]


oFOK7Kd.png

#2

كيف يمكن المشاركة في فريق عمل المشروع 

 
Full Name : Ahmed Mohamed Abd El Hammed Salem
Job : Soft ware Developer
Mobile Number : (+2) 01110024783
Skype : SkipCoder
Email : DevAhmedSalim@Gmail.Com

يوماً ما سأجعل وطني يفخر بى

#3

رائع جدا 

#4
SmartCode2013 كتب:

كيف يمكن المشاركة في فريق عمل المشروع 

أخي الكريم المشروع مفتوح للجميع وهدفه تعليمي.

بإمكانك المشاركة بالعمل من خلال النقاشات التي ستتم خلال توسعة العمل، وإذا كان لديك موضوع معين ترغب في تطبيقه بإمكاننا دمجه مع هذا النظام.

 

بالتوفيق

• • •


[ ربيّ احفظ سوريا الحبيبة]


oFOK7Kd.png

#5

لماذ توقف المشرووع :(  :(  :(

#6

بسم الله الرحمن الرحيم


سنتابع ما بدءناه سابقاً في نظام التشغيل الإفتراضي، اليوم سنقوم إن شاء الله بتغطية عدة مواضيع، لكي نستطيع متابعة العمل بشكل جماعي، فيكون لدى الجميع فكرة عامة عن ما تم عمله، وسنعطي الفرصة في نهاية الموضوع للمشاركة في تصميم قاعدة بيانات بسيطة لتخدم File System على نظامنا، علماً أني سأقوم بعرض تصميم جيد وبسيط لهذه القاعدة.


 


سنقوم بتغطية المواضيع التالية:


1. تصميم الكلاسات الخاصة بأيقونات نظام التشغيل Widget  (جهاز كمبيوتر، مستندات، ملفات نصية...)، بإستخدام الرسم على GDI+، الناتج سيكون مشابه للدرس الماضي لكن مختلف كلياً، الفائدة هنا تطبيق مفاهيم OOP مثلا Abstraction و Inheritance.


2. عمل كلاس   WidgetsHolder يقوم بتنظيم مجموعة من أيقونات نظام التشغيل، وإجراء بعض العمليات عليها.


3. عمل عنصر جديد User Control يعرض محتويات  WidgetsHolderعمله مشابه لعمل مستعرض الملفات Windows Explorer . بالتالي نستطيع استخدامه في أي واجهة أخرى. سنسميه WidgetsHolderUI.


4. سنشاهد طريقة إضافة عناصر جديدة لهذا المكون، مثلا عمل ملف جديد أو مجلد جديد، ستكون الإضافة حالياً على مستوى النظام، أي لن نقوم بحفظ هذه الملفات والمجلدات إلى قاعدة البيانات، حتى الدرس القادم بإذن الله. والهدف هو التعلم أولاً وآخراً.


5. عمل واجهة سطح المكتب بمساعدة العنصر السابق.


6. المشروع لحد هذه النقطة سيكون مرفق أيضاً


7. توصيف لقاعدة البيانات التي ستخدم نظام الملفات FileSystem. وإعطاء الفرصة في مناقشتها والتعديل عليها.

• • •


[ ربيّ احفظ سوريا الحبيبة]


oFOK7Kd.png

#7

1. تصميم الكلاسات الخاصة بأيقونات نظام التشغيل

 

في الشكل التالي نجد الهرمية الخاصة بتصميم الكلاسات للوصول إلى مرادنا

 

o7ZE0EQ.png

 

1. نقوم بعمل مشروع جديد من نوع Windows Forms Application بلغة سي شارب، ونقوم بتسميته CSOS كما قلنا.

2. نقوم بإضافة مجلد جديد للمشروع بإسم Widgets ليحوي على المكونات السابقة.

3. نقوم بإضافة كلاس جديد لهذا المجلد ونسميه Widget سيكون من نوع abstract كونه الأب للـ Widgets الأخرى ConputerWidget, FolderWidget, FileWidget.

4. نقوم بتعريف Enum جديد نفس الموجود بأعلى المخطط يحوي على أنواع Widgets وبالتالي سيكون لدينا حالياً شكل الكلاس كالتالي:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CSOS.Widgets
{
    public enum WidgetType { Computer, Documents, Folder, TextFile }
    public abstract class Widget
    {

    }
}

إذا حصل معنا لاحقاً تعديل معين أو إضافة معينه يمكننا إضافتها بكل سهولة.

 

5. الآن نحن بحاجة لتعريف مجموعة من المتغيرات التي تصف شكل الأيقونه وموقعها وحجم الخط ونوعة ومجموعة من الألوان، وهناك متغير مهم هو Graphics سنجعلة من نوع static ليكون موحداً لجميع العناصر. وهو عبارة عن السطح الذي سنرسم عليه لاحقاً، لكي تعرف كل أيقونه كيف ترسم نفسها وأين؟. ويجب أن يحوي هذا الكلاس

على ميثود Draw  من نوع virtual، نرسم خلالها الأيقونه بشكل معين، وإذا أردنا لاحقا تعديل الرسم لأيقونه معينه يمكننا عمل override لهذه الميثود والرسم من جديد.

 

سيكون لدينا الشكل النهائي للكلاس كالتالي:

namespace CSOS.Widgets
{
    public enum WidgetType { Computer, Documents, Folder, TextFile }
    public abstract class Widget
    {
        private int m_x = 0;
        private int m_y = 0;
        private int m_width = 100;
        private int m_height = 100;
        private string m_title = "Widget";
        private Color m_fontColor = Color.Black;
        private Color m_backColor = Color.Transparent;
        private Color m_selectedColor = Color.FromArgb(50, 0, 0, 255);
        private string m_fontName = "Tahoma";
        private float m_fontSize = 8;
        private FontStyle m_fontStyle = FontStyle.Regular;
        private Image m_icon = null;
        private int m_iconSize = 64;
        private bool m_isSelected = false;
        private WidgetType m_type = WidgetType.Folder;
        public static Graphics Graphics;

        public int Y
        {
            get { return m_y; }
            set { m_y = value; }
        }

        public int X
        {
            get { return m_x; }
            set { m_x = value; }
        }

        public int Width
        {
            get { return m_width; }
            set { m_width = value; }
        }

        public int Height
        {
            get { return m_height; }
            set { m_height = value; }
        }

        public Rectangle Bounds
        {
            get { return new Rectangle(X, Y, Width, Height); }
            set
            {
                X = value.X;
                Y = value.Y;
                Width = value.Width;
                Height = value.Height;
            }
        }

        public string Title
        {
            get { return m_title; }
            set { m_title = value; }
        }

        public Color FontColor
        {
            get { return m_fontColor; }
            set { m_fontColor = value; }
        }

        public Color BackColor
        {
            get { return m_backColor; }
            set { m_backColor = value; }
        }

        public Color SelectedColor
        {
            get { return m_selectedColor; }
            set { m_selectedColor = value; }
        }

        public string FontName
        {
            get { return m_fontName; }
            set { m_fontName = value; }
        }

        public float FontSize
        {
            get { return m_fontSize; }
            set { m_fontSize = value; }
        }

        public FontStyle FontStyle
        {
            get { return m_fontStyle; }
            set { m_fontStyle = value; }
        }

        public Font Font
        {
            get { return new Font(FontName, FontSize, FontStyle); }
        }

        public Image Icon
        {
            get { return m_icon; }
            set { m_icon = value; }
        }

        public int IconSize
        {
            get { return m_iconSize; }
            set { m_iconSize = value; }
        }

        public bool IsSelected
        {
            get { return m_isSelected; }
            set { m_isSelected = value; }
        }

        public WidgetType Type
        {
            get { return m_type; }
            set { m_type = value; }
        }

        public virtual void Draw()
        {
            if (Graphics == null)
                return;

            int xLocation = (Width - IconSize) / 2;
            SizeF textSize = Graphics.MeasureString(Title, Font);
            PointF textLocation = new PointF((Width - textSize.Width) / 2 + X, (Y + Height) - textSize.Height-5);
            
            if (Icon != null)
            {
                Graphics.DrawImage(Icon, new RectangleF(xLocation + X, Y + 10, IconSize, IconSize));
            }
            Graphics.DrawString(Title, Font, new SolidBrush(FontColor), textLocation);
            if (IsSelected)
            {
                Graphics.FillRectangle(new SolidBrush(SelectedColor), Bounds);
                Graphics.DrawRectangle(Pens.Silver, Bounds);
            }
        }      
    }
}

الأن أطلب منك قراءة ما سبق جيداً، وسنقوم بعدها بشرح عملية الرسم البسيطة السابقة.

• • •


[ ربيّ احفظ سوريا الحبيبة]


oFOK7Kd.png

#8

للأشخاص الذين يحبون تجربة ناتج المشروع حالياً، بإمكانكم تحميله من المرفقات، وهذه صورة توضيحة لما وصلنا إليه في هذه المرحلة. ستلاحظ فرق عن النسخة القديمة بسبب التعديلات والإضافات الجديدة التي سنتابع التحدث عنها للوصول للمثال الحالي كامل.

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

 

++ برنامج للتطبيق

نحن بحاجة الآن لبرنامج محرر نصوص بسيط لكي نستخدمه لاحقا في تعديل النصوص. فالنافذة في الصورة لا تقوم بأي خدمات إطلاقا، فإذا كان بإمكان أحدكم عمله لكي ندمجة مع مشروعنا يكون قد ساهم في هذا العمل.

 

KT2iofh.png

 

-------------------------------------------

قبل الإنتقال للمرحلة الثانية يجب أن نفهم خوارزمية رسم الأيقونة على سطح معين. لذلك سنشرح محتوى الميثود Draw، لكن يجب أن ننتبه إلى أن الرسم هنا معتمد على سطح الرسم، أي لو فرضنا سنرسم على سطح المكتب فإن الزاوية اليسرى العليا تعتبر مركز الرسم (0, 0). لذلك وضعنا الخاصيتين X, Y لتحديد موضوع الأيقونة بالنسبة لهذه الإحداثيات، والصورة التالية توضح توضع أيقونة جهاز الكمبيوتر على سطح المكتب.

 

UvaUc7i.png?1

 

1. قمنا بعملها من نوع virtual لنستطيع عمل override لها فيما بعد وتخصيص الرسم أكثر وهذا المفهوم مهم جدا في OOP ويعرف بإسم Polymorphism 

2. قمنا بالتحقق من Graphics لأنه ربما في مرحلة الرسم في وقت معين يكون سطح الرسم Graphics غير مهيئ، لذلك نتفادى عملية الرسم ونخرج من الميثود return

3. على اعتبار اختلاف حجم الأيقونة وإختلاف طول نص الإسم، لذلك نحن بحاجة لعمل مجموعة من القياسات لتحديد مكان رسم الصورة على الأيقونة وكذلك رسم الإسم Title، وكما شاهدنا في الكلاس Widget هناك خاصية تسمى IconSize وتساعدنا في تغيير حجم الأيقونة في أي وقت، لذلك قمنا بعملية حساب عرض الصورة وطرحها من العرض المخصص للأيقونة Width بهذه العملية سنحصل على المساحة المتبقية والتي تعبر عن المساحة الفارغة على جانبي الصورة، لذلك نقوم بقسمها إلى قمسين 2/، وبالتالي نحدد موضع الصورة أفقيا على الأيقونة. أما بالنسبة للموضع العمودي فلقد فرضناه مساوي لموضع الأيقونة  Y+120

4. قمنا بحساب طول وعرض النص (الإسم أو العنوان) وقمنا بعمل حسابات مشابه للخطوة 3 لتحديد موضع النص على الأيقونة، ثم نرسم النص عن طريق الميثود DrawString

5. الأن نحن بحاجة لعمل القليل من الرسم في حال تم اختيار أيقونة معينة، فكما نرى في الصورة السابقة قام المستخدم بالنقر بالفأرة على الأيقونة فتغير لون الخلفية. لذلك أضفنا الخاصية IsSelected لتمييز الأيقونة المحددة عن غيرها، وضمن ميثود الرسم تحققنا من حالة الأيقونة فيما إذا كانت محددة Selected وقمنا برسم مستطيل ملون.

------------------------------------------------------------------------

 

بعد الإنتهاء من عمل كلاس الأب Widget نحن بحاجة لتعريف مجموعة كلاسات الأبناء ضمن مجلد Widgets، في الوقت الحاضر سنقوم بتعريف ثلاث ابناء:

1. ComputerWidget   : خاصة بجهاز الكمبيوتر.

2. FolderWidget         : خاصة بالمجلدات.

3. FileWidget             : خاصة بالملفات النصية.

بالطبع سنقوم بإضافة مجموعة من الخائص لكل ابن فيما بعد، لكن سنكتفي الآن بتهية كل واحد.

بعد إضافة كلاس لكل ابن بنفس المسمى السابق سينتج لدينا ثلاث كلاست جديدة بالشكل التالي:

 

1. ComputerWidget Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSOS.Widgets
{
    public class ComputerWidget : Widget
    {
        public ComputerWidget()
        {
            Type = WidgetType.Computer;
            Icon = Properties.Resources.computer;
            Title = "Computer";
        }
    }
}

2. FolderWidget Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSOS.Widgets
{
    public class FolderWidget : Widget
    {
        static int serial = 1;
        public FolderWidget()
        {
            Type = WidgetType.Folder;
            Icon = Properties.Resources.documents;
            Title = string.Format("Folder({0})", serial++);
        }
        public FolderWidget(string name)
        {
            Type = WidgetType.Folder;
            Icon = Properties.Resources.documents;
            Title = name;
        } 
    }
}

3. FileWidget Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSOS.Widgets
{
    public class FileWidget : Widget
    {
        static int serial = 1;
        public FileWidget()
        {
            Type = WidgetType.TextFile;
            Icon = Properties.Resources.textfile;
            Title = string.Format("TextFile({0}).txt", serial++);
        }
    }
}

بعد الإنتهاء من عمل هذه الكلاسات، تأتي المرحلة التالية، وهي عمل كلاس جديد WidgetsHolder, WidgetsHolderUI ينظم عمل الابناء جميعا كما سنرى لاحقاً.

CSOS.rar

1

• • •


[ ربيّ احفظ سوريا الحبيبة]


oFOK7Kd.png

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