در این تاپیک قصد دارم روشی رو آموزش بدم که میتونید به یک کنترل روی فرمی که سورس اون رو ندارید، دسترسی داشته باشید و مقدار اون رو بخونید.
یک مزیت این ترفند مواقعی هست که مثلاً شما یک GUI از یک وسیله دارین که به سورس اون دسترسی ندارین مثلاً یک اسکوپ دیجیتال که میتونه مقدار لحظه ای ولتاژ رو نشون بده یا هر چیز دیگه ای که بتونید تصور کنید، حالا شما برای اتوماتیک کردن یا اضافه کردن ویژگی جدید به برنامه محدودیت دارین ولی با این ترفند به راحتی میتونید به خروجی های برنامه دسترسی داشته باشین و کارهای Real-Time رو به راحتی انجام بدین و نیازی هم به سروکله زدن با کد و پروتکل وسیله ندارین.
در مثال، فرکانس کلاک CPU در برنامه CPU-Z رو به این روش روی فرمی که خودم ایجاد کردم نشون میدم.
من کدها رو در VB.NET مینویسم ولی به راحتی خودتون میتونید معادل #C اونها رو هم به دست بیارید در ضمن مهم نیست برنامه ای که میخواین ازش بخونید با چه زبانی نوشته شده باشه.
هر فرم یا کنترل روی فرم (مثل TextBox, Panel, Label, CheckBox, RadioButton و ...) در ویندوز دارای یک کد منحصر به فرد به اسم Handle هست که سیستم عامل ویندوز از طریق این هندل به اون دسترسی داره. در صورتی که شما هندل فرم و کنترل رو داشته باشین میتونید به اون کنترل دسترسی داشته باشین و مقدارش رو بخونید.
تنها مشکلی که وجود داره اینه که مقدار این هندل در هر بار اجرای برنامه متفاوته چون ویندوز بهش یک مقدار جدید نسبت میده و بنابراین در هر بار اجرای برنامه ای که میخواین مقداری ازش بخونید نیاز دارید که مقادیر هندل ها رو دوباره در کد پدیت کنید.
برای خواندن مقادیر هندل میتونید از برنامه کوچک ++WinSpy استفاده کنید.
روش کار هم خیلی راحته، کافیه ابزار نشان مانند شکل زیر رو روی فرم یا کنترل مورد نظر بکشید و رها کنید تا مشخصاتش رو به دست بیارید:

