تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
SoftWare Screen Resolution
#1
بسم الله الرحمن الرحيم

مقدمـــــــة :

هذا الموضوع أكتبه إكراما لرجل لما أقابله في الدنيا و عسي الله أن يجمعنا به جميعا في جنات النعيم و الموضوع بمثابة صدقة جارية علي روح هذا الرجل
لذلك أدعوكم جميعا أن تقرأو له الفاتحة و تترحموا عليه و تدعو له بالرحمة
هذا الرجل هو المغفور له أبوليث رحمة الله عليه
الهدف :

الهدف من هذا الموضوع هو توضيح كيفية حساب Resolution الخاصة بشاشة الكمبييوتر ثم استخدام تلك الحسابات في ضبط أبعاد الفورم و أيضا ضبط أبعاد كل شئ موجود علي الفورم مثل الكونترول و الصور و الفونت ليتناسب مع أبعاد شاشة الكمبيوتر
هذا الموضوع يصلح للإستخدام مع كل من الويندوز فورم و أيضا ربما يصلح للإستخدام مع WPF

أولا  عزيزي القارئ عليك ان تعلم أن كل شئ يظهر علي شاشة الكمبيوتر يتأثر كليا بشاشة الكمبيوتر و السبب في ذلك هو أن كل شئ علي سطح الكمبيوتر عبارة عن مجموعة من الرسومات التي تم رسمها علي سطح شاشة الكمبيوتر
والقائمة التالية تحتوي علي الأشياء التي تتأثر بشاشة الكمبيوتر
1-  الفونت  - Font
2-   الابعاد , والمقصد هنا Size و SizeF و  RectangleF و Rectangle
3-  أماكن الصور و الكونترول و ما شابه - و المقصد هنا Point و PointF
4-  الصور - Images أو  Icons او Bitmap
5-  الفورم - Form
6-  الكونترول - Control مثل PictureBox او ListBox او أشياء من هذا القبيل

بنظرة سريعة علي القائمة أعلاه ستجد  أن جميع هذه الأشياء لها صلة وثيقة و مرتبطة مع بعضها البعض تماما
توضيح :

1- في هذا الموضوع سوف أعتمد بشكل رئيسي و تام علي IntPtr ليكون بمثابة الرابط بين جميع العناصر الموجودة في القائمة أعلاه وكمثال علي ذلك سوف أستخدم IntPtr للحصول علي بيانات عن الفورم و أيضا للحصول علي عدد و كمية و نوعية الكونترول الموجودة علي الفورم. أيضا سوف أستخدم IntPtr للحصول علي معلومات عن شاشة الكمبيوتر Screen Class و أيضا NativeWindow Class
2- هذا الموضوع عبارة عن تجميع لمجموعة من الموضوعات كنت قد كتبتها علي مراحل متفرقة ولكن مع بعض التعديلات و الإضافات
وهذه الموضوعات ستجدونها في قسم المقالات هنا بالموقع
3- سوف أحاول جاهدا و بقدر الإمكان أن اضع جميع الروابط لأي مصادر قد تفيدكم لتوضيح الموضوع بشكل افضل
4- سوف أحاول أن أضع الكثير من الأمثلة لتوضيح الفكرة
5- هذا الموضوع سيتم كتابته علي أجزاء منفصلة لأنه موضوع قد لا ينتهي كلية

6- توضيح اخير ليس الهدف من الموضوع هو صياغة الكود نيابة عن القارئ لكن الهدف هو توضيح بعض المشاكل البرمجية و محاولة إيجاد حلولا لها و يتبقي علي القارئ إن كان مهتما بهذه النوعية من الموضوعات أن يطور أي كود تم كتابته عن هذا الموضوع لأن الهدف الأهم هو تحسين الكود المكتوب من أجل الحصول علي نوعية جيدة من الكود حتي يستفيد الجميع

في النهاية أدعو الله أن يكون الموضوع مفيدا للبعض منكم
و لا تنسونا من صالح دعائكم
غفر الله لنا و لكم ما تقدم من الذنوب و ما تأخر
الرد
#2
السلام عليكم
تقبل الله منك
الله يرحمه ويغفر له ويسكنه فسيح جناتة

وجزاك الله الف خير
  Heart   الرجاء البحث قبل وضع السؤال  Heart

   كل عام وانتم بالف بخير.  
الرد
تم الشكر بواسطة:
#3
الجزء الأول

هناك مجموعة من الدوال من النوع Shared و التي تم توزيعها علي بعض الكلاسات في الدوت نت وجميع هذه الدوال تشترك في شئ واحد ألا وهو إن مررت لها  IntPtr أو Handle الخاص بالفورم او بالكونترول بشكل صحيح هنا سوف تحصل علي بعض المعلومات الهامة  التي يمكن الاستفادة منها بأشكال عديدة.

وهذه الدوال كالتالي:
1- Control.FromHandle
و هي دالة حين تمرر لها IntPtr أو Handle الخاص بأي كونترول هنا سوف تحصل علي الكونترول الذي يمتلك هذا IntPtr او Handle
2- Screen.FromHandle
وهي دالة حين تمرر لها IntPtr أو Handle الخاص بأي كونترول هنا سوف تحصل علي Screen التي يوجد بها هذا الكونترول
3- NativeWindow.FromHandle
وهي أيضا دالة حين تمرر لها IntPtr أو Handle الخاص بأي كونترول هنا سوف تحصل علي NativeWindow المتصلة بهذا الكونترول

بشكل عام جميع هذه الدوال موجودة في فضاء الاسماء   System.Windows.Forms
ولكنها موزعة علي ثلاثة كلاسات هي الكلاس Control و الكلاس Screen و الكلاس NativeWindow

للأسف موقع مايكروسوفت لم يعطي أمثلة توضح كيفية استخدام الدوال أعلاه
لذلك المثال التالي سيوضح كيفية التعامل مع هذه الدوال
وهنا انا استخدم Handle الخاص بالفورم مع جميع الأكواد أدناه
ولتحاول عزيزي القارئ أن تضع باتون علي الفورم و تستخدم Handle الخاص بهذا الباتون بدلا من الفورم و لتري ماذا سيحدث معك

