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

كيفية مناداة Unmanaged Code في C# الدرس الاول

بدأه fkugd2003 في 14 نوفمبر 2008 · 5 رد · 905 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

خلال هذين اليومين الاخيرين اصبت بحمى من النوع الرفيع الذي يجعل فرائصك ترتعد من البرد. لذلك قلت اكتب درس في سي شارب لاتسلى و انسى التعب.... لذلك فاذا رايت اخطاء في النص لا تلمني لانني والله بريئ :blush:

المهم هدا الدرس من اجل الأخوة الذين يتسائلون هل من الممكن ان ننادي دوال ويندوز عن طريق منصة Microsoft.net

و الجواب نعم... و اذا لم تصدقني :angry: سوف انال منك اينما كنت وهو مهدى الى كل شخص يحب البرمجة بالكود

كما يعرف اغلبنا ان منصة .net تقوم بتنفيذ كود برمجي غير حقيقي كالذي تملكه لغة جافا لذلك فان مناداة اجرائات وندوز غير معرفة و هذا بسبب محمولية البرنامج لانه اذا خرج عن CLR فانه يصبح مرتبطا بنوع نظام التشغيل وهذا ما حعل مكروسوفت تتخلى عن دوال وندوز, لكن لكل مشكلة حلا

العمل باتخدام تقنية PInvoke:

تقنية PInvoke تسمح لك بمناداة دوال وندوز الموجودة في ملفات الربط الديناميكي Win32 DLL, هذه الدوال مفيدة جدا عندما تريد ان تقوم بعمليات منخفضة المستوى كالعمليات على القرص الصلب و كذلك تسمح للمبرمجين الذين تعوذو على استعمال مكونات COM خاصة بهم ان لا يضيعو وقتهم في محاولة اعادة برمجتها بلغة من لغات .net

اكثر الدوال المعروفة و المشروحة من خلال كتب او مقالات توجد في الملفات:

Kernel32.dll

GDI32.dll

User32.dll

Method Modifiers هذه لم استطع وضع ترجمة جيدة لها ولكن لندعها معرفات الدوال 

كل الدوال في C# يجب ان تحتوي على كلمة تعريف تسمح لنا و للمترجم بمعرفة مستوى منظورية Visibility الدالة و هذه التعاريف هي (او على الاقل التي اعرفها):

static: دالة تابتة اي نستطيع ان نناديها مباشرة من الكلاس بدون ان نضطر الى خلق عنصر جديد بالمعامل new

ClassName.StaticMethod() ;

افضل مثال عنها هو الكلاس MessageBox الموجود في System.Windows.Forms.MessageBox

