المشاركات : 490
المواضيع 54
الإنتساب : Sep 2013
السمعة :
63
الشكر: 1726
تم شكره 1192 مرات في 348 مشاركات
23-07-16, 05:45 PM
(آخر تعديل لهذه المشاركة : 23-07-16, 05:53 PM {2} بواسطة السندبااد.)
السلام عليكم ورحمة الله وبركاته
سابقاً تجاوزت مشكلة البحث مع التشكيل سواء في قواعد البيانات أو أدوات العرض ، والحمد لله تجاوزت ذلك في تقنية WPF إلا أنني اصطدمت بحاجز أداة RichTextBox ؛ فعند البحث في الريتش بوكس يعطيني نتائج صحيحة ولكن لو كان البحث مع تجاهل التشكيل فلن يتم تلوين كلمة البحث الموجودة بشكل صحيح ، البرنامج على هذ الرابط :
وهنا صفحة البرنامج وهو مفتوح المصدر تم نشره على صفحات هذا المنتدى سابقاً :
الملف باسم : Makalat-Source.rar
طبعاً أنا برمجت دالة لتجاهل التشكيل وستجدها ضمن البرنامج باسم ReplaceString وهي تعمل بشكل جيد كما سترى
فقد استخدمتها ضمن البحث في قواعد البيانات مع تجاهل التشكيل
المشكلة فقط في تلوين الكلمة عندما يكون النص في الريتش بوكس مشكولاً
بعد أن تحمل السورس شغل البرنامج واختر مقالة التحيات والصلوات الإبراهيمية
واكتب في مربع البحث مثلاً كلمة الله
ثم انقر زر "بحث في هذه المقالة"
ستجد النتائج صحيحة ولكن التلوين خطأ لأن كلمة الله في الريتش بوكس مشكولة
ولو بحثت في مقالة سامي باني حسين عن كلمة سامي
ستجد النتائج صحيحة والتلوين صحيح لأن كلمة سامي في الريتش بوكس غير مشكولة
فاعلم أنه لا إله إلا الله
المشاركات : 490
المواضيع 54
الإنتساب : Sep 2013
السمعة :
63
الشكر: 1726
تم شكره 1192 مرات في 348 مشاركات
سبب المشكلة التي وضعتها هو أنه عند البحث عن كلمة غير مشكولة فإنه يقوم بحسب عدد حروفها وعدد الخانات في الجملة ليبدأ التلوين من عندها ؛ مثلاً : بسم الله الرحمن الرحيم ، عند البحث عن كلمة الرحيم سيعرف أن عدد الحروف 6 وبداية الكلمة عند الخانة 17 وبناء عليه سيتم التلوين ، ولكن لو كانت الجملة مشكولة فهنا سيحدث التشويش ؛ لأن التشكيل يعتبر خانة ؛ فكلمة الرَّحيم سيعتبر أن عدد حروفها 8 ، وهكذا.
بعيداً عن هذه الطريقة وصلت لحل عن طريق Regex وكانت النتائج مذهلة ومرضية 100 % ولكن المشكلة أن البحث عن طريق Regex سيُفقِد الريتش بوكس تنسيقها وسيكون لها تنسيق مخصص بعد البحث.
فاعلم أنه لا إله إلا الله
المشاركات : 490
المواضيع 54
الإنتساب : Sep 2013
السمعة :
63
الشكر: 1726
تم شكره 1192 مرات في 348 مشاركات
27-07-16, 12:20 AM
(آخر تعديل لهذه المشاركة : 27-07-16, 12:26 AM {2} بواسطة السندبااد.)
بصراحة أنا دخت بالنت والبحث والتجريب حتى أصل لكود احترافي
ولكن الفضل لله تعالى وكرمه وصلت إلى الكود الاحترافي الذي يُمكنني من خلاله البحث في الريتش بوكس مع المحافظ على تنسيقاتها وترتيبها
البحث مع تجاهل التشكيل ، سواء البحث عن كلمة واحدة أو عدة كلمات ، وعندما يعطيك النتيجة ستكون الكلمة ملونة حتى لو كانت في الريتش مشكولة
إليكم الكود :
كود :
Dim range As New TextRange(RichTxtPost.Document.ContentStart, RichTxtPost.Document.ContentEnd)
'منسق
Dim GetPost As String
GetPost = myInput2
Dim documentBytes = Encoding.UTF8.GetBytes(GetPost)
Using reader = New MemoryStream(documentBytes)
reader.Position = 0
RichTxtPost.SelectAll()
RichTxtPost.Selection.Load(reader, DataFormats.Rtf)
End Using
Dim pattern As String = ""
For Each c As Char In Me.TxtSearch.Text.Trim
pattern = pattern & Regex.Escape(c) & "[\u064B-\u0653]*"
Next c
'للبحث عن كلمة واحدة
Dim reg As New Regex("(" & pattern & ")", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
'للبحث عن عدة كلمات
'Dim reg As New Regex("(" & pattern & "| مُحَمَّدٍ " & "| إِبْرَاهِيمَ " & ")", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
Dim start = RichTxtPost.Document.ContentStart
While start IsNot Nothing AndAlso start.CompareTo(RichTxtPost.Document.ContentEnd) < 0
If start.GetPointerContext(LogicalDirection.Forward) = TextPointerContext.Text Then
Dim match = reg.Match(start.GetTextInRun(LogicalDirection.Forward))
Dim textrange = New TextRange(start.GetPositionAtOffset(match.Index, LogicalDirection.Forward), start.GetPositionAtOffset(match.Index + match.Length, LogicalDirection.Backward))
textrange.ApplyPropertyValue(TextElement.ForegroundProperty, New SolidColorBrush(Colors.Red))
'textrange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold)
start = textrange.[End]
End If
start = start.GetNextContextPosition(LogicalDirection.Forward)
End While
وهذه الصورة لا تحتاج لتعليق :
الجميل في هذا الكود وفي Regex أنك تستطيع تنويع البحث
فمثلاً لو بحثت عن لفظ الجلالة الله بدون فستخرج لك في كل الحالات مرفوعة ومجرورة ومكسورة
ولو بحث عن لفظ الجلالة اللهُ في حالة الرفع فستخرج لك النتائج في حالة الرفع فقط
على فكرة كوننا نتحدث عن تجاهل التشكيل هنالك دالة لحذف التشكيل وتجاهله من أي عبارة
أو حتى لاستخدامها في البحث داخل قاعدة البيانات
وهذه الدالية غير دالة ReplaceString التي استخدمتها أنا في برنامج خزانة المقالات
بل هي دالة RemoveDiacritics تفضلوا كود الدالة :
كود :
Private Shared Function RemoveDiacritics(text As String) As String
Dim normalizedString = text.Normalize(NormalizationForm.FormD)
Dim stringBuilder = New StringBuilder()
For Each c As Object In normalizedString
Dim unicodeCategory__1 = CharUnicodeInfo.GetUnicodeCategory(c)
If unicodeCategory__1 <> UnicodeCategory.NonSpacingMark Then
stringBuilder.Append(c)
End If
Next
Return stringBuilder.ToString().Normalize(NormalizationForm.FormC)
End Function
فاعلم أنه لا إله إلا الله
المشاركات : 1,733
المواضيع 147
الإنتساب : Sep 2012
السمعة :
215
الشكر: 8484
تم شكره 12163 مرات في 1145 مشاركات
الحمدلله انك وجدت الحل
المشاركات : 531
المواضيع 4
الإنتساب : May 2016
السمعة :
55
الشكر: 694
تم شكره 535 مرات في 367 مشاركات
روووعة، باينه من الصورة.
هل يمكن تطبيق هذا البحث الرائع على RichTextBox الخاصة بالجوال بيسيك أو العملية مخصصة لأدوات wpf
المشاركات : 490
المواضيع 54
الإنتساب : Sep 2013
السمعة :
63
الشكر: 1726
تم شكره 1192 مرات في 348 مشاركات
المشاركات : 490
المواضيع 54
الإنتساب : Sep 2013
السمعة :
63
الشكر: 1726
تم شكره 1192 مرات في 348 مشاركات
السلام عليكم ورحمة الله وبركاته
من أراد أن يبحث عن أكثر من كلمة في الريتش بوكس فليستخدم هذا الكود :
كود :
'إما أن تعمل مصفوفة بهذا الشكل
'Dim Days(6) As String
'Days(0) = "الله"
'Days(1) = "رسول"
'Days(2) = "عن"
'Days(3) = "قال"
'Days(4) = "من"
'Days(5) = "عليه"
'Days(6) = "سلم"
'أو مصفوفة بهذا الشكل
Dim Days() As String = {"الله", "رسول", "عن", "قال", "من", "عليه", "سلم"}
'عدد محتويات المصفوفة
'MsgBox((Days.Count))
Dim range As New TextRange(RichTxtPost.Document.ContentStart, RichTxtPost.Document.ContentEnd)
'منسق
Dim GetPost As String
GetPost = myInput2
Dim documentBytes = Encoding.UTF8.GetBytes(GetPost)
Using reader = New MemoryStream(documentBytes)
reader.Position = 0
RichTxtPost.SelectAll()
RichTxtPost.Selection.Load(reader, DataFormats.Rtf)
End Using
Dim pattern As String = ""
For ii = 0 To Days.Count - 1
For Each c As Char In Days(ii).ToString
pattern = pattern & Regex.Escape(c) & "[\u064B-\u0653]*"
Next c
'تنسيق الكلمات لتخرج بالنهاية هكذا
'"(عليه|سلم|من|قال|عن|رسول|الله)"
pattern = "(" & pattern & ")" & "|"
Next
'سنحذف من آخر المتغير القوس والعمود |)
pattern = Mid(pattern, 1, Len(pattern) - 2)
'MsgBox(pattern)
'للبحث عن كلمة واحدة
'نضع المتغير + القوس الذي حذفناها فنحن كانت غايتنا حذف العمود لا القوس فهنا نعيد القوس في النهاية
Dim reg As New Regex(pattern & ")", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
'للبحث عن عدة كلمات
'Dim reg As New Regex("(" & pattern & "| مُحَمَّدٍ " & "| إِبْرَاهِيمَ " & ")", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
If reg.Matches(range.Text).Count < 1 Then
MsgBox("لا يوجد نتائج")
Else
MsgBox("عدد النتائج : " & reg.Matches(range.Text).Count)
End If
Dim start = RichTxtPost.Document.ContentStart
While start IsNot Nothing AndAlso start.CompareTo(RichTxtPost.Document.ContentEnd) < 0
If start.GetPointerContext(LogicalDirection.Forward) = TextPointerContext.Text Then
Dim match = reg.Match(start.GetTextInRun(LogicalDirection.Forward))
Dim textrange = New TextRange(start.GetPositionAtOffset(match.Index, LogicalDirection.Forward), start.GetPositionAtOffset(match.Index + match.Length, LogicalDirection.Backward))
textrange.ApplyPropertyValue(TextElement.ForegroundProperty, New SolidColorBrush(Colors.HotPink))
textrange.ApplyPropertyValue(Inline.TextDecorationsProperty, TextDecorations.Underline)
'textrange.ApplyPropertyValue(Inline.FontStyleProperty, FontStyles.Italic)
'textrange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold)
start = textrange.[End]
End If
start = start.GetNextContextPosition(LogicalDirection.Forward)
End While
فاعلم أنه لا إله إلا الله
المشاركات : 476
المواضيع 33
الإنتساب : Mar 2014
السمعة :
175
الشكر: 366
تم شكره 1393 مرات في 471 مشاركات
03-11-20, 02:14 PM
(آخر تعديل لهذه المشاركة : 03-11-20, 02:20 PM {2} بواسطة Anas Mahmoud.)
صراحة اول مرة اشاهد هذا الموضوع المفيد بحق ، وكنت قد بحثت عن هذا الموضوع كثيرا فعلا وتوصلت للحل باستخدام Regex بطريقة مشابهة جدا ، سعيد اني وجدت من تحدث في هذا الموضوع هنا على المنتدى من قبل
وخصوصا "[\u064B-\u0653]*" السحرية ، وحقيقة زاد حبي لل Regex بعدها كثيرا وعزمت على ان اطور الطريقة اكثر لتشمل حالات اكثر وتوفر طريقة سلسة للبحث داخل النصوص العربية ان شاء الله
جزاك الله خير الجزاء وبارك لك
المشاركات : 490
المواضيع 54
الإنتساب : Sep 2013
السمعة :
63
الشكر: 1726
تم شكره 1192 مرات في 348 مشاركات
(03-11-20, 02:14 PM)Anas Mahmoud كتب : صراحة اول مرة اشاهد هذا الموضوع المفيد بحق ، وكنت قد بحثت عن هذا الموضوع كثيرا فعلا وتوصلت للحل باستخدام Regex بطريقة مشابهة جدا ، سعيد اني وجدت من تحدث في هذا الموضوع هنا على المنتدى من قبل
وخصوصا "[\u064B-\u0653]*" السحرية ، وحقيقة زاد حبي لل Regex بعدها كثيرا وعزمت على ان اطور الطريقة اكثر لتشمل حالات اكثر وتوفر طريقة سلسة للبحث داخل النصوص العربية ان شاء الله
جزاك الله خير الجزاء وبارك لك
هذا الموضوع كان شغلي الشاغل، ودخلت في عدة حوارات سابقاً حوله؛ منها هذا هنا.
حقيقة أحييك على جهدك الرائع في الوصول إلى حل، واليوم كنت أقرأ موضوعك في هذا الخصوص، وليتك بالفعل تقوم بعمل تطوير للطريقة؛ لأن هذا من أهم المواضيع للمبرمجين، أضف أن البعض يشكو من Regexبأنها بطيئة، فإيجاد طريقة سلسلة سيكون شيئاً رائعاً.
أسأل الله تعالى أن يستجيب دعواتك الطيبة، وأن يرحم والدك ويجعله في زمرة الأنبياء والشهداء والصالحين
فاعلم أنه لا إله إلا الله
|