19-09-20, 05:28 PM
(آخر تعديل لهذه المشاركة : 19-09-20, 05:33 PM {2} بواسطة Anas Mahmoud.)
بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته
كان الاخ عبد الهادي قد طرح تساؤل حول البحث عن الكلمات داخل نص عربي يحتوي على حركات فتحة وضمة وهكذا ، وكان سؤالا هامة جدا وجيدا للغاية
وكنت قد توصلت للحل باستخدام Regex ووعدت بان اقوم بشرح الموضوع بشكل اكبر
نبدأ على بركة الله
تقديم للمشكلة :
تشكيل الحروف يمثل مشكلة عند البحث في الكلمات ، لان التشكيل نفسه يعتبر حرفا ،
مثلا في الآية :
الْحَمْدُ لِلَّهِ الَّذِي أَنْزَلَ عَلَىٰ عَبْدِهِ الْكِتَابَ وَلَمْ يَجْعَلْ لَهُ عِوَجًا ۜ
اذا اردت البحث عن الكلمة "الحمد" فان الطريقة التقليدية IndexOf() مثلا فانها لن تنجح ،
الكلمة التي تريد البحث عنها : الحمد : ا - ل - ح - م - د
الكلمة الموجودة في الاية : ا - ل - ْ - ح - َ - م - ْ - د - ُ
ما يقوم به IndexOf هو مقارنة حرف حرف من الكلمتين لايجاد تطابق ، وبالتالي لن ينجح الامر عند وجود تشكيل
نحتاج طريقة ما للبحث ، بحيث نخبرها اننا نقبل اي من حروف التشكيل بعد كل حرف من الكلمة المطلوبة ، هنا يأتي دور Regex
تقديم Regex :
التعابير النمطية او القياسية او Regular Expression هي طريقة للبحث داخل نصوص بشكل رئيسي ، باستخدام تعابير تأخذ شكل معين لتحديد طريقة البحث المطلوب ، وهي طريقة جميلة جدا وعملية جدا وسريعة جدا فيما يتعلق بالوقت
لست بصدد شرح Regex هنا ، يمكنك ان تجد معلومات اكثر عنها من هنا :
http://vb4arb.com/vb/showthread.php?tid=467
https://docs.microsoft.com/en-us/dotnet/...-reference
https://docs.microsoft.com/en-us/dotnet/...etcore-3.1
ولكن سأشرح ما سنحتاجه فقط .
استخدم الموقع التالي للتجربة : https://regex101.com/r/euj8kG/1
الفئة System.Text.RegularExpressions.Regex تحتوي على دالة Matches التي تعيد MatchCollection يمثل المطابقات في النص المطلوب البحث فيه ، تقبل مدخلان :
الاول : النص المطلوب البحث بداخله
الثاني : تعبير Regex المستخدم في البحث ، ونحتاج منه الآتي :
الكلمات الحرفية : في تعبير Regex اذا اردت البحث عن حروف ما بعينها بنفس الترتيب ، فعليك وضعها كما هيا في التعبير :
التعبير التالي يبحث عن كلمة vb4arab
الاختيار بين مجموعة حروف : اذا اردت اختيارا من بين اكثر من حرف ، يعني اما هذا او هذا او هذا تضعه بين اقواس مربعة [] في المكان الذي تريده :
التعبير التالي يبحث عن الكلمات vb4arab و vb3arab و vb2arab :
ويمكن استخدام - للدلالة على المدى من كذا الى كذا :
الدلالة على التكرار : اذا اردت ان يكون الحرف اختياري ويمكن تكراره اكثر من مرة استخدم * بعد الحرف المطلوب :
التعبير التالي يبحث عن vb4arb و vb4araaaaab و vb4arab و ....
ويمكن استخدامها مع اختيار من الحروف
التعبير التالي يبحث عن vb4arab و vb4323243343323223arab و vbarab و .... ايضا :
مجموعات الالتقاط : فرضا انت تبحث عن نص بشرط ما ، ولكنك لاتريد فعلا ان ترجع بالنص باكمله بل تريد جزء منه فقط كان تبحث عن كلمتين مكررتين بعد بعضهما مباشرة وتريد الكلمة فقط ، هذه فائدة مجموعات الالتقاط Capture group
التعبير التالي نفس التعبير السابق ولكنننا نضع الارقام في مجموعة نسميها x لكي نستعيدها مستقبلا :
استخدام الحروف بكود unicode : اذا حاولت وضع التشكيل في الكود فانه على الارجح لن يكتب ، بدلا من ذلك نستخدم التعبير بكود الحرف unicode
قائمة بيونيكود الحروف العربية : https://en.wikipedia.org/wiki/Arabic_script_in_Unicode
التعبير التالي يبحث عن حرف ال v والذي له الكود U+0056 :
الخطة :
الان يجب ان نحدد الاهداف :
1. نريد البحث عن الكلمات التي تحتوي على النص المدخل من المستخدم مع الاخذ بالاعتبار التشكيل
2. نريد ملي ال ListBox بنتائج البحث
3. نريد تلوين النص المدخل فقط من المستخدم ( ليس الكلمة كلها ) في كل المواقع الموجودة في النص الاصلي
4. عند اختيار المستخدم عنصر من ال ListBox يقوم البرنامج بالقفز الى موقعه في النص الاصلي
التصميم :
الكود :
الدوال والاجرائات :
سنعرف بعض الدوال لتسهيل العملية ،
الدالة SearchArabic : عصب الكود الاساسي ، سنقوم فيها باجراء عملية البحث واعادة IEnumerable(Of Match) تمثل نتائج البحث لاستخدامها لاحقا ،
ببساطة ، تأخذ النص المطلوب البحث عنه ، ونص البحث :
طيب الان ماذا نريد ان نفعل ؟
نريد ان نكوّن نص التعبير ،
ببساطة نأخذ كل حرف ونضيف بعده القيمة [\u064B-\u0652]* التي تمثل اي من حروف التشكيل ، اختياري وقابل للتكرار
الان نحن نبحث عن الحروف المدخلة من المستخدم فقط وسط التشكيل وهذا شيء جميل
لكن كيف نستخرج الكلمة كاملة ؟
الامر بغاية البساطة ، نخبره بان يحضر ايضا اي عدد من الحروف العربية قبل هذه الحروف التي نبحث عنها وكذلك اي عدد من الحروف العربية بعد هذه الحروف التي نبحث عنها
للتوضيح : (اي عدد من الحروف العربية)(حروف البحث)(اي عدد من الحروف العربية)
مدى الحروف العربية هو من U+0600 الى U+06FF
الان نحن جاهزون للبحث عن الكلمة باكملها ،نريد ان نضع الحروف المدخلة من المستخدم في مجموعة ونضع لها اسم input حتى نتمكن من الحصول عليها لاحقا :
الان المتغير expression اصبح يحمل نص التعبير واصبح جاهزا لعملية البحث :
نجري عملية البحث من الدالة Regex.Matches ونقوم بتحويل النتائج الى IEnumerable(Of Match) عن طريق Cast(Of Match)
يصبح كود الدالة كاملا :
للتجربة على كلمة "من" : https://regex101.com/r/QZKLfk/1
الإجراء ColorResults : نقوم فيه بتلوين نتائج البحث من مدخل المستخدم فقط وليس الكلمة كاملة ، لفعل ذلك نمر على نتائج البحث كلها ونختار المجموعة التي سميناها input ونلون منها
مدخلات الاجراء: RichTextBox الذي به النص ، IEnumerable(Of Match) نتائج البحث ، ProgressBar اختياري لعرض نتائج البحث
نستفيد من الخصائص داخل كائن ال Group ايضا مثل Index الذي يمثل بداية المجموعة داخل النص الاصلي و Length طول المجموعة
بكل بساطة نمر على نتائج البحث ،
لكل نتيجة نستخرج منها المجموعة "input" ،
نقوم بتحديد المجموعة من ال RichTextBox وتلوينها بالاصفر
نقوم بزيادة ال ProgressBar
الإجراء FillListBox : نقوم بملئ الليست بوكس به عن طريق ToList السحرية !
المدخلات : ListBox المطلوب ملئه ، و IEnumerable(Of Match) نتائج البحث :
الإجراء PopulateResults : نقوم بوضع عدد نتائج البحث في الليبل وكذلك القيمة القصوى للبروجريس بار
الإجراء Reset : نقوم باعادة كل شيء الى ما كان عليه :
الان نأتي للاحداث :
الحدث txtSearch.TextChanged : سنجري عملية البحث وايجاد النتائج اثناء الكتابة ، لهذا نستخدم الحدث txtSearch.TextChanged
نقوم اولا باعادة كل شيء Reset()
نعرف متغيرات للنص المطلوب البحث فيه textToSearch ونص البحث word وكذلك نتيجة البحث matches
اذا كانت الكلمة ليس بها احرف ، لا نكمل التالي
نقوم باجراء عمليه البحث وتخزين النتائج في matches
اذا كانت النتائج خالية لا نكمل ايضا
نقوم بملي الليبل وتجهيز شريط التقدم ، وكذلك ملئ الليست بوكس
اذا كان خيار التلوين التلقائي معلم نقوم بتلوين النتائج
حدث btnColor.Click : عند الضغط على زر التلوين نريد ان نحصل على نتائج البحث من الليست بوكس ، ثم بعد ذلك نطلب اجراء التلوين :
اذا كانت الليست فارغة او كانت النتائج فارغة هذا معناه لا يوجد نتائج لتلوينها ، لذلك نعود
حدث txtSearch.GotFocus و txtSearch.LostFocus : نريد ان نعرف اذا كان مربع البحث قيد الاستخدام ام لا ، لانه في كل مرة ينفذ حدث تغير الكتابة يتم مليء الليست بوكس وينطلق حدث تغير العنصر المختار SelectedIndexChanged ويفقد مربع النص تركيزه
نقوم بتعريف متغير عام textboxFocusd من نوع Boolean ، عندما تحصل الاداه على التركيز ياخذ قيمة True وعندما تفقده ياخذ قيمة False :
الحدث lstResults.SelectedIndexChanged : عندما يختار المستخدم عنصر من الليست بوكس نريد ان نذهب الى هذا العنصر تحديدا ونقوم بتحديده في ال RichTextBox :
لاحظ نختبر اذا كان مربع النص عليه تركيز لا نكمل
النتيجة :
ملاحظات هامة للتطوير :
1. في النصوص الطويلة تلوين الكلمات قد يأخذ وقت ملحوظ ، لذلك تعطيل التلوين التلقائي قد يكون فكرة جيدة
2. هذه الطريقة لا تأخذ بعين الاعتبار الاشكال المختلفة للحرف الواحد ، مثلا الالف : ( أاإآ ) او الواو ( وؤ ) ، ربما اقوم بتطوير شامل لهذه النقطة
3. هذه الطريقة ايضا لا تشمل حركات المصحف كالغنة وحركات الوقف وغيرها ، الموضوع للتبسيط اشتمل على الحركات الاساسية فقط
4. هذه الطريقة تعامل الحروف في المدى الحرفي Unicode من u0600 الى u06FF على انها حروف عربية ، وهي اغلبها حروف فعلا ولكن بها ايضا رموز يجب للدقة استثنائها ولكن لم ارغب ان يكون تعبير البحث معقدا لسهولة الفهم ، ربما اقوم بتطوره ليصبح اكثر دقة
واخيرا :
اخيرا وجب ان اقول اني اجد الموضوع على قدر كبير جدا من الاهمية ، لذلك استحق الوقت والمجهود سواء في المثال او حتى في الموضوع نفسه هنا ، اتمنى ان يكون قد قدم الافادة المطلوبة ، ويسعدني جدا ان اشرح نقطة معينة مجددا ان كنت قد قصرت فيها ، وكذلك مقترحاتكم لتطوير هذه الطريقة
السلام عليكم ورحمة الله وبركاته
كان الاخ عبد الهادي قد طرح تساؤل حول البحث عن الكلمات داخل نص عربي يحتوي على حركات فتحة وضمة وهكذا ، وكان سؤالا هامة جدا وجيدا للغاية
وكنت قد توصلت للحل باستخدام Regex ووعدت بان اقوم بشرح الموضوع بشكل اكبر
نبدأ على بركة الله
تقديم للمشكلة :
تشكيل الحروف يمثل مشكلة عند البحث في الكلمات ، لان التشكيل نفسه يعتبر حرفا ،
مثلا في الآية :
الْحَمْدُ لِلَّهِ الَّذِي أَنْزَلَ عَلَىٰ عَبْدِهِ الْكِتَابَ وَلَمْ يَجْعَلْ لَهُ عِوَجًا ۜ
اذا اردت البحث عن الكلمة "الحمد" فان الطريقة التقليدية IndexOf() مثلا فانها لن تنجح ،
الكلمة التي تريد البحث عنها : الحمد : ا - ل - ح - م - د
الكلمة الموجودة في الاية : ا - ل - ْ - ح - َ - م - ْ - د - ُ
ما يقوم به IndexOf هو مقارنة حرف حرف من الكلمتين لايجاد تطابق ، وبالتالي لن ينجح الامر عند وجود تشكيل
نحتاج طريقة ما للبحث ، بحيث نخبرها اننا نقبل اي من حروف التشكيل بعد كل حرف من الكلمة المطلوبة ، هنا يأتي دور Regex
تقديم Regex :
التعابير النمطية او القياسية او Regular Expression هي طريقة للبحث داخل نصوص بشكل رئيسي ، باستخدام تعابير تأخذ شكل معين لتحديد طريقة البحث المطلوب ، وهي طريقة جميلة جدا وعملية جدا وسريعة جدا فيما يتعلق بالوقت
لست بصدد شرح Regex هنا ، يمكنك ان تجد معلومات اكثر عنها من هنا :
http://vb4arb.com/vb/showthread.php?tid=467
https://docs.microsoft.com/en-us/dotnet/...-reference
https://docs.microsoft.com/en-us/dotnet/...etcore-3.1
ولكن سأشرح ما سنحتاجه فقط .
استخدم الموقع التالي للتجربة : https://regex101.com/r/euj8kG/1
الفئة System.Text.RegularExpressions.Regex تحتوي على دالة Matches التي تعيد MatchCollection يمثل المطابقات في النص المطلوب البحث فيه ، تقبل مدخلان :
الاول : النص المطلوب البحث بداخله
الثاني : تعبير Regex المستخدم في البحث ، ونحتاج منه الآتي :
الكلمات الحرفية : في تعبير Regex اذا اردت البحث عن حروف ما بعينها بنفس الترتيب ، فعليك وضعها كما هيا في التعبير :
التعبير التالي يبحث عن كلمة vb4arab
كود :
vb4arab
الاختيار بين مجموعة حروف : اذا اردت اختيارا من بين اكثر من حرف ، يعني اما هذا او هذا او هذا تضعه بين اقواس مربعة [] في المكان الذي تريده :
التعبير التالي يبحث عن الكلمات vb4arab و vb3arab و vb2arab :
كود :
vb[234]arab
ويمكن استخدام - للدلالة على المدى من كذا الى كذا :
كود :
vb[2-4]arab
الدلالة على التكرار : اذا اردت ان يكون الحرف اختياري ويمكن تكراره اكثر من مرة استخدم * بعد الحرف المطلوب :
التعبير التالي يبحث عن vb4arb و vb4araaaaab و vb4arab و ....
كود :
vb4ara*b
ويمكن استخدامها مع اختيار من الحروف
التعبير التالي يبحث عن vb4arab و vb4323243343323223arab و vbarab و .... ايضا :
كود :
vb[2-4]*arab
مجموعات الالتقاط : فرضا انت تبحث عن نص بشرط ما ، ولكنك لاتريد فعلا ان ترجع بالنص باكمله بل تريد جزء منه فقط كان تبحث عن كلمتين مكررتين بعد بعضهما مباشرة وتريد الكلمة فقط ، هذه فائدة مجموعات الالتقاط Capture group
التعبير التالي نفس التعبير السابق ولكنننا نضع الارقام في مجموعة نسميها x لكي نستعيدها مستقبلا :
كود :
vb(?<x>[2-4]*)arab
استخدام الحروف بكود unicode : اذا حاولت وضع التشكيل في الكود فانه على الارجح لن يكتب ، بدلا من ذلك نستخدم التعبير بكود الحرف unicode
قائمة بيونيكود الحروف العربية : https://en.wikipedia.org/wiki/Arabic_script_in_Unicode
التعبير التالي يبحث عن حرف ال v والذي له الكود U+0056 :
كود :
\u0056
الخطة :
الان يجب ان نحدد الاهداف :
1. نريد البحث عن الكلمات التي تحتوي على النص المدخل من المستخدم مع الاخذ بالاعتبار التشكيل
2. نريد ملي ال ListBox بنتائج البحث
3. نريد تلوين النص المدخل فقط من المستخدم ( ليس الكلمة كلها ) في كل المواقع الموجودة في النص الاصلي
4. عند اختيار المستخدم عنصر من ال ListBox يقوم البرنامج بالقفز الى موقعه في النص الاصلي
التصميم :
الكود :
الدوال والاجرائات :
سنعرف بعض الدوال لتسهيل العملية ،
الدالة SearchArabic : عصب الكود الاساسي ، سنقوم فيها باجراء عملية البحث واعادة IEnumerable(Of Match) تمثل نتائج البحث لاستخدامها لاحقا ،
ببساطة ، تأخذ النص المطلوب البحث عنه ، ونص البحث :
كود :
Function SearchArabic(Text As String, Word As String) As IEnumerable(Of Match)
End Function
طيب الان ماذا نريد ان نفعل ؟
نريد ان نكوّن نص التعبير ،
ببساطة نأخذ كل حرف ونضيف بعده القيمة [\u064B-\u0652]* التي تمثل اي من حروف التشكيل ، اختياري وقابل للتكرار
كود :
Dim expression As String
For Each l In Word
expression &= l & "[\u064B-\u0652]*"
Next
الان نحن نبحث عن الحروف المدخلة من المستخدم فقط وسط التشكيل وهذا شيء جميل
لكن كيف نستخرج الكلمة كاملة ؟
الامر بغاية البساطة ، نخبره بان يحضر ايضا اي عدد من الحروف العربية قبل هذه الحروف التي نبحث عنها وكذلك اي عدد من الحروف العربية بعد هذه الحروف التي نبحث عنها
للتوضيح : (اي عدد من الحروف العربية)(حروف البحث)(اي عدد من الحروف العربية)
مدى الحروف العربية هو من U+0600 الى U+06FF
كود :
Dim expression As String = "[\u0600-\u06FF]*"
For Each l In Word
expression &= l & "[\u064B-\u0652]*"
Next
expression &= "[\u0600-\u06FF]*"
الان نحن جاهزون للبحث عن الكلمة باكملها ،نريد ان نضع الحروف المدخلة من المستخدم في مجموعة ونضع لها اسم input حتى نتمكن من الحصول عليها لاحقا :
كود :
Dim expression As String = "[\u0600-\u06FF]*(?<input>"
For Each l In Word
expression &= l & "[\u064B-\u0652]*"
Next
expression &= ")[\u0600-\u06FF]*"
الان المتغير expression اصبح يحمل نص التعبير واصبح جاهزا لعملية البحث :
كود :
Return Regex.Matches(Text, expression).Cast(Of Match)
نجري عملية البحث من الدالة Regex.Matches ونقوم بتحويل النتائج الى IEnumerable(Of Match) عن طريق Cast(Of Match)
يصبح كود الدالة كاملا :
كود :
Function SearchArabic(Text As String, Word As String) As IEnumerable(Of Match)
Dim expression As String = "[\u0600-\u06FF]*(?<input>"
For Each l In Word
expression &= l & "[\u064B-\u0652]*"
Next
expression &= ")[\u0600-\u06FF]*"
Return Regex.Matches(Text, expression).Cast(Of Match)
End Function
للتجربة على كلمة "من" : https://regex101.com/r/QZKLfk/1
الإجراء ColorResults : نقوم فيه بتلوين نتائج البحث من مدخل المستخدم فقط وليس الكلمة كاملة ، لفعل ذلك نمر على نتائج البحث كلها ونختار المجموعة التي سميناها input ونلون منها
مدخلات الاجراء: RichTextBox الذي به النص ، IEnumerable(Of Match) نتائج البحث ، ProgressBar اختياري لعرض نتائج البحث
نستفيد من الخصائص داخل كائن ال Group ايضا مثل Index الذي يمثل بداية المجموعة داخل النص الاصلي و Length طول المجموعة
كود :
Sub ColorResults(richTextBox As RichTextBox, matches As IEnumerable(Of Match), Optional ProgressBar As ProgressBar = Nothing)
For Each m As Match In matches
Dim input As Group = m.Groups("input")
richTextBox.Select(input.Index, input.Length)
richTextBox.SelectionBackColor = Color.Yellow
If ProgressBar IsNot Nothing Then ProgressBar.PerformStep()
Next
End Sub
بكل بساطة نمر على نتائج البحث ،
لكل نتيجة نستخرج منها المجموعة "input" ،
نقوم بتحديد المجموعة من ال RichTextBox وتلوينها بالاصفر
نقوم بزيادة ال ProgressBar
الإجراء FillListBox : نقوم بملئ الليست بوكس به عن طريق ToList السحرية !
المدخلات : ListBox المطلوب ملئه ، و IEnumerable(Of Match) نتائج البحث :
كود :
Sub FillListBox(matches As IEnumerable(Of Match), ListBox As ListBox)
ListBox.DataSource = matches.ToList
End Sub
الإجراء PopulateResults : نقوم بوضع عدد نتائج البحث في الليبل وكذلك القيمة القصوى للبروجريس بار
كود :
Sub PopulateResults(matches As IEnumerable(Of Match))
lblResults.Text = String.Format("{0} نتيجة بحث", matches.Count)
prgColor.Maximum = matches.Count
End Sub
الإجراء Reset : نقوم باعادة كل شيء الى ما كان عليه :
كود :
Sub Reset()
lblResults.Text = "- نتيجة بحث"
prgColor.Value = 0
lstResults.DataSource = Nothing
rtbSource.SelectAll()
rtbSource.SelectionBackColor = Color.White
End Sub
الان نأتي للاحداث :
الحدث txtSearch.TextChanged : سنجري عملية البحث وايجاد النتائج اثناء الكتابة ، لهذا نستخدم الحدث txtSearch.TextChanged
كود :
Private Sub txtSearch_TextChanged(sender As Object, e As EventArgs) Handles txtSearch.TextChanged
Reset()
Dim word As String = txtSearch.Text.Trim
Dim textToSearch As String = rtbSource.Text
Dim matches As IEnumerable(Of Match)
If String.IsNullOrWhiteSpace(word) Then Return
matches = SearchArabic(textToSearch, word)
If matches.Count = 0 Then Return
PopulateResults(matches)
FillListBox(matches, lstResults)
If chkAutoColor.Checked Then ColorResults(rtbSource, matches, prgColor.ProgressBar)
End Sub
نقوم اولا باعادة كل شيء Reset()
نعرف متغيرات للنص المطلوب البحث فيه textToSearch ونص البحث word وكذلك نتيجة البحث matches
اذا كانت الكلمة ليس بها احرف ، لا نكمل التالي
نقوم باجراء عمليه البحث وتخزين النتائج في matches
اذا كانت النتائج خالية لا نكمل ايضا
نقوم بملي الليبل وتجهيز شريط التقدم ، وكذلك ملئ الليست بوكس
اذا كان خيار التلوين التلقائي معلم نقوم بتلوين النتائج
حدث btnColor.Click : عند الضغط على زر التلوين نريد ان نحصل على نتائج البحث من الليست بوكس ، ثم بعد ذلك نطلب اجراء التلوين :
كود :
Private Sub btnColor_Click(sender As Object, e As EventArgs) Handles btnColor.Click
Dim matches As IEnumerable(Of Match) = lstResults.DataSource
If matches Is Nothing OrElse matches.Count = 0 Then Return
ColorResults(rtbSource, matches, prgColor.ProgressBar)
End Sub
اذا كانت الليست فارغة او كانت النتائج فارغة هذا معناه لا يوجد نتائج لتلوينها ، لذلك نعود
حدث txtSearch.GotFocus و txtSearch.LostFocus : نريد ان نعرف اذا كان مربع البحث قيد الاستخدام ام لا ، لانه في كل مرة ينفذ حدث تغير الكتابة يتم مليء الليست بوكس وينطلق حدث تغير العنصر المختار SelectedIndexChanged ويفقد مربع النص تركيزه
نقوم بتعريف متغير عام textboxFocusd من نوع Boolean ، عندما تحصل الاداه على التركيز ياخذ قيمة True وعندما تفقده ياخذ قيمة False :
كود :
Dim textboxFocusd As Boolean
Private Sub txtSearch_GotFocus(sender As Object, e As EventArgs) Handles txtSearch.GotFocus
textboxFocusd = True
End Sub
Private Sub txtSearch_LostFocus(sender As Object, e As EventArgs) Handles txtSearch.LostFocus
textboxFocusd = False
End Sub
الحدث lstResults.SelectedIndexChanged : عندما يختار المستخدم عنصر من الليست بوكس نريد ان نذهب الى هذا العنصر تحديدا ونقوم بتحديده في ال RichTextBox :
كود :
Private Sub lstResults_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstResults.SelectedIndexChanged
If textboxFocusd Then Return
Dim lst As ListBox = sender
Dim m As Match = lst.SelectedItem
If m Is Nothing Then Return
rtbSource.SelectionStart = m.Index
rtbSource.SelectionLength = m.Length
rtbSource.Focus()
End Sub
لاحظ نختبر اذا كان مربع النص عليه تركيز لا نكمل
النتيجة :
ملاحظات هامة للتطوير :
1. في النصوص الطويلة تلوين الكلمات قد يأخذ وقت ملحوظ ، لذلك تعطيل التلوين التلقائي قد يكون فكرة جيدة
2. هذه الطريقة لا تأخذ بعين الاعتبار الاشكال المختلفة للحرف الواحد ، مثلا الالف : ( أاإآ ) او الواو ( وؤ ) ، ربما اقوم بتطوير شامل لهذه النقطة
3. هذه الطريقة ايضا لا تشمل حركات المصحف كالغنة وحركات الوقف وغيرها ، الموضوع للتبسيط اشتمل على الحركات الاساسية فقط
4. هذه الطريقة تعامل الحروف في المدى الحرفي Unicode من u0600 الى u06FF على انها حروف عربية ، وهي اغلبها حروف فعلا ولكن بها ايضا رموز يجب للدقة استثنائها ولكن لم ارغب ان يكون تعبير البحث معقدا لسهولة الفهم ، ربما اقوم بتطوره ليصبح اكثر دقة
واخيرا :
اخيرا وجب ان اقول اني اجد الموضوع على قدر كبير جدا من الاهمية ، لذلك استحق الوقت والمجهود سواء في المثال او حتى في الموضوع نفسه هنا ، اتمنى ان يكون قد قدم الافادة المطلوبة ، ويسعدني جدا ان اشرح نقطة معينة مجددا ان كنت قد قصرت فيها ، وكذلك مقترحاتكم لتطوير هذه الطريقة