MessageBox.Show("البرمجة مسلية","رسالة", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

virtual: يستخدم هذا المعرف ليدل على انك تستطيع تغيير كود الدالة في كلاس موروثة منها لكنه لا يعمل الا مع المعرف public

abstract: يدل على ان الدالة معرفة لكنها لا تحتوي على كود وهو نفس المفهوم المستخدم مع جافا. اذا اردت ان تستعمل كلاس يحوي على دالة من هذا النوع يجب عليك ان تشتقها ثم تعيد تعريف الدالة.

extern: وهو النوع الذي يهمنا و يسمح لك بتعريف دالة موجودة في ملف ربط ديناميكي dll وهو يعمل في اغلب الاحيان مع التعريف DllImport.

الآن لنعد لرسالة الترحيب التي طبعناها و نحاول ان نستعمل الدالة الاصلية في ملف user32.dll و لنحاول ان نتعرف عليها من خلال دليل WinAPI


HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
int MessageBox(

لكن كيف ساقوم باستدعاء هذه الدالة مع كل هذه الرموز الغريبة والمرعبة لبرمجة Win32 :P

HWND: يكافؤها في لغة سي int لذلك يمكن ان نضع فيها 0. ارجع الى دروس iczelion اذا لم ترد ان تصدقني و هي القيمة التي تعرف بها كل نافذة في النظام..... يا اخي ارجع لدروس iczelion -_-

LPCTSTR: ضع مكانه string الذي تريده ان يظهر

UINT: نوع unsigned int اظن ان هذه سهلة :P و تكافئ جميع التعريفات عن الازرار و الايقونات

اذن عرفنا الاساس. الى الهجوم يا رجااااااال......... عفوا و يا نساء :wub:

لتعلم .net انك سنقوم بمناداة اجراء وندوز اضف له التالي

using System.Runtime.InteropServices;

و الان لنعرف MessageBox:

[DllImport("user32.dll",EntryPoint="MessageBox")]
public static extern int MessageBox_Win32(int hWnd, String text, String caption, uint type);

كما لاحظنا فاننا قلنا ل.net حمل ملف user32.dll و اجعل نقطة الدخول EntryPoint عند الدالة MessageBox وبعد ذلك قمنا بتعريف دالة MessageBox_Win32 و اعطيناها نفس التعريف الذي رأيناه.

ملاحظة مهمة: يمكن لك ان تتجاهل تعريف نقطة الدخول للمكتبة لكنك لن تستطيع ان تعطي اسماء للدوال و انما ستضطر لاستعمالها بالاسماء التي عرفت بها في user32.dll

[DllImport("user32.dll")]

public static extern int MessageBox(int hWnd, String text, String caption, uint type

);

لكي نقوم باستدعاء الاجراء تقوم بالتالي:

لنفرض انك وضعت نافذة Form ثم اضفت اليها زرا سميته Button1 و اردت بمجرد الضغط على الزر ان تظهر رسالة الترحيب:

void Button1Click(object sender, EventArgs e)
{
	MessageBox_Win32(0,"انااحب البرمجة","هيا نبرمج",0);		
}

فسوف تظهر لك الرسالة و التي ستؤكد لك انك رائع :P ........احيانا عندما انزعج و احس بالملل اضع الرسالة و اكتب فيها

MessageBox_Win32(0,"انااحترمك و احبك يا انا لأنك طيب (ناس ملاح بالجزائري)","هيا نبرمج",0);

-_-

و هكذا ارتاح و احس بالحنان الامومي من برنامجي :wub:

بعد ان تنفذ البرنامج حاول ان تتأكد من خاصية show modal للرسالة و سوف تلاحظ انك يمكن ان تضغط على الزر مرة اخرى لتظهر رسالة اخرى..... :wink: صح لكن ما العمل؟ ......... :S اقرأ مقالات iczelion :lol:

الفكرة بسيطة وهي ان تستعيد الhandle الخاص بتطبيقك و ترسله الى الدالة و هذه محاولتي:

int MyHandle = (int)this.Handle;
MessageBox_Win32(MyHandle,"انااحب البرمجة","هيا نبرمج",0);

وهكذا لن تستطيع ان تعيد الضغط على الزر حتى تضغط على OK

وللحديث بقية إن شاء الله

العمل كثير و الوقت قليل أعاننا الله

seo zen SEO Enlightment amazon danbo

#3

أحب أضيف لحضرتك شيئ:

HWND = يكافئها في الـ .NET Framework الكلاس System.IntPtr.

آه يمكننا استخدام int لكن إذا أردنا تحديد Owner للـ MessageBox ؟ الأفضل استخدام Form.Handle أفضل من Fom.Handle.ToInt32().

والأفضل والأسرع من هذا كله استخدام int* ولكن يفضل عدم استخدامه لإنه بيدخلنا في Unsafe Code وده هيخلي عملية Debugging أصعب وأي خطأ بيعمل memory corrupt.

#4

يمكن لك ان رجع الى تعريف HWND في تطبيقات Win32 والذي هو int.. وليس *int

اماالمثال كان فقط للتجربة لان استعمال win32 يجب ان يكون له سبب مثل القيام بعمليات منخفضة...

المهم الجزء الثاني قادم و ستتبين الفكرة

العمل كثير و الوقت قليل أعاننا الله

seo zen SEO Enlightment amazon danbo

#5

حضرتك أصلا ما عرفتش ايه هو int*!!!!!!!!

int* هو نفسه int لكن هو عبارة عن pointer لـقيمة هي عبارة عن 4 بايت في الميموري وبتكون رقم integer.

يعني مثلا byte* نفسه byte لكن عبارة عن pointer لقيمة هي عبارة عن 1 بايت في الميموري.

يعني مجرد بس إني أدخل في Unsafe Code يعني هبدأ أستخدام بعض الحروف الغريبة زي (* , &) وبعض الـ Keywords مثل (fixed وغيرها) وده بيوفرلي direct access للـ memory وده بيكون أسرع بس أصعب وأي خطأ بيعمل مشاكل زي ما قلتلك.

HWND في API Documentation بيتقول: a pointer to an int يعني int* في الدوت نت, يعني لو Managed Type هتكون IntPtr أو int بس IntPtr أفضل.

على العموم مش غلط int برضه.

وبرضه مشكور على الدرس الرائع وكويس إننا برضه نتكلم في المواضيع دي وخصوصا إن API في الدوت نت نادرا اللي بيتكلم عنها واحنا مستنيين باقي الدروس ونتمنى كل التوفيق.

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