قسمت دوم این مقاله
گفتیم 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 می شناسیم.
منبع