1- الكود التالي يوضح كيفية الحصول علي أي كونترول من Handle الخاص به
يمكن  كتابة الكود بالشكل التالي:
PHP كود :
Dim hwnd As IntPtr Me.Handle
Dim f 
As Form TryCast(Control.FromHandle(hwnd), Form
2- الكود التالي يوضح كيفية الحصول علي Screen التي تحتوي الكونترول او الفورم
PHP كود :
Dim hwnd As IntPtr Me.Handle
Dim scr 
As Screen TryCast(Screen.FromHandle(hwnd), Screen
 3- وبالمثل الكود التالي يوضح كيفية الحصول علي NativeWindow المرتبطة بأي كونترول
PHP كود :
Dim hwnd As IntPtr Me.Handle
Dim f 
As Form TryCast(Control.FromHandle(hwnd), Form
4- الكودالتالي يوضح كيفية الحصول علي الفورم عن طريق تمرير Handle الخاص به الي مصفوفة Application.OpenForms
فقط تأكد ان تمرر Index الخاص بالفورم بشكل صحيح

PHP كود :
Dim hwnd As IntPtr Me.Handle
Dim anyOpenform 
As Form TryCast(Control.FromHandle(Application.OpenForms(0).Handle), Form

أعتقد أنه و بعد الحصول علي Form او الكونترول أو Screen او NativeWindow بهذا الاسلوب سيكون الأمر يسيرا علي القارئ لكي يتعامل مع هذه المتغيرات كما يحلو له وذلك بهدف الحصول علي معلومات اضافية من كل متغير

قد يتساءل البعض و ما الفائدة من كل هذا الكود و الاجابة علي هذا التساؤل هي أننا نبني مكتبة بسيطة للتعامل مع الفورم و الكونترول و شاشة الكمبيوتر و بالتالي سوف نحتاج الي تلك المعلومات لكي نستفيد منها لاحقا
و لأننا نبني مكتبة لذلك من الأفضل كتابة كلاس بسيط بحيث حين نمرر له IntPtr أو Handle نستطيع أن نحصل علي المعلومات التي نحتاجها

و الكود التالي يوضح شكل هذا الكلاس و لقد كتبته علي هيئة Structure
والأمر متروك للقاري لكي يطور الكلاس و يضيف له بعض السمات الإضافية طبقا لرؤية القارئ


PHP كود :
Public Structure WindowPointer
    Private _handle 
As IntPtr

    Public Sub 
New(handle As IntPtr)
 
       _handle handle
    End Sub

    Public ReadOnly Property Handle 
As IntPtr
        Get
            Return _handle
        End Get
    End Property

    Public 
Function FindWindow() As System.Windows.Forms.Form
        If _handle 
<> IntPtr.Zero Then
            Return FindWindow
(_handle)
 
       End If
 
       Return Nothing
    End 
Function

 
   Public Function FindScreen() As System.Windows.Forms.Screen
        If _handle 
<> IntPtr.Zero Then
            Return FindScreen
(_handle)
 
       End If
 
       Return Nothing
    End 
Function

 
   Private Function FindWindow(hwnd As IntPtr) As System.Windows.Forms.Form
        Return 
(Function()
 
                   Return TryCast(System.Windows.Forms.Control.FromHandle(hwnd), System.Windows.Forms.Form)
 
               End Function)()
 
   End Function

 
   Private Function FindScreen(hwnd As IntPtr) As System.Windows.Forms.Screen
        Return TryCast
(System.Windows.Forms.Screen.FromHandle(hwnd), System.Windows.Forms.Screen)
 
   End Function

End Structure 

الكود التالي يوضح كيف تستخدم الكلاس كبديلا عن الأمثلة التي كتبنا أكوادها أعلاه
PHP كود :
       Dim hwnd As IntPtr Me.Handle
        Dim wp 
As WindowPointer = New WindowPointer(hwnd)

 
       Dim scr As Screen wp.FindScreen()
 
       Dim f As Form wp.FindWindow()

 
       Me.Text f.Name " -" "Test"

 
       Dim screenBounds As Rectangle scr.Bounds
        Dim scrWorkingAre 
As Rectangle scr.WorkingArea 

لمزيد من التفاصيل يمكن للقارئ الإطلاع علي الروابط  الروابط التالية
Control.FromHandle 
Screen.FromHandle
NativeWindow.FromHandle
IntPtr Structure
الرد
تم الشكر بواسطة: ابو ليلى
#4
الجزء الثاني

ضبط الفورم و الكونترول ليتنسابا مع أبعاد اي شاشة كمبيوتر يتلخص في الخطوات التالية:

1- تحديد مقياس الرسم الذي نراه مناسبا و افضل مقياس رسم هو القيمة = 1
2- معرفة  الفورم الي سنقوم بضبط أبعاده
3- معرفة جميع الكونترول الموجودة علي الفورم
4-  معرفة DPI الخاص بأي شاشة عرض وهذا يتم باستخدام الجرافكس
5- ثم بناء علي حسابات DPI نحسب مقياس الرسم الحقيقي الذي يتناسب مع ابعاد شاشة الكمبيوتر

الأن نأتي لكيفية كتابة الأكواد لتنفيذ الخطوات أعلاه و هي خطوات بسيطة جدا
في الحدث Load الخاص بالفورم ضع الكود التالي

PHP كود :
       ' تحديد مقياس الرسم
        Dim scale As Double = 3

        ' 
تحديد الفورم
        Dim currentForm 
As Form Me

        
' تحديد جميع الكونترول علي الفورم
        ' 
هنا يجب أن نتحري الدقة قليلا لأنه ربما الفورم لا يعطيك جميع الكونترول  فعليا
        
'خاصة حينما يكون لديك اي كونترول أخر مثل الجروب بوكس مثلا قد يحتوي علي بعض الكونترول
        Dim currenControls As Control.ControlCollection = Me.Controls

        ' 
حسابات دقة الشاشة
        

        Dim dpiX As Single = CSng(88)
        Dim dpiY As Single = CSng(96)
        Dim currentDpi As SizeF = SizeF.Empty
        Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
            currentDpi = New SizeF(Math.Max(g.DpiX, dpiX), Math.Max(g.DpiY, dpiY))
        End Using

        ' 
حسابات مقياس الرسم الدقيق و الفعلي
        Dim realScale 
As Double = (scale currentDpi.Width) / 100

        
' الأن لنضبط أبعاد  الفورم
        Dim currentFormSize As Size = currentForm.Size
        Dim newBestSize As Size = New Size(currentFormSize.Width * realScale, currentFormSize.Height * realScale)
        currentForm.Size = newBestSize 

مثلا أن أردت تغيير الفونت قم بإضافة الأسطر التالية من الكود الي الأكواد اعلاه
 
PHP كود :
       ' مثال لكيفية ضبط الفونت مع مقياس الرسم
        ' 
ضع باتون علي الفورم و لاحظ ما سيحدث معك
        Dim currentFormFont 
As Font currentForm.Font
        Dim bestFitFont 
As Font = New Font(currentFormFont.FontFamilycurrentFormFont.Size realScale)
 
       currentForm.Font bestFitFont 

حاول تغير في مقياس الرسم و أقصد هنا المتغير scale و لتري ما سيحدث معك

أخيرا و بما أننا نصنع كلاس او نبني مكتبة بسيطة لضبط الفورم ليكون مناسبا مع ابعاد الشاشة فإن الكود سيكون مختلف قليلا
لكن ستظل الخطوات واحدة

وإن أردت أن تفعل نفس الشي مع جميع الكونترول الموجودة علي الفورم فقط ستحتاج الي حلقة تكرارية و تقوم بضبط ابعاد كل كونترول

في الجزء الثالث و الأخير سأضع لكم الكلاس الذي يمكنكم استخدامه مع اي فورم
الرد
تم الشكر بواسطة: ابو ليلى
#5
الجزء الثالث و الأخير

الكود التالي يوضح شكل الكلاس الذي من الممكن استخدامه لضبط ابعاد الفورم لتتناسب مع شاشة الكمبيوتر
الكلاس يمكن اعتباره أساس معقول لبعض المبرمجين لكي يطوروا فيه بشكل أفضل

PHP كود :
Public Structure WindowResolution

    Private _scale 
As Double
    Private _hwnd 
As IntPtr
    Private 
Const LogicDpiX As Integer 88
    Private 
Const LogicDpiY As Integer 96

    
' هنا يتم استخدام مقياس رسم يساوي 1
    Public Sub New(hwnd As IntPtr)
        Me.New(hwnd, 1)
    End Sub

    ' 
هنا يمكن تحديد مقياس رسم أكبر من أو أقل من 1
    Public Sub 
New(hwnd As IntPtrscale As Double)
 
       _hwnd hwnd
        _scale 
scale
    End Sub

    Public ReadOnly Property Controls 
As IEnumerable(Of Control)
 
       Get
            Dim _controls 
As IEnumerable(Of Control) = Nothing
            If _hwnd 
<> IntPtr.Zero Then
                Dim criteria 
As Func(Of ControlBoolean) = Function(cc IsNot Nothing AndAlso Not c.IsDisposed AndAlso c.IsHandleCreated AndAlso c.Visible
                Dim ctrl 
As Form TryCast(Control.FromHandle(_hwnd), Form)
 
               _controls = If(Not criteria(ctrl), New Control() {}, GetControls(ctrl.Controlsctrlcriteria))

 
           End If
 
           Return _controls
        End Get
    End Property

    Public ReadOnly Property Window 
As Form
        Get
            If _hwnd 
<> IntPtr.Zero Then
                Return FindWindow
(_hwnd)
 
           End If
 
           Return Nothing
        End Get
    End Property

    Public ReadOnly Property Scale 
As Double
        Get
            Return CalculateScale
(_scale)
 
       End Get
    End Property

    Public ReadOnly Property Size 
As Size
        Get
            Dim currentFormSize 
As Size Window.Size
            Dim bestFitSize 
As Size = New Size(currentFormSize.Width ScalecurrentFormSize.Height Scale)
 
           Return bestFitSize
        End Get
    End Property

    Public ReadOnly Property Font 
As Font
        Get
            Dim currentFormFont 
As Font Window.Font
            Dim bestFitFont 
As Font = New Font(currentFormFont.FontFamilycurrentFormFont.Size Scale)
 
           Return bestFitFont
        End Get
    End Property

    Private 
Function FindWindow(hwnd As IntPtr) As System.Windows.Forms.Form
        Return 
(Function()
 
                   Return TryCast(System.Windows.Forms.Control.FromHandle(hwnd), System.Windows.Forms.Form)
 
               End Function)()
 
   End Function

 
   Private Sub FindControls(parent As Controlcontrols As HashSet(Of Control), criteria As Func(Of ControlBoolean))
 
       If parent Is Nothing Then
            Return
        End 
If
 
       For Each ctrl As Control In parent.Controls
            If criteria
(ctrlThen
                controls
.Add(ctrl)
 
           End If

 
           If ctrl.HasChildren Then
                FindControls
(ctrlcontrolscriteria)
 
           End If
 
       Next
    End Sub

    Private 
Function GetControls(list As ICollectionparent As Controlcriteria As Func(Of ControlBoolean)) As HashSet(Of Control)
 
       If list Is Nothing OrElse parent Is Nothing Then
            Return Nothing
        End 
If
 
       Dim controls As HashSet(Of Control) = New HashSet(Of Control)()
 
       For Each ctrl As Control In list
 
           controls.Add(ctrl)
 
           FindControls(parentcontrolscriteria)
 
       Next
        Return controls
    End 
Function

 
   Private Function DetectResolution() As SizeF
        Return DetectResolution
(CType(NothingControl))
 
   End Function

 
   Private Function DetectResolution(control As Control) As SizeF
        Dim currentDpi 
As SizeF SizeF.Empty
 
       Dim dpiX As Single CSng(LogicDpiX)
 
       Dim dpiY As Single CSng(LogicDpiY)
 
       If control Is Nothing Then
            Using g 
As Graphics Graphics.FromHwnd(IntPtr.Zero)
 
               currentDpi = New SizeF(Math.Max(g.DpiXdpiX), Math.Max(g.DpiYdpiY))
 
               Return currentDpi
            End Using
        End 
If
 
       Using g As Graphics control.CreateGraphics()
 
           currentDpi = New SizeF(Math.Max(g.DpiXdpiX), Math.Max(g.DpiYdpiY))
 
           Return currentDpi
        End Using

        Return currentDpi
    End 
Function

 
   Private Function CalculateScale(value As Double) As Double
        Return 
(value DetectResolution().Width) / 100
    End 
Function

End Structure 

الكود التالي يوضح بعضا من الأفكار البسيطة لكيفية استخدام الكلاس

PHP كود :
       Dim res As New WindowResolution(Me.Handle1.4)
 
       Me.Size res.Size
        Me
.Font res.Font 

أتمني ان تكون الفكرة قد اتضحت للقارئ
الرد
تم الشكر بواسطة: khodor1985 , khodor1985 , ابو ليلى
#6
شكرا لك استاذ silverlight
رحمه الله عليك يا ابا الليث ,, التقيته ذات حين , وهو من ارقى الناس الذين عرفتهم .
رحمه الله رحمه واسعة.
الرد
تم الشكر بواسطة: elgokr , elgokr , silverlight


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  Detect Display Screen DPI silverlight 3 795 11-06-16, 12:07 PM
آخر رد: Sajad
  Introduction To Screen Capture silverlight 2 1,086 09-10-15, 05:22 PM
آخر رد: silverlight
  معلومة ::: How to resize Windows form to fit Windows screen ::: RaggiTech 0 687 06-10-12, 09:53 PM
آخر رد: RaggiTech
  درس- كيفية عمل شاشة البدء splash Screen RaggiTech 0 2,132 05-10-12, 10:36 AM
آخر رد: RaggiTech
  مثال Screen Server RaggiTech 0 627 05-10-12, 01:13 AM
آخر رد: RaggiTech
  إعمل Splash Screen في دقيقة! RaggiTech 0 701 02-10-12, 01:01 AM
آخر رد: RaggiTech
  MultiPoint Software Development RaggiTech 1 538 01-10-12, 06:11 PM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم