09-06-16, 02:36 AM
(آخر تعديل لهذه المشاركة : 09-06-16, 02:44 AM {2} بواسطة silverlight.)
السلام عليكم ورحمة الله وبركاته
هذا الموضوع الهدف منه توضيح كيفية تحديد قيمة DPI الخاصة بشاشة جهاز الكمبيوتر و الإستفادة من تلك القيمة في برامجنا المختلفة
مقدمـــــة
هناك أساليب كثيرة لإسترداد قيمة DPI الخاصة بجهاز الكمبيوتر والأمثلة التالية توضح كيفية استرجاع تلك القيمة
المثال الأول
من الممكن استخدام الدالة الموجودة في الكود التالي وهي عبارة عن Un-Managed API Function وبشكل عام الدالة مصممة لإسترداد قيم كثيرة غير قيمة DPI الخاصة بجهاز الكمبيوتر
الكود التالي يوضح كيف نستخدم الدالة أعلاه لإسترداد قيمة DPI الخاصة بجهاز الكمبيوتر إما عن طريق استخدام شاشة الكمبيوتر بشكل مباشر أو عن طريق استخدام الفورم أو باستخدام اي كونترول موجود علي الفورم
لكن وبما أن الفكرة في الكود أعلاه هي الحصول علي قيمة DpiX و قيمة DpiY وبما أن قيمتهما التي هي عبارة عن Integer تعتمد اصلا علي Screen Graphics أو تعتمد علي Control Graphics لذلك من السهل جدا الإستغناء عن الدالة GetDeviceCaps أعلاه و إعادة كتابة الكود بأسلوب أخر يسهل فهمه والأكواد التالية توضح كيفية الإستغناء عن الدألة أعلاه و تحويلها الي Managed كود
المثال الثاني
من الممكن الإستغناء عن الدالة GetDeviceCaps و تحويلها الي Managed Code كالتالي بحيث يتم استرجاع قيمة DPI علي هيئة SizeF
طبعا من الأسهل للمبرمج إعادة كتابة الكود أعلاه علي هيئة دالة حتي يستطيع استخدامها حين يشاء و الكود التالي يوضح شكل هذه الدالة وكيفية استخدامها
المثال الثالث
هذا المثال يعتمد علي نفس الأسلوب المستخدم في المثال الثاني و لكن بدلا من استخدام SizeF تم كتابة Structure اسمه DPI
ومن ثم نسترجع القيمة الخاصة به
الكود التالي يوضح شكل الدوال التي من الممكن استخامها مع DPI Structure أعلاه لإسترجاع القيمة الخاصة به
الكود التالي يوضح كيف تستخدم الدوال أعلاه
كيف نستفيد من DPI
هذا هو السؤال الأهم في الموضوع و الإجابة عليه تكمن في أن كل شئ يظهر علي شاشة الكمبيوتر يتأثر تماما بقيمة DPI فعلي سبيل المثال أبعاد الكونترول أو أبعاد الفورم و أيضا الفونت و أيضا مكان الكونترول علي الفورم و ايضا الصور تتأثر بتلك القيمة
إذن الفائدة من قيمة DPI هي أنه ومن الممكن استخدام تلك القيمة في عمل مقياس رسم Scale لظهور كل شئ علي شاشة الكمبيوتر مثل الصور Bitmaps/Images و الفونت Font و الأبعاد Size و مكان الكونترول Location
بحيث ومهما تغيرت أبعاد شاشة الكمبيوتر يظل الفورم الخاص بك و جميع الكونترول الموجودة علي الفورم تقوم بضبط مكانها و ابعادها والفونت الخاص بها أتوماتيكيا ليتناسب مع أبعاد شاشة الكمبيوتر
ولكن لهذا حديث أخر ...... في المرفقات ستجدون نسخة من جميع الأكواد مكتوبة ببرنامج الفيجوال استوديو 2015
المراجع
GetDeviceCaps
تقبلوا تحياتي
هذا الموضوع الهدف منه توضيح كيفية تحديد قيمة DPI الخاصة بشاشة جهاز الكمبيوتر و الإستفادة من تلك القيمة في برامجنا المختلفة
مقدمـــــة
هناك أساليب كثيرة لإسترداد قيمة DPI الخاصة بجهاز الكمبيوتر والأمثلة التالية توضح كيفية استرجاع تلك القيمة
المثال الأول
من الممكن استخدام الدالة الموجودة في الكود التالي وهي عبارة عن Un-Managed API Function وبشكل عام الدالة مصممة لإسترداد قيم كثيرة غير قيمة DPI الخاصة بجهاز الكمبيوتر
PHP كود :
<DllImport("gdi32.dll")>
Public Shared Function GetDeviceCaps(ByVal hDC As IntPtr, ByVal nIndex As Integer) As Integer
End Function
الكود التالي يوضح كيف نستخدم الدالة أعلاه لإسترداد قيمة DPI الخاصة بجهاز الكمبيوتر إما عن طريق استخدام شاشة الكمبيوتر بشكل مباشر أو عن طريق استخدام الفورم أو باستخدام اي كونترول موجود علي الفورم
PHP كود :
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' -------------------- Method 1
' use screen to create graphics object
Dim g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
' Get screen hdc
Dim hdcHigh As IntPtr = g.GetHdc()
' use the unmanaged API function to get Dpi values
Dim dpiX_Screen As Integer = GetDeviceCaps(hdcHigh, DeviceCap.LOGPIXELSX)
Dim dpiY_Screen As Integer = GetDeviceCaps(hdcHigh, DeviceCap.LOGPIXELSY)
' -------------------- Method 2
' use control/form to create graphics object
Dim gr As Graphics = CreateGraphics()
' Get control hdc
Dim hdcLow As IntPtr = gr.GetHdc()
' use the unmanaged API function to get Dpi values
Dim dpiX_Control As Integer = GetDeviceCaps(hdcLow, DeviceCap.LOGPIXELSX)
Dim dpiY_Control As Integer = GetDeviceCaps(hdcLow, DeviceCap.LOGPIXELSY)
' show result in form
Label1.Text = dpiX_Screen
Label2.Text = dpiY_Screen
Label3.Text = dpiX_Control
Label4.Text = dpiY_Control
End Sub
<DllImport("gdi32.dll")>
Public Shared Function GetDeviceCaps(ByVal hDC As IntPtr, ByVal nIndex As Integer) As Integer
End Function
End Class
Public Enum DeviceCap As Integer
''' <summary>
''' Device driver version
''' </summary>
DRIVERVERSION = 0
''' <summary>
''' Device classification
''' </summary>
TECHNOLOGY = 2
''' <summary>
''' Horizontal size in millimeters
''' </summary>
HORZSIZE = 4
''' <summary>
''' Vertical size in millimeters
''' </summary>
VERTSIZE = 6
''' <summary>
''' Horizontal width in pixels
''' </summary>
HORZRES = 8
''' <summary>
''' Vertical height in pixels
''' </summary>
VERTRES = 10
''' <summary>
''' Number of bits per pixel
''' </summary>
BITSPIXEL = 12
''' <summary>
''' Number of planes
''' </summary>
PLANES = 14
''' <summary>
''' Number of brushes the device has
''' </summary>
NUMBRUSHES = 16
''' <summary>
''' Number of pens the device has
''' </summary>
NUMPENS = 18
''' <summary>
''' Number of markers the device has
''' </summary>
NUMMARKERS = 20
''' <summary>
''' Number of fonts the device has
''' </summary>
NUMFONTS = 22
''' <summary>
''' Number of colors the device supports
''' </summary>
NUMCOLORS = 24
''' <summary>
''' Size required for device descriptor
''' </summary>
PDEVICESIZE = 26
''' <summary>
''' Curve capabilities
''' </summary>
CURVECAPS = 28
''' <summary>
''' Line capabilities
''' </summary>
LINECAPS = 30
''' <summary>
''' Polygonal capabilities
''' </summary>
POLYGONALCAPS = 32
''' <summary>
''' Text capabilities
''' </summary>
TEXTCAPS = 34
''' <summary>
''' Clipping capabilities
''' </summary>
CLIPCAPS = 36
''' <summary>
''' Bitblt capabilities
''' </summary>
RASTERCAPS = 38
''' <summary>
''' Length of the X leg
''' </summary>
ASPECTX = 40
''' <summary>
''' Length of the Y leg
''' </summary>
ASPECTY = 42
''' <summary>
''' Length of the hypotenuse
''' </summary>
ASPECTXY = 44
''' <summary>
''' Shading and Blending caps
''' </summary>
SHADEBLENDCAPS = 45
''' <summary>
''' Logical pixels inch in X
''' </summary>
LOGPIXELSX = 88
''' <summary>
''' Logical pixels inch in Y
''' </summary>
LOGPIXELSY = 90
''' <summary>
''' Number of entries in physical palette
''' </summary>
SIZEPALETTE = 104
''' <summary>
''' Number of reserved entries in palette
''' </summary>
NUMRESERVED = 106
''' <summary>
''' Actual color resolution
''' </summary>
COLORRES = 108
' Printing related DeviceCaps. These replace the appropriate Escapes
''' <summary>
''' Physical Width in device units
''' </summary>
PHYSICALWIDTH = 110
''' <summary>
''' Physical Height in device units
''' </summary>
PHYSICALHEIGHT = 111
''' <summary>
''' Physical Printable Area x margin
''' </summary>
PHYSICALOFFSETX = 112
''' <summary>
''' Physical Printable Area y margin
''' </summary>
PHYSICALOFFSETY = 113
''' <summary>
''' Scaling factor x
''' </summary>
SCALINGFACTORX = 114
''' <summary>
''' Scaling factor y
''' </summary>
SCALINGFACTORY = 115
''' <summary>
''' Current vertical refresh rate of the display device (for displays only) in Hz
''' </summary>
VREFRESH = 116
''' <summary>
''' Vertical height of entire desktop in pixels
''' </summary>
DESKTOPVERTRES = 117
''' <summary>
''' Horizontal width of entire desktop in pixels
''' </summary>
DESKTOPHORZRES = 118
''' <summary>
''' Preferred blt alignment
''' </summary>
BLTALIGNMENT = 119
End Enum
لكن وبما أن الفكرة في الكود أعلاه هي الحصول علي قيمة DpiX و قيمة DpiY وبما أن قيمتهما التي هي عبارة عن Integer تعتمد اصلا علي Screen Graphics أو تعتمد علي Control Graphics لذلك من السهل جدا الإستغناء عن الدالة GetDeviceCaps أعلاه و إعادة كتابة الكود بأسلوب أخر يسهل فهمه والأكواد التالية توضح كيفية الإستغناء عن الدألة أعلاه و تحويلها الي Managed كود
المثال الثاني
من الممكن الإستغناء عن الدالة GetDeviceCaps و تحويلها الي Managed Code كالتالي بحيث يتم استرجاع قيمة DPI علي هيئة SizeF
PHP كود :
Public Class Form2
' Logical pixels inch in X
Public Const LogicDpiX As Integer = 88
' Logical pixels inch in Y
Public Const LogicDpiY As Integer = 96
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' -------------------- Method 1
' use screen to create graphics object
Dim g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
Dim dpi_Screen As SizeF = SizeF.Empty
dpi_Screen = New SizeF(Math.Max(g.DpiX, CSng(LogicDpiX)), Math.Max(g.DpiY, CSng(LogicDpiY)))
' -------------------- Method 2
' use control/form to create graphics object
Dim gr As Graphics = CreateGraphics()
Dim dpi_Control As SizeF = SizeF.Empty
dpi_Control = New SizeF(Math.Max(gr.DpiX, CSng(LogicDpiX)), Math.Max(gr.DpiY, CSng(LogicDpiY)))
' show result in form
Label1.Text = dpi_Screen.Width
Label2.Text = dpi_Screen.Height
Label3.Text = dpi_Control.Width
Label4.Text = dpi_Control.Height
End Sub
End Class
طبعا من الأسهل للمبرمج إعادة كتابة الكود أعلاه علي هيئة دالة حتي يستطيع استخدامها حين يشاء و الكود التالي يوضح شكل هذه الدالة وكيفية استخدامها
PHP كود :
Private Function DetectDsipalyDPI() As SizeF
Return DetectDsipalyDPI(CType(Nothing, Control))
End Function
Private Function DetectDsipalyDPI(control As Control) As SizeF
Dim dpi As SizeF = SizeF.Empty
If control Is Nothing Then
Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
dpi = New SizeF(Math.Max(g.DpiX, CSng(LogicDpiX)), Math.Max(g.DpiY, CSng(LogicDpiY)))
Return dpi
End Using
End If
Using g As Graphics = control.CreateGraphics()
dpi = New SizeF(Math.Max(g.DpiX, CSng(LogicDpiX)), Math.Max(g.DpiY, CSng(LogicDpiY)))
Return dpi
End Using
Return dpi
End Function
' كيف تستخدم الدالة
Dim dpiX As Single = DetectDsipalyDPI().Width
Dim dpiY As Single = DetectDsipalyDPI().Height
' show result
Me.Text = dpiX & "," & dpiY
المثال الثالث
هذا المثال يعتمد علي نفس الأسلوب المستخدم في المثال الثاني و لكن بدلا من استخدام SizeF تم كتابة Structure اسمه DPI
ومن ثم نسترجع القيمة الخاصة به
PHP كود :
Public Structure DPI
Public Sub New(dpiX As Single, dpiY As Single)
_DpiX = dpiX
_DpiY = dpiY
End Sub
Public ReadOnly Property DpiX As Single
Public ReadOnly Property DpiY As Single
Public Shared Empty As DPI = New DPI(0, 0)
End Structure ' Dpi
الكود التالي يوضح شكل الدوال التي من الممكن استخامها مع DPI Structure أعلاه لإسترجاع القيمة الخاصة به
PHP كود :
' Logical pixels inch in X
Public Const LogicDpiX As Integer = 88
' Logical pixels inch in Y
Public Const LogicDpiY As Integer = 96
Public Function DetectScreenDPI() As DPI
Return DetectScreenDPI(CType(Nothing, Control))
End Function
Public Function DetectScreenDPI(control As Control) As DPI
Dim currentDpi As DPI = DPI.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 DPI(Math.Max(g.DpiX, dpiX), Math.Max(g.DpiY, dpiY))
Return currentDpi
End Using
End If
Using g As Graphics = control.CreateGraphics()
currentDpi = New DPI(Math.Max(g.DpiX, dpiX), Math.Max(g.DpiY, dpiY))
Return currentDpi
End Using
Return currentDpi
End Function
الكود التالي يوضح كيف تستخدم الدوال أعلاه
PHP كود :
Dim dpi As DPI = DetectScreenDPI()
' show result
Me.Text = dpi.DpiX & "," & dpi.DpiY
كيف نستفيد من DPI
هذا هو السؤال الأهم في الموضوع و الإجابة عليه تكمن في أن كل شئ يظهر علي شاشة الكمبيوتر يتأثر تماما بقيمة DPI فعلي سبيل المثال أبعاد الكونترول أو أبعاد الفورم و أيضا الفونت و أيضا مكان الكونترول علي الفورم و ايضا الصور تتأثر بتلك القيمة
إذن الفائدة من قيمة DPI هي أنه ومن الممكن استخدام تلك القيمة في عمل مقياس رسم Scale لظهور كل شئ علي شاشة الكمبيوتر مثل الصور Bitmaps/Images و الفونت Font و الأبعاد Size و مكان الكونترول Location
بحيث ومهما تغيرت أبعاد شاشة الكمبيوتر يظل الفورم الخاص بك و جميع الكونترول الموجودة علي الفورم تقوم بضبط مكانها و ابعادها والفونت الخاص بها أتوماتيكيا ليتناسب مع أبعاد شاشة الكمبيوتر
ولكن لهذا حديث أخر ...... في المرفقات ستجدون نسخة من جميع الأكواد مكتوبة ببرنامج الفيجوال استوديو 2015
المراجع
GetDeviceCaps
تقبلوا تحياتي