بعد مقدار Handle رو کپی کنید و در محلی که در کد برنامه میگم Paste کنید(روشهای دیگه هم هست ولی این ساده ترین و سرراست ترین روشه).
لازمه که در ابتدای برنامه (قبل از اعلان نام کلاس) کد زیر رو اضافه کنید تا بتونید با هندل کار کنید:
تابع زیر رو هم در قسمت Public کلاس (زیر نام کلاس) تعریف کنید:
در رویداد Load فرم هم کافیه کد زیر رو اضافه کنید:
مقداری که در جلوی متغیر CPU_Clock نوشته شده، همون مقدار هندل هست که کپی کردین، توجه کنید که چون این مقدار هگزادسیمال هست باید از پیشوند H& (در #C از 0x) استفاده بشه.
خط دوم هم مربوط به فعالسازی تایمری هست که در هر تیک اون، مقدار از برنامه CPU-Z خوانده میشه و روی فرم ما پدیت میشه. شما میتونید با تبدیل خروجی که string هست به double کارهای جالبتری هم با اون انجام بدین!
در رویداد تیک تایمر هم کد زیر رو نوشتم که توضیحات کافی هم داره:
و این هم نتیجه برنامه:

امیدوارم این تاپیک برای شما مفید باشه.
یک مزیت این ترفند مواقعی هست که مثلاً شما یک GUI از یک وسیله دارین که به سورس اون دسترسی ندارین مثلاً یک اسکوپ دیجیتال که میتونه مقدار لحظه ای ولتاژ رو نشون بده یا هر چیز دیگه ای که بتونید تصور کنید، حالا شما برای اتوماتیک کردن یا اضافه کردن ویژگی جدید به برنامه محدودیت دارین ولی با این ترفند به راحتی میتونید به خروجی های برنامه دسترسی داشته باشین و کارهای Real-Time رو به راحتی انجام بدین و نیازی هم به سروکله زدن با کد و پروتکل وسیله ندارین.
در مثال، فرکانس کلاک CPU در برنامه CPU-Z رو به این روش روی فرمی که خودم ایجاد کردم نشون میدم.
من کدها رو در VB.NET مینویسم ولی به راحتی خودتون میتونید معادل #C اونها رو هم به دست بیارید در ضمن مهم نیست برنامه ای که میخواین ازش بخونید با چه زبانی نوشته شده باشه.
هر فرم یا کنترل روی فرم (مثل TextBox, Panel, Label, CheckBox, RadioButton و ...) در ویندوز دارای یک کد منحصر به فرد به اسم Handle هست که سیستم عامل ویندوز از طریق این هندل به اون دسترسی داره. در صورتی که شما هندل فرم و کنترل رو داشته باشین میتونید به اون کنترل دسترسی داشته باشین و مقدارش رو بخونید.
تنها مشکلی که وجود داره اینه که مقدار این هندل در هر بار اجرای برنامه متفاوته چون ویندوز بهش یک مقدار جدید نسبت میده و بنابراین در هر بار اجرای برنامه ای که میخواین مقداری ازش بخونید نیاز دارید که مقادیر هندل ها رو دوباره در کد پدیت کنید.
برای خواندن مقادیر هندل میتونید از برنامه کوچک ++WinSpy استفاده کنید.
روش کار هم خیلی راحته، کافیه ابزار نشان مانند شکل زیر رو روی فرم یا کنترل مورد نظر بکشید و رها کنید تا مشخصاتش رو به دست بیارید:

بعد مقدار Handle رو کپی کنید و در محلی که در کد برنامه میگم Paste کنید(روشهای دیگه هم هست ولی این ساده ترین و سرراست ترین روشه).
لازمه که در ابتدای برنامه (قبل از اعلان نام کلاس) کد زیر رو اضافه کنید تا بتونید با هندل کار کنید:
کد PHP:
Imports System.Runtime.InteropServices
تابع زیر رو هم در قسمت Public کلاس (زیر نام کلاس) تعریف کنید:
کد PHP:
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
در رویداد Load فرم هم کافیه کد زیر رو اضافه کنید:
کد PHP:
CPU_Clock = &H28084C
tmrUpd100ms.Enabled = True
مقداری که در جلوی متغیر CPU_Clock نوشته شده، همون مقدار هندل هست که کپی کردین، توجه کنید که چون این مقدار هگزادسیمال هست باید از پیشوند H& (در #C از 0x) استفاده بشه.
خط دوم هم مربوط به فعالسازی تایمری هست که در هر تیک اون، مقدار از برنامه CPU-Z خوانده میشه و روی فرم ما پدیت میشه. شما میتونید با تبدیل خروجی که string هست به double کارهای جالبتری هم با اون انجام بدین!
در رویداد تیک تایمر هم کد زیر رو نوشتم که توضیحات کافی هم داره:
کد PHP:
'Alloc memory for the buffer that receives the text = 5 Bytes [you can change this value, increase for fast changes)
Dim Handle As IntPtr = Marshal.AllocHGlobal(5)
'send (message = 13) to the notepad window [you shouldn't change this value!]
' and (wparam = 7) [you should change this value to Maximum length of your text]
Dim NumText As Integer = SendMessage(CPU_Clock, 13, 7, Handle)
'copy the characters from the unmanaged memory to a managed string
Dim strValue As String = Marshal.PtrToStringUni(Handle)
'Dim strValue As String = Marshal.PtrToStringUni(Handle)
lblCPU.Text = strValue
و این هم نتیجه برنامه:

امیدوارم این تاپیک برای شما مفید باشه.
دیدگاه