Wednesday, August 30, 2006

ทดลองใช้ user32.dll เพื่อเรียกขนาด Resolution

จากการอ่านบทความเมื่อวานเกี่ยวกับการใช้งาน Win32API บน C# ผมก็ได้ทดลองนำไป
ใช้งานกับการเขียนโปรแกรมใช้งาน Win32API ซึ่ง API ตัวที่ผมเรียกใช้คือ user32.dll

สำหรับ Function ที่ผมเลือกที่จะใช้คือ SystemParameterInfo ซึ่งผมจะใช้ ฟังก์ชัน
นี้ในการเรียกค่า Resolution ของจอภาพมาดูครับว่าปัจจุบัน Desktop ของเราใช้
Resolution ของจอภาพไว้ที่เท่าไร

ด้านล่างจะเป็นการประกาศใน Visual Basic นะครับ ( จาก APIViewer )
Public Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long

สำหรับ Sourcecode ของโปรแกรมนะครับผมแปลงมาใส่ C# จากด้านบนเป็นดังนี้ครับ

แน่นอนครับลืมไม่ได้ถ้าจะใช้ WIN32API ต้องอ้างถึงตัวนี้
using System.Runtime.InteropServices;

จากนั้น
[DllImport("user32.dll",EntryPoint="SystemParametersInfo")]
private static extern int SystemParametersInfo(int uiAction,int uiParam,out rc pvParam,int fWinlni);

สำหรับตัวโปรแกรมผมออกแบบโดยมีฟอร์ม 1 ฟอร์มมี Label ไว้แสดง Resolution
และมีปุ่มกด เพื่อใช้เรียกฟังก์ชันให้ดึงค่า Resolution มาแสดงบน Label ที่กำหนด
ตัวอย่างโค๊ตที่จะทำงานเมื่อมีการกดปุ่มนะครับ

private void button1_Click(object sender, EventArgs e)
{
rc Rect;
int lngResult;
lngResult = SystemParametersInfo(48, 0,out Rect,0);

label1.Text = "";
label1.Text = "("+Rect.Left+")("+Rect.Top+"),("+Rect.Rigth+")("+Rect.Bottom+")";
}


** ข้อสังเกตุ **
จากการประกาศ rc Rect;
ตัวแปร rc ในที่นี้คือ Struct ซึ่งแปลงมาจาก Type ของ Visual Basic ใน APIViewer

CODE ประกาศ Struct ของ C#

struct rc
{
public int Left;
public int Top;
public int Rigth;
public int Bottom;
}

ตัวอย่างการเรียกใช้จาก Visual Basic

เริ่มแรกต้องประกาศใช้ก่อนดังนี้
Declare Function SystemParametersInfo Lib "user32.dll" _
Alias "SystemParametersInfoA"(ByVal uiAction As Long, _
ByVal uiParam As Long,pvParam as Any,ByVal fWinlni As Long) As Long

สำหรับ CODE ในปุ่มก็มีดังนี้ครับ

Private Sub Command1_Click()
Dim udiWorkArea As RECT
Dim lngResult As Long

lngResult = SystemParametersInfo(SPI_GETWORKAREA,0,udiWorkArea,0)

With udiWorkArea
Label1.Caption = "(" & .Right &","& .Bottom &")"
End With

End Sub


** หมายเหตุ 1 **
เมื่อเราเปิดจาก APIViewer ในส่วนของ Constant จะพบว่าตัวแปร RECT มีประเภทเป็น Type
ใน Visual Basic ซึ่งจะเท่ากับ Stuct เราจึงทำการประกาศ Struct ใน CODE C#

** หมายเหตุ 2 **
ในส่วนนี้ของ Visual Basic ( บรรทัดล่าง )
lngResult = SystemParametersInfo(SPI_GETWORKAREA,0,udiWorkArea,0)

จะเห็นว่าต่างจากของ C# คือ
lngResult = SystemParametersInfo(48, 0,out Rect,0);

เนื่องมาจาก SPI_GETWORKAREA ใน Visual Basic ตามเอกสารของ WIN32API ระบุว่า
เป็นตัวแปรแบบค่าคงที่ เท่ากับ 48

และที่ส่วนของ Parameter ที่ส่งมีคำว่า out Rect เนื่องจากในการประกาศใช้ Function
มีการกำหนดให้เป็น out rc เอาไว้ ดัง Code ด้านล่าง
[DllImport("user32.dll",EntryPoint="SystemParametersInfo")]
private static extern int SystemParametersInfo(int uiAction,int uiParam,out rc pvParam,int fWinlni);

จะเห็นว่าในส่วนที่ APIViewer แจ้งว่า Function มี Argument แบบ ByVal หรือ ByRef
เวลาเรานำมาประกาศใน C# เราต้องมี out นำหน้า datatype ตามด้วย ชื่อตัวแปร

** หมายเหตุ 3 **
จะสังเกตุว่า เราใช้ int ในตัวแปรของ C# แทนที่จะประกาศเป็น long เช่นเดียวกับ Visual Basic
นั้นก็เพราะขนาดของข้อมูลของ Visual Basic และ C# ไม่เท่ากัน

จบข่าวครับ . . .

No comments: