خب حالا ما پیام WM_PAINT رو برای برنامه معرفی کردیم و ارتباطمون رو با کارت گرافیک برای نوشتن روی صفحه برقرار کردیم.
و در آخر ما به یه قالب میرسیم که به این صورته:



case WM_PAINT:
(hwnd, &ps)hdc=BeginPaint
[Painting Commands]
EndPaint(hwnd, &ps);



شما با دادن دستور EndPaint محیطتون رو از حالت نادرست به درست برمیگردونید. پس با تعریف کردن WM_PAINT توابع BeginPaint و EndPaint حتما باید معرفی بشن حتی اگه توشون هیچ دستوری نباشه. در صورتی که این دو تابع نوشته نشن، محیط پنجره نادرست میمونه و به پروسیجر پیش فرض ویندوز بر میگرده. پروسیجر ویندوز محیط برنامه رو نادرست تشخیص میده. درنتیجه یه پیام WM_PAINT تو صف پیامها میذاره و تو هر ثانیه هزاران بار محیط نقاشی میشه و این چرخه تا ابد انجام میشه.


هر استراکچر PAINTSTRUCT دارای این فیلد هاست:



typedef struct tagPAINTSTRUCT
{
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
}



ویندوز با فراخوانی تابع BeginPaint این فیلد هارو پر میکنه ولی برنامه شما تنها از سه تاشون استفاده میکنه و بقیه رو ویندوز استفاده میکنه.


فیلد اول مربوط به دستگیره برنامه شما به Device Context هست که توسط تابع BeginPaint هم بازگردونده میشه.


فیلد بعدی مربوط به پاک کردن محیط برنامه اس که تو اکثر مواقع، ارزش FALSE به خودش میگیره که به این معناست که ویندوز محیط نادرست برنامه رو نقاشی کرده (که تو تابع BeginPaint این اتفاق میفته).


فیلد rcPaint یه استراکچر از نوع RECT هست. RECT خودش چهار تا فیلد داره که چپ(left)، بالا(up)، راست(right) و پایین(down) اونو تشکیل میدن. این استراکچر قسمت نادرست محیط برنامه رو نشون میده که برنامه اونجا رو دوباره نقاشی کنه.
Capture.PNG
اگر میخواین که محیط برنامتون رو بصورت دستی نادرست کنید از این تابع کمک بگیرید:


(hwnd, NULL, TRUE)InvalidateRect

همونطور که با استفاده از BeginPaint، HDC برنامه رو پر میکردیم و برنامه رو برای نقاشی آماده می کردیم و با EndPaint اونو کامل میکردیم. میتونیم از دوتابع دیگه استفاده کنیم که شباهت های زیادی به این دوتا تابع دارن:

hdc = GetDC(hwnd)
[painting commands]
ReleaseDC(hwnd, hdc)

شاید یه سوال براتون پیش اومده که نمیشه بیرون از پیام WM_PAINT و تو پیام های دیگه محیط رو نقاشی کنیم؟
با دو تابع BeginPaint, EndPaint نه، ولی با توابع GetDC ,ReleaseDC میشه چون دقیقا این دو تابع برای همین کار ساخته شدن و ما میتونیم تو پیام هایی مثل WM_KEYDOWN, WM_MOUSEMOVE, ... از اونها استفاده کنیم.
این دوتا تابع هم مثل BeginPaint , EndPaint باید با هم فراخونده شن و توی یه پیام هم باشن(یکی نباید تو یه پیام و اون یکی تو پیام دیگه ای باشه).
اما برخلاف دو تابع قبلی این تابع ها بعد از فراخونده شدن، محیط نادرست پنجره رو درست نمیکنن و باید به صورت دستی میتونیم اون رو درست کنیم.
برای درست کردن محیط پنجره برای جلوگیری از نقاشی دوباره هم میتونیم از این تابع استفاده کنیم:

ValidateRect(hwnd, NULL)