|
المثال التطبيقي
سنشرح برمجة برنامج بسيط باستخدام لغة
فيجوال سي يوفر للمستخدم إمكانية البحث عن اسم كتاب في قاعدة
بيانات، وسنستخدم تقنية ADO
في التعامل مع قاعدة البيانات.
الخطوة الأولى هي تكوين الهيكل الرئيسي
للبرنامج، ولعمل ذلك استخدم المعالج MFC
AppWizard (exe)، الذي يمكنك الوصول إليه
بالنقر على القائمة File،
ثم اختيار البند New...، واختيار البند
MFC AppWizard (exe) من الشريط Projects،
ثم كتابة اسم المشروع،
ولنطلق على مشروعنا هذا اسم Library، ثم
ننقر على الزر OK.
اختر بعد ذلك
البندDialog
based ، ثم انقر على الزر Finish.
فتظهر نافذة تحتوي على معلومات عن
المشروع الذي أنشأناه. انقر على الزر OK،
فيفتح الإطار IDD_LIBRARY_DIALOG جاهزاً
للتحرير. امسح الزر Cancel،
والنص TODO: Place dialog controls here،
وغيّر نص الزر OK إلى Close،
وذلك بالنقر عليه بالزر الأيمن للماوس، ثم اختيار البند Properties...،
وتغيير النص في مربع التحرير Caption إلى
Close. أضف عناصرتحكم إلى هذا الإطار، ثم رتبها بطريقة
مشابهة للشكل 1.
www.tartoos.com
تلاحظ أن الحقل
Extended Styles يحتوي أحياناً على القيمة
"Static edge"، ويعني هذا أن عليك النقر
على الشريط Extended Styles
في الإطار Text Properties،
وتعيين المربع Static edge. وربما يتبادر السؤال التالي إلى أذهان بعض
القراء: لماذا أعطينا بعض عناصر التحكمات النصية Static Texts
أرقام تعريف
ID خاصة بها، مثل ID_PUBLISHER_STATIC،
بينما اكتفينا في مرات آخرى برقم التعريف
IDC_STATIC؟

تستخدم عناصر التحكم
النصية الساكنة بشكل رئيس لكتابة النصوص في النوافذ أثناء
مرحلة التصميم، كما استخدمناها في كتابة النص
"Publisher:" مثلاً، وفي هذه الحالة، لسنا بحاجة
لتغيير هذا النص برمجياً، ما يعني
أننا لسنا بحاجة إلى إعطاء عنصر التحكم هذا رقماً تعريفياً خاصاً. أما في حالة عنصر التحكم ID_PUBLISHER_STATIC
وغيره من العناصر،
فإننا نريد أن نضع فيه اسم دار النشر التي نشرت الكتاب الذي
يبحث عنه المستخدم، وقيمة هذا التحكم غير معروفة أثناء
فترة التصميم، وعلينا أن نضعها فيه برمجياً ، لذا فنحن بحاجة إلى تغيير قيمة
عنصر التحكم برمجياً، أي أننا بحاجة إلى ربط متغيّر
بهذا التحكم، كي نستطيع من خلال هذا المتغيّر، تغيير قيمة عنصر
التحكم.
www.tartoos.com
وخلاصة القول:
إذا كنت لا تعتزم ربط متغير بتحكم نصي لتغيير قيمته مثلاً، فأبقِ قيمة رقمه
التعريفي:
IDC_STATIC،
وإلا عليك تغيير قيمة الرقم التعريفي.
علينا الآن أن
نُضيف الوظائف البرمجية إلى هذا الإطار، والخطوة الأولى هي ربط بعض المتغيرات
بعناصر التحكم الموجودة في هذا الإطار، ولعمل ذلك اختر البند
ClassWizard...
من
القائمة
View.
انقر بعد ذلك على الشريط
Member Variables،
ثم اختر البند
CLibraryDlg
من القائمة المنسدلة
Class name:.
يمكنك الآن النقر على كل من عناصر
التحكم التي تجد رقمها التعريفي في
الجدول 2،
والنقر على الزر
Add Variable...،
وتعبئة حقول هذا الإطار.www.tartoos.com
علينا
الآن تنفيذ بعدة خطوات، كي نتمكن من استخدام تعليمات
ADO
في برنامجنا من أجل
التخاطب مع قاعدة البيانات. والحقيقة أنه توجد عدة طرق لعمل ذلك، وأسهلها هو
استخدام تعليمة
#import،
وهي الطريقة التي تنصح بها شركة مايكروسوفت. ولعمل ذلك،
افتح الملف
"StdAfx.h"،
وأضف إلى نهايته، وقبل تعليمة
#endif
الأخيرة، السطرين:www.tartoos.com
#include #import "C:\program files\common files\system\ado\msado15.dll" no_namespace
rename( "EOF", "adoEOF" )
وعندما تنفذ يعد ذلك عملية ربط البرنامج، فإنَّ يكون آلياً عدة
ملفات رأسية
(Header Files)
يمكن أن نستخدمها لاحقاً.
تعتمد تقنية
ADO
على تقنية
COM،
وعليك لهذا أن تخبر البرنامج بالحاجة إلى مكتبات
COM،
ولعمل ذلك افتح الملف
Library.cpp،
ثم ابحث عن الوظيفة
InitInstance،
وأضف السطر التالي إلى بداية تلك
الوظيفة: AfxOleInit ( );
علينا الآن أن نضيف متغيّرين إلى الصنف
CLibraryDlg،
ولعمل ذلك، افتح الملف
LibraryDlg.h،
ثم أضف السطرين التاليين تحت
التعليمة
"protected:":
BOOL m_bIsConnectionOpen; _ConnectionPtr m_pConnection;

بعد
ذلك افتح الملف
LibraryDlg.cpp،
ثم اذهب إلى
المنشئ
"Constructor"
الخاص بهذا الصنف، أي
CLibraryDlg::CLibraryDlg(CWnd* pParent /*=NULL*/)
وأضف إليه السطر التالي: m_bIsConnectionOpen = FALSE;
وسنستخدم هذا المتغير للإشارة إلى إذا كان الاتصال مع قاعدة البيانات
مفتوحاً أو مغلقاً.
أضف بعد ذلك السطور التالية إلى الوظيفة
OnInitDialog،
تحت
السطر
//TODO…:-
HRESULT hResult;
hResult = m_pConnection.CreateInstance (__uuidof(Connection));
if (SUCCEEDED(hResult)) { hResult = m_pConnection->Open
(bstr_t(L"Provider=Microsoft.Jet.OLEDB.3.51;Data
Source=c:\\Library\\Library97.mdb;"), _bstr_t(L""), _bstr_t(L""), adModeUnknown);
if (SUCCEEDED(hResult)) m_bIsConnectionOpen = TRUE; }
عرفنا
في البداية متغير من نوع
HRESULT، وذلك كي نخزّن فيه
النتيجة التي ترجعها بعض الوظائف. واستخدمنا المتغيّر
"m_pConnection"، الذي
عرّفناه سابقاً، لتكوين كائن للاتصال بقاعدة بيانات. ثم تأكدنا
من أنَّ النتيجة التي أرجعتها الوظيفة
"CreateInstance" إيجابية، فإذا كانت كذلك فإننا
نفتح قاعدة البيانات التي صممتها في
الجزء الأول من هذه المقالة، باستخدام الأمر Open.
وتذكر
أن تغيير المسار المذكور في القيمة:
Data
Source=c:\\Library\\Library97.mdb
إلى المسار الذي توجد فيه قاعدة البيانات على
قرصك الصلب.
نفحص بعد ذلك القيمة التي أرجعتها التعليمة
Open، فإذا كانت
إيجابية، فإن ذلك يعني أننا تمكّنا من فتح الاتصال مع قاعدة
البيانات، ونقوم عندها بوضع القيمة TRUE
في المتغيّر m_bIsConnectionOpen.
علينا أن نضيف وظيفةً تُنفذ
عندما ينقر المستخدم على الزر Find it!،
لتتم عملية البحث عن اسم الكتاب الذي أدخله
المستخدم. ولعمل ذلك شغّل المعالج
ClassWizard... من القائمة View،
ثم انقر على الشريط
Message Maps، وتأكد من أن الصنف المحدد ضمن
القائمة Class name: هو
CLibraryDlg. انقر على البند
IDC_FIND_BUTTON ضمن القائمة Objects IDs:،
ثم انقر على البند
BN_CLICKED ضمن القائمة Messages،
وانقر على الزر Add Function...، فتظهر
نافذة تقترح عليك الاسم OnFindButton
للوظيفة الجديدة. اقبل هذا الاسم، وانقر على
الزر OK. انقر على
الزر Edit Code ليتم فتح هذه الوظيفة
للتحرير، وأضف الأسطر التالية إلى
هذه الوظيفة:
if
(!m_bIsConnectionOpen) return;
UpdateData ( );
_RecordsetPtr pRecordSet;
CString str; str.Format ("SELECT * FROM Books WHERE Book = '%s'", m_strEditBook); _bstr_t bstrQuery (str); _variant_t vRecsAffected (0L);
try { pRecordSet = m_pConnection->Execute (bstrQuery, &vRecsAffected,
adOptionUnspecified);
if (!pRecordSet->GetadoEOF()) { _variant_t vBook, vISBN, vAuthor, vPublisher, vPages;
vBook = pRecordSet->GetCollect (L"Book"); vISBN = pRecordSet->GetCollect (L"ISBN"); vAuthor = pRecordSet->GetCollect (L"Author"); vPublisher = pRecordSet->GetCollect (L"Publisher"); vPages = pRecordSet->GetCollect (L"Pages");
m_strBook = (BSTR)(_bstr_t)vBook; m_strISBN = (BSTR)(_bstr_t)vISBN; m_strAuthor = (BSTR)(_bstr_t)vAuthor; m_strPublisher = (BSTR)(_bstr_t)vPublisher; m_strPages = (BSTR)(_bstr_t)vPages; } else AfxMessageBox ("Can't find this book!");
pRecordSet->Close ( ); }
catch( _com_error &e ) {
_bstr_t bstrSource(e.Source()); _bstr_t bstrDescription(e.Description());
CString strError; strError.Format ("Source = %s\nDescription = %s\n", bstrSource,
bstrDescription); AfxMessageBox (strError); }
UpdateData (FALSE);
تأكدنا في البداية من أنَّ الاتصال مع قاعدة البيانات مفتوح،
ثم نقلنا محتويات عناصر التحكم إلى المتغيرات المرتبطة بها عن
طريق الأمر
UpdateData (FALSE)، ثم عرّفنا متغيّر من نوع
_RecordsetPtr، لتخزين الحقول التي
سنطلبها من قاعدة البيانات. عرّفنا متغيّر نصي، ووضعنا فيه سطر
برمجي مكتوب بلغة SQL، يطلب تحديد
جميع الحقول في الجدول Books، التي فيها
قيمة الحقل Book مطابقة
لاسم الكتاب الذي أدخله المستخدم في مستطيل التحرير، والذي
خزّناه في المتغيّر m_strEditBook. عرّفنا بعد ذلك متغيّر من نوع _bstr_t،
وهو نوع يسّهل علينا التعامل مع
النوع BSTR، ووضعنا في هذا
المتغيّر قيمة المتغيّر str. ثم عرّفنا
متغيّر من نوع _variant_t، سنستخدمه فيما
بعد. حصرنا التعليمات الخاصة بطلب الحقول الخاصة باسم
الكتاب الذي أدخله المستخدم بين قوسي تعليمة try،
وهي تعليمة خاصة بالاستثناءات، فإذا
حصل أي خطأ أثناء عملية طلب الحقول من قاعدة البيانات، فإنها ترسل استثناء إلى
تعليمة catch التي
تقوم بمعالجته.www.tartoos.com
تنفذ
التعليمة الأولى ضمن قوسي تعليمة
try،
الأمر
Execute
عن طريق المتغيّر
m_pConnection،
والنتيجة الراجعة ستكون إما الحقول
التي تحتوي على المعلومات الخاصة باسم الكتاب الذي أدخله المستخدم في حال وجود
اسمه
في قاعدة البيانات، أو لا شيء.
www.tartoos.com
فحصنا بعد ذلك وجود أي حقول راجعة، فإذا وجدت،
يعرّف البرنامج عدة متغيّرات من نوع
_variant_t
لنخزّن فيها قيم الحقول الراجعة،
وذلك عن طريق استخدام الأمر
GetCollect.
بعد ذلك، وضعنا قيم هذه المتغيّرات في
المتغيرات المرتبطة بعناصر التحكم. ثم أغلقنا الاتصال مع المتغيّر
pRecordSet.
يتم تنفيذ التعليمات الخاصة بالتعليمة
catch،
في حالة وجود خطأ،
فقط، وهي تعرض رسالة خطأ تخبرك عن سببه. وأنبه إلى إنَّ استخدام تعليمتي
catch
و
try
ضروري جداً، فإذا حصل خطأ، ولم تكن هاتان التعليمتان مستخدمتان، فإنَّ البرنامج
سينهار بدون أن تعرف سبب ذلك.www.tartoos.com
شغّل المعالج
ClassWizard...،
وأضف وظيفة إلى
البند
IDOK،
ثم انقر على الزر
Edit Code،
ففتح الوظيفة
OnOK
جاهزةً للتحرير. أضف
الأسطر التالية تحت عبارة
//TODO…:-
if
(m_bIsConnectionOpen) { m_pConnection->Close ( ); m_bIsConnectionOpen = FALSE; }

والغرض من إضافة هذه السطور،
هو إغلاق الاتصال مع قاعدة البيانات، إذا كان مفتوحاً، عند
إغلاق البرنامج. يظهر الشكل 2 النتائج التي حصلت عليها
بعد أن أدخلت الاسم
"Wallenstein".
ونكون بذلك قد أنهينا
الجزء الثاني والأخير من هذه المقالة التعليمية، وآمل بأني
قدمت فائدة مهمة لك.
|