صفحه: [1]
 
نويسنده موضوع: در ویندوز چه اتفاقی می افتد!!  (دفعات بازدید: 272 بار)
Shahryar
مدیر انجمن
*
آفلاین آفلاین

رشته: computer
سال ورود: 86
تعداد ارسال: 1484

تشكر
-اهدا شده: 976
-دريافت شده: 1444



ديدن مشخصات
« : سپتامبر 16, 2008, 10:09:22 am »

مقاله جالبی پیدا کردم گفتم بزارم بقیه هم استفاده کنن

ا سلام
مطلبی که امروز می خواهم بگم ارتباطی با زبان برنامه نویسی خاص نداره! ولی به نظر من یک Windows Application کار حرفه ای باید این مطلب را بدونه.
تا بحال از خودتان پرسیدید در داخل ویندوز چه اتفاقاتی می افته؟ مثلا این فرم از کجا می فهمه زمانی که رویدکمه Close کلیک کنیم باید فرم را ببندد؟ و ...!
بگذارید در ابتدا برخی کلمات اختصاصی در سطح ویندوز را شرح دهم(نه در سطح یک برنامه نویس، چون با هم کمی تفاوت می کند)

زینپس BUTTON، EDIT، COMBOBOX، LISTBOX، STATIC و... همگی به عنوان پنجره شناخته می شوند.
البته دلفی کارها با اکثر پنجره هایی که بالا گفتم آشنا هستند ولی برای کلی شدن مطلب برای تمام برنامه نویسان برخی از پنجره های بالا را شرح می دهم.

Edit که در بعضی زبانها به عنوان TextBox شناخته میشوند، کار آن دریافت و نمایش اطلاعات هست.

STATIC که در اکثر زبانها با نام Lable شناخته می شه، کار آن نمایش یک متن هست.

در ویندوز هر پنجره ای که ایجاد می شه یک عدد 32 بیتی منحصر به فردی به آن اختصاص داده می شه. که این عدد را با نام Handle می شناسیم.


زمانی که ما به طور مثال کلیدی را فشار می دهیم، درایور کیبرد آن کلید را تبدیل به Messageیی می کنه و میفرسته به صف Message های سیستم. پس از آن صف Message های سیستم آن را به Thread پنجره مربوطه میده، در Thread پنجره مربوطه یک حلقه وجوود داره که به طور دائم Message ها را دریافت می کند و بر اساس اون Message تصمیم می گیره که چه باید بکند(به اصطلاح، اگر Messageیی را پردازش کنیم می گوییم Message را Handle کردیم).

خوب گفتیم درایور Message یی ارسال می کند، چطور؟؟؟ در API - Application Programming Interface ویندوز متدی وجود داره به نام SendMessage که درایور با کمک آن این پیام را ارسال می کند.
ببینیمپارامترهای SendMessage چی هست :
کد:
LRESULT SendMessage(
HWND hWnd, // handle of destination window
UINT Msg, // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);

خوب ما که نفهمیدیم اگه فهمیدید به ما هم بگید  biggrin. به طور ساده چند خط بالا پارامتر های
SendMessage هست که به ترتیب توضیح می دهم. پارامتر اول hWnd هست، درواقع Handle پنجره ای که می خواهیم به آن Message را ارسال کنیم هست. پارامتر دوم یعنی Msg که کاملاً معلومه Message یی هست که می خواهیم به پنجره مربوطه ارسال کنیم. راجع به Message این رو باید بگم که Message در واقع یک عددی هست که در ویندوزاکثراً آن را با یک نام می شناسن که ابتدای آن WM شروع می شود. مخفف WindowMessage هست. مثلا عدد 201 (در مبنای 16) را به نام WM_LBUTTONDOWN می شناسند و زمانی که دکمه چپ ماوس پایین رفته باشد درایور ماوس این Message را ارسال می کند.

اگر به جای Handle عدد FFFF را ارسال کنیم که به عنوان HWND_BROADCAST آن را می شناسیم برای تمام پنجره ها این Message ارسال می شود.

2 تاپارامتر wParam و lParam اطلاعات اضافی یک Message می تواند باشد مثلاً در Message یی که در بالا گفتم wParam آن اگر کلید ترکیبی مانند Control یا Shift یا Alt یا ... فشرده شده باشه را مشخص می کند.
و همچنین در ناحیه بالایی lParam مقتصات x و در ناحیه بالایی lParam مقتصات y قرار می گیرد.
البته Message هایی هم هستند که ممکنه فقط از یکی از این دو پارامتر استفاده کنند یا اصلا از این دو استفاده نکنند.

اگه یادتون باشه گفتیم در Thread پنجره مربوطه که یک حلقه هست به طور مرتب Message ها را دریافت می کند، درواقع این کار با استفاده از متد GetMessage انجام می شود.
ببینیم پارامتر های GetMessage چی هست :

کد:
BOOL GetMessage(
LPMSG lpMsg, // address of structure with message
HWND hWnd, // handle of window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message
);

ا معمولا فقط با پارامتر اول این متد کار داریم یعنی lpMsg که در واقع Message یی هست که برای این پنجره ارسال شده است.

حال خود به سوال اولی که پرسیدم جواب دهید زمانی که ما بر روی دکمه Close کلیک می کنیم چه اتفاقاتی می افته و از کجا می فهمه که باید این پنجره بسته شه.

image



براي اين پست, 1 کاربر تشکر کرده است
taban
خارج شده است
Shahryar
مدیر انجمن
*
آفلاین آفلاین

رشته: computer
سال ورود: 86
تعداد ارسال: 1484

تشكر
-اهدا شده: 976
-دريافت شده: 1444



ديدن مشخصات
« پاسخ #1 : اکتبر 14, 2008, 09:26:24 pm »

قسمت دوم این مقاله

گفتیم BUTTON، EDIT، COMBOBOX، LISTBOX، STATIC همه یک پنجره هستند، حال یک پنجره چی هست.
در واقع می خواهم این رو توضیح دهم که زمانی که ما پنجره ای از BUTTON را ایجاد می کنیم، چه اتفاقاتی می افته تا این BUTTON را ببینیم!

تابعی وجود داره به نام RegisterClass که پارامترهای آن به شکل زیر هست :

کد:
ATOM RegisterClass(
    CONST WNDCLASS *lpWndClass // address of structure with class data
   );

خوب این تابع Structureیی به شکل زیر دریافت می کند :

کد:
typedef struct _WNDCLASS {    // wc 
    UINT    style;
    WNDPROC lpfnWndProc;
    int     cbClsExtra;
    int     cbWndExtra;
    HANDLE  hInstance;
    HICON   hIcon;
    HCURSOR hCursor;
    HBRUSH  hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
} WNDCLASS;

فیلد lpszClassName که نام کلاسی هست که می خواهیم آن را Register کنیم و این نام دلخواه هست و نباید در طول زندگی یک ویندوز نام تکراری ایجاد کرد. منظور از طول زندگی یک ویندوز از زمانی هست که ویندوز بالا می آید و تا زمانی که ویندوز Shotdown نشده هست.

فیلد بعدی hbrBackground هست که همانطور که از اسمش پیداست رنگ زمینه پنجره مورد نظر را تغییر می دهد. به طور مثال برای تنظیم رنگ زمینه به رنگ خاکستری، همانند بقییه پنجره ها از COLOR_BTNFACE استفاده می کنیم که مقدار عددیش برابر 15 هست.

فیلد دیگری داریم با نام lpfnWndProc که اشاره گری هست که می تواند به تابع اشاره کند، پس تابعی به نام DefWindowProc را به آن می دهیم این تابع Message هایی رو که به پنجره ارسال می شود را Handle می کنه، البته اگر بخواهیم Message ها را خودمان Handle کنیم باید تابع مشابه به DefWindowProc ایجاد کنیم، هنگامی که برای پنجره Messageیی ارسال میشه داخل این تابع می آید و ما می توانیم Message ها را خودمان Handle کنیم.

حال که این ها را تنظیم کردیم (یا ویندوز تنظیم کرد) با استفاده از تابع RegisterClass آن را Register می کنیم.

خوب حالا باید از حاصل دسترنج خودمون استفاده کنیم، یعنی یک نونه از کلاسی که Register کردیم ایجاد کنیم و به کاربر نشان دهم.
پس برای این کار از تابع CreateWindowEx استفاده می کنیم.
پارامترهای این تابع به شکل زیر هستند :

کد:
HWND CreateWindowEx(

    DWORD dwExStyle, // extended window style
    LPCTSTR lpClassName, // pointer to registered class name
    LPCTSTR lpWindowName, // pointer to window name
    DWORD dwStyle, // window style
    int x, // horizontal position of window
    int y, // vertical position of window
    int nWidth, // window width
    int nHeight, // window height
    HWND hWndParent, // handle to parent or owner window
    HMENU hMenu, // handle to menu, or child-window identifier
    HINSTANCE hInstance, // handle to application instance
    LPVOID lpParam // pointer to window-creation data
   );

پارامتر lpClassName را باید نام همان کلاسی را بدهیم که قبلا Register کردیم.

lpWindowName هم نام پنجره ایجاد شده را می دهیم، که دلخواه می باشد و نباید این پارامتر را با Text یا Caption اشتباه کنیم.

dwStyle را برابر با WS_OVERLAPPEDWINDOW می کنیم که مقدار عددیش برابر است با CF0000

پارامترهای x و y هم مختصاتی هست که می خواهیم پنجره به نمایش در آید.

پارامتر های nWidth و nHeight در واقع Size پنجره ای است که می خواهیم ایجاد کنیم.

hWndParent در واقع Handle شی پدر هست مثلا اگر BUTTON را خواستیم ایجاد کنیم و روی یک فرمی قرار دهیم، فرم همان Handle پدر هست که می توان آن را 0 قرار داد به این منظور که خود این شی پدر هست.


lpParam را برابر nil یا null کنید.

با اجرای این تابع خواهید دید پنجره ای باز می شود که ما آن را Form می نامیم!

بقیه پارامترهای توضیح داده نشده این تابع را برابر 0 قرار دهید. برای اطلاعات بیشتر از پارامترهای توضیح داده نشده کافیست نام تابع یا Structure مورد نظر را جستجو کنید تا اطلاعات بسیار خوبی را پیدا کنید.

نکته جالب اینکه حالا متوجه خواهیم شد که چرا تاکید داشتم BUTTON، EDIT، COMBOBOX، LISTBOX، STATIC همه پنجره هستند چراکه روند کار ایجاد این پنجره ها شبیه به مراحلی هست که توضیح دادم و فقط فیلد lpfnWndProc از Structure به نام WNDCLASS را برابر تابع مورد نظر خود کرده اند و مثلا برای BUTTON پیامهای آن را Handle کردند و پنجره ای که ما می بینیم را ایجاد می کنند و آن را به عنوان Button می شناسیم.

منبع

براي اين پست, 1 کاربر تشکر کرده است
taban
خارج شده است
صفحه: [1]
 

تگ ها:


 
پرش به :