Bài toán "Viết một ứng dụng, có khả năng thông báo xác nhân khi người dùng thoát ứng dụng"
Nếu anh em đã học API thì có thể sẽ thấy bài này ko khó phải nói là dễ, nhưng mà có nhiều vấn đề phải nói ở đâ.
Nhìn vào bài toán ban đầu ý tưởng thoáng đến sẽ là đặt cái MessageBox trong cái WM_DESTROY, để kiểm tra người dùng có muốn thoát ứng dụng ko
Mã:
case WM_DESTROY:
int Thoat;
Thoat = MessageBox(hWnd, _T("Ban co muon thoat chuong trinh khong ???"), _T("Thong Bao"), MB_OKCANCEL);
if(Thoat == IDOK)
PostQuitMessage(0);
else
return 0;
break;
Kết quả nhận đc là khi bấm thoát chương trình, 1 cái MesageBox sẽ hiện lên hỏi bạn có muốn thoát chương trình không. Nếu bạn chọn OK, thì ko có gì xảy ra, còn nếu chọn NO, thì chương trình cũng tự mất tiêu !!! . chạy 1 lần nữa thì ứng dụng báo là đang chạy xin tắt cái cũ đi, vào TaskManager thì thấy ứng dụng vẫn còn lù lù đó chưa tắt. Tại sao vậy
Vì khi bạn đã nhận đc WM_DESTROY có nghĩa là ít nhiều chương trình đã đc giải phóng vùng nhớ , chỉ còn chờ PostQuitMessage() cho 1 cái WM_QUIT để nó tắt cái vòng lặp và tắt luôn cái ứng dụng
Mã:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_C4W_P1_BT3_EVENT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_C4W_P1_BT3_EVENT));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
Nếu nhận đc WM_QUIT thì GetMessage ở trên sẽ trả về 0 và thoát khỏi while và thoát ứng dụng
Vậy tóm lại ko thể đặt cái MessageBox ở WM_DESTROY vì lúc nhận đc nó thì ứng dụng đã "dọn dẹp sạch sẽ, giấy nháp vào sọt rác" chỉ chờ "mở cửa ra khỏi công ty", mà đã "dọn dẹp" rồi thì làm sao mà để lại nguyên si như ban đầu đc [IMG]images/smilies/11.gif[/IMG]
You can use the DestroyWindow function to destroy a window. Typically, an application sends the WM_CLOSE message before destroying a window, giving the window the opportunity to prompt the user for confirmation before the window is destroyed. A window that includes a window menu automatically receives the
WM_CLOSE message when the user clicks
Close from the window menu. If the user confirms that the window should be destroyed, the application calls
DestroyWindow. The system
sends the WM_DESTROY message to the window after removing it from the screen. In response to
WM_DESTROY, the window saves its data and frees any resources it allocated. A main window concludes its processing of
WM_DESTROY by calling the PostQuitMessage function to quit the application.
Xem thêm : http://msdn2.microsoft.com/en-us/library/ms632598(VS.85).aspx
Giải pháp cho việc này là để cái MessageBox vào WM_CLOSE. Vì khi bạn bấm Close 1 ứng dụng nó sẽ đi theo thứ tự
WM_CLOSE > DestroyWindow() > WM_DESTROY > PostQuitMessage() > WM_ QUIT
Xem thêm ở đây
http://www.daniweb.com/forums/thread43819.html
vậy phải chận nó trước khi nó gọi DestroyWindow để "dọn dẹp"
Mã:
case WM_CLOSE:
int Thoat;
Thoat = MessageBox(hWnd, _T("Ban co muon thoat chuong trinh khong ???"), _T("Thong Bao"), MB_OKCANCEL);
if(Thoat == IDCANCEL)
{
return 0;
}
else
DestroyWindow(hWnd); // Chỉ "dọn dẹp" khi người dùng click vào OK
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
Ok kết quả thật là mĩ mãn, nhưng vấn đề mắc phải là khi nhấp vào nút Exit thì nó đi luôn ko hỏi han gì cả khác với việc nhấn vào nút X hay Alt + F4, tìm cái code chỗ Exit của menu thì thấy nó gọi luôn DestroyWindow(), khi đó nó sẽ đi tới bước WM_DESTROY mà ko qua bước WM_CLOSE.
Giải pháp : Ép nó phải qua WM_CLOSE ko cho DestroyWindow()
Mã:
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
//DestroyWindow(hWnd);
SendMessage (hWnd, WM_CLOSE, 0, 0) ; // Gửi Message kêu nó phải thoát bằng cách qua WM_CLOSE
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
Theo một số người khác nói thì WM_QUIT nằm ở khoảng giữa WM_DESTROY và WM_CLOSE (thật vậy sao [IMG]images/smilies/daydreaming.gif[/IMG])
http://www.3dbuzz.com/vbforum/showthread.php?t=135789
Nên tui đặt câu hỏi : Tại sao ko đặt MessageBox chận nó lại hỏi nó thử xem
Mã:
case WM_QUIT:
MessageBox(hWnd, _T("WM_QUIT"), _T("Thong Bao"), MB_OK);
break;
Nhưng cho dù bạn có đặt BreakPoint để Debug thì ko cách chi vào đc. Do
The WM_QUIT message indicates a request to terminate an application and is
generated when the application calls the PostQuitMessage function. It causes the GetMessage function to return zero.
Remarks
The WM_QUIT message is not associated with a window and therefore will
never be received through a window's window procedure. It is retrieved only by the GetMessage or PeekMessage functions.
Xem thêm : http://msdn2.microsoft.com/en-us/library/ms632641(VS.85).aspx
Vậy là bạn ko thể chận nó đc vì khi nó xuất hiện thì nó đã làm vòng While bị vỡ (GetMessage trả về 0) và thoát chương trình.
Và do câu nói "generated when the application calls the PostQuitMessage" nên tôi nghĩ chính xác nó phải nằm cuối chứ ko nằm giữa [IMG]images/smilies/2.gif[/IMG]
Tóm lại :
WM_CLOSE nhận đc khi người dùng close chương trình (Alt + F4 hay là click vào dấu x)
WM_DESTROY nhận đc khi DestroyWindow(), khi đó dữ liệu đã đc xóa, chỉ còn đợi PostQuitMessage(0) post WM_QUIT để Window gỡ nó ra khỏi hàng đợi, nếu bỏ qua bước PostQuitMessage , thì chương trình sẽ vẫn còn chạy trong TaskManager
WM_QUIT xảy ra sau khi PostQuitMessage, ko nhận đc trong WndProc, chỉ nhận đc khi GetMessage trả về 0, nó làm cho vòng lặp nhận thông điệp ngưng trước khi thông điệp đến đc WndProc của ứng dụng
WM_CLOSE > DestroyWindow() > WM_DESTROY > PostQuitMessage(0) > WM_ QUIT
-------------------------------------------------------
Vấn đề này tuy ko lớn lắm nhưng cũng đưa ra để mọi người cùng thảo luận xem có phải nó như thế ko. Mọi người xem thử nếu có sai xót hay có gì khác thì nhắn liền để anh em cùng biết cùng thảo luận tiếp về WM_QUIT, WM_DESTROY, WM_CLOSE . Cái này thì tui thấy 1 số sách tui đã xem qua, nó ko nói kĩ phần này lắm nên tức quá phải mò cho bằng đc
Cái này ko khó để code, nhưng cũng để luôn nếu ai muốn tham khảo thử
MessageBox nằm trong WM_DESTROY, ứng dụng vẫn còn trong TaskManager khi đã tắt :
http://www.ziddu.com/downloadlink.ph...hkZSnZqugmZSm9
MessageBox nằm trong WM_CLOSE :
http://www.ziddu.com/downloadlink.ph...JGlaaeam5w%3D7
View more random threads:
Hiện nay trên thị trường xuất hiện rất nhiều loại thuốc bôi tăng kích thước dương vật được lăng xê là có khả năng làm tăng kích cỡ dương vật của cánh mày râu. Tuy nhiên không phải loại thuốc nào cũng...
Thuốc tăng kích thước chim có tác...