prof.programer

[ تمت الإجابة ]كيفية التنقل بين مربعات نص (كونترولز ) باستخدام Api

7 ردود في هذا الموضوع

السلام عليكم

بداية اود تقديم شرح بسيط

يوجد برنامج واجهته كما في المرفقات :

من داخل الكود نجد انها مكونة من 9 عناصر (controls ) عدد اثنين منها مربعات نص بالاضافة الى واحد من نوع زر

الذي احاوله هو التالي :

يوجد برنامج اخر سيرسل send message ليضع set focus على النص الاول و يمرر قيمة ثم يكرر نفس العملية على المربع الثاني و يمرر قيمة

و لكن الذي يحصل معي انه في كلتا الحالتين يمرر النص لنفس المربع و احيانا لا يمرر لاي مربع نص مع العلم انه ينفذ التعليمات بدون اخطاء

و اليكم الاكواد

Public Class NativeWin32

<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function FindWindow(ByVal lpClassName As StringBuilder, ByVal lpWindowName As String) As Integer
End Function

<DllImport("User32.dll")> _
Private Shared Function EnumChildWindows _
(ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
ByVal lParam As IntPtr) As Boolean
End Function
'
'--- user defined datatype
Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean

Public Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
Dim ChildrenList As New List(Of IntPtr)
Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
Try
EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
Finally
If ListHandle.IsAllocated Then ListHandle.Free()
End Try
Return ChildrenList.ToArray
End Function


<DllImport("user32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function GetDlgCtrlID(ByVal hWnd As IntPtr) As Integer
End Function

Public Const WM_SETTEXT = &HC
Public Const WM_SETFOCUS = &H7

Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

end class

و الان لدينا دالتان الاولى هي T() تطلب من المستخدم ادخل اسم الشاشة المطلوبة و من ثم يقوم باستدعاء دالة اخرى وكودها كالتالي :

Sub T()
'
Dim WinWnd As Long, Ret As String, RetVal As Long, lpClassName As New StringBuilder()
'Ask for a Window title
Ret = InputBox("Enter the exact window title:" + Chr(13) + Chr(10) + "Note: must be an exact match")
'Search the window
WinWnd = NativeWin32.FindWindow(Nothing, Ret)

If WinWnd = 0 Then MsgBox("Couldn't find the window ...") : Exit Sub
'
Me.tt(WinWnd)
End Sub

الدالة الثانية اسمها TT() وهي تقوم بمهمة ايجاد controls التي يحويها الفورم و من ثم يبدا بالمرور عندما يجد مربعات النص الخاصة بنا يمرر نص كما هو في الكود التالي

Sub tt(ByVal winwnd As Long)
Dim tWnd As Long
Dim strValue As String
'
Dim i() As IntPtr
ReDim i(UBound(NativeWin32.GetChildWindows(WinWnd)))
'MsgBox(i.Length)
Dim sbTitle1 As StringBuilder = New StringBuilder(1024)
''
For ii As Integer = 0 To UBound(NativeWin32.GetChildWindows(winwnd))
'--- CONTROL CLASS NAME
NativeWin32.GetClassName(NativeWin32.GetChildWindows(winwnd).GetValue(ii), sbTitle1, sbTitle1.Capacity)
'MsgBox(sbTitle1.ToString)
'
Dim Id As Int32 = NativeWin32.GetDlgCtrlID(NativeWin32.GetChildWindows(winwnd).GetValue(ii))
If ii = 0 Or ii = 1 Then
'
'tWnd = NativeWin32.SetForegroundWindow(winwnd) 'bring the whole form to the front (optional)
tWnd = NativeWin32.SendMessage(Id, NativeWin32.WM_SETFOCUS, 0&, 0&) 'Focus to Text1
strValue = "hello" 'value of textbox
'Dim gh As GCHandle = GCHandle.Alloc(strValue, GCHandleType.Pinned)
SendKeys.SendWait(strValue)
'tWnd = NativeWin32.SendMessage(Id, NativeWin32.WM_SETTEXT, 0&, gh.AddrOfPinnedObject) 'store the value
'
End If
'
Next

End Sub

كما اسلفت سابقا المشكلة لدي في داخل جملة اتخاذ القرار if الاوامر غير دقيقة و لا ينفذ المطلوب على اكمل وجه

بانتظار تعليقات الاعضاء الاعزاء لحل المشكلة و من لديه فكرة افضل نرحب بسردها للنقاش و كي تعم الفائدة

تقبلو تحياتي

post-65668-1251289560_thumb.jpg

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

لتقوم بتحديد الاداه التاليه يمكنك استدعاء الداله SendMessege ثم تمرير مقبض النافذه ثم تمرير الرساله WM_NEXTDLGCTL

بالنسبه لـ lParam : يحتوى إما على TRUE او FALSE و معنى كل منهم يحدده الـ wParam

بالنسبه للـ wParam : إذا كان lParam يحتوى على TRUE فهنا يتم وضع الـ ID الخاص بالاداه التى سيتم وضع الـ Focus عليها، إما إذا كان lParam يساوى FALSE فأمامك حاله من اثنين

1 - اما ان يحتوى wParam على صفر و هذا يعنى ان اول اداه تاليه للحاليه و ايضا احد خصائص نوعها WS_TAPSTOP سيتم الوقوف عليها.

2 - اما إذا كان wParam يحتوى على غير الصفر فسيتم وضع الـ Focus على اول اداه سابقه للحاليه و ايضا احد خصائص نوعها WS_TAPSTOP سيتم الوقوف عليها.

و الله ولى التوفيق

تم تعديل بواسطه Muhammad alaa
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

If ii = 0 Or ii = 1 Then

؟

جملة الشرط هنا تعني أنه لا ضروة لان تكون جملة الـ for بهذا الشكل

For ii As Integer = 0 To UBound(NativeWin32.GetChildWindows(winwnd))

ويكفي ان تكون هكذا

For ii As Integer = 0 To 1

--

اعتقد ان عليك عمل ما يلي:

معرفة نوع ال class للمكون الذي تريد التعامل معه

مقارنة ما تحصلت عليه من إستدعاء NativeWin32.GetClassName مع الـ class المعروف سابقاً فان تطابقا قم بما تريد

أين أنك ستغير في جملة الشرط ...

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الاخ محمد علاء بارك الله فيك و شاكرا لك التوضيح و جاري تجربة المقترح

الاخ ياسين

لا يمكنني وضع for لييعمل للقيمة 0 و 1 فقط لانه عمليا لا نعلم ما هو موقع control في مصفوفة controls الموجودة في الواجهة و لكن بحكم التجربة و استخدام اسم الصنف تمكنت من معرفة ال id الخاص بمربعي النص و لكن هذه ليست قاعدة و انما حالة خاصة للمثال الذي ادرجته انا لتسهيل العمل فقط

و ينقصني ايضا كيفية ارسال امر click الى button الموجود في نفس الواجهة باستخدام send message ؟

و ذلك لنتمكن من الدخول الى التطبيق ( لم اقم ببرمجة التطبيق ولا يمكنني معرفة اكواده لذلك اجبرت للدخول في api للتحكم الالي فيه )

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

لمحاكة الحدث Click على الزر نستخدم الداله SendMessege و نرسل لها مقبض الزر و الرساله BM_CLICK ثم الـ wParam و lParam بصفر

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

يمكنك معرفة الـ Style الخاص بالإداه بإستخدام Spy++

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
لا يمكنني وضع for لييعمل للقيمة 0 و 1 فقط لانه عمليا لا نعلم ما هو موقع control في مصفوفة controls الموجودة في الواجهة

لم أقل ذلك . كنت أقصد أن جملة الشرط لن تنفذ إلا حين تكون ii تساوي 0 أو 1 أي أنه لا داعي لجملة الـ for لأن تكون بذلك الشكل بل إن الحصول على الـ classname , ID لا فائدة منه في الكود الذي وضعته في أول مشاركة لك ..

راجع ردي جيداً ولاحظ اني أشرت لطريقة الحل التي اتوقعها هنا

اعتقد ان عليك عمل ما يلي:

معرفة نوع ال class للمكون الذي تريد التعامل معه

مقارنة ما تحصلت عليه من إستدعاء NativeWin32.GetClassName مع الـ class المعروف سابقاً فان تطابقا قم بما تريد

أين أنك ستغير في جملة الشرط ...

النقطة الاولى :

معرفة نوع الـ class للمكون الذي تريد التعامل معه ... لم أذكر التفاصيل لأني ظننت أن تعرف الطريقة للحصول عليها وإحدى تلك الطرق

يمكنك معرفة الـ Style الخاص بالإداه بإستخدام Spy++

باختصار التعديل يجب أن يكون في جملة الشرط فقط ...

تم تعديل بواسطه YaSeenTA
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .