win32 CreateDialog和DialogBox

INT_PTR DialogBox(          HINSTANCE hInstance,
    LPCTSTR lpTemplate,
    HWND hWndParent,
    DLGPROC lpDialogFunc
);
這個函數根據對話框資源,創建一個模式對話框,這個對話框應該用EndDialog來結束。


hInstance 當前應用程序實例句柄。
lpTemplate 標識對話框模板資源,有兩種使用方式:一種是把對話框模板的ID強制轉爲LPCTSTR,一種可以使用MAKEINTRESOURCE宏得到標識ID。
hWndParent 父窗口的句柄。
lpDialogFunc 對話框消息處理函數。


HWND CreateDialog(          HINSTANCE hInstance,
    LPCTSTR lpTemplate,
    HWND hWndParent,
    DLGPROC lpDialogFunc
);
這個函數根據對話框資源,創建一個非模式對話框,這個對話框應該用DestroyWindow來結束。
函數的參數跟上面的DialogBox用法相同。




模式對話框一般是在棧中生成的,所以EndDialog可能只是隱藏窗口,並沒有銷燬,當模式對話框對應的對象離開生命區時即銷燬對話框。非模式的對話框一般在堆中,所以要主動用DestroyWindow銷燬它。
DialogBox 函數自己處理消息循環(這個消息循環在user32.dll裏面維護,看不到)且在對話框關閉後函數纔會返回(返回值是EndDialog的第二個參數, 所以可以用EndDialog的第二個參數來標識子控件的ID),而CreateDialog函數調用了CreateWindowEx函數來創建窗口並立 即返回,之後這個窗口使用主窗口的消息循環(即這個窗口產生的消息可能直接發給這個窗口的處理函數,也可能進入主窗口的消息循環)。


不管是模式的還是非模式的對話框,對於不希望處理的消息,都不應該調用DefWindowProc來處理(否則會有問題),因爲系統會主動對這些消 息進行處理。對於不希望處理的消息,程序要做的只是return FALSE即可,而對於處理過的消息,則應該return TRUE。
這種情況跟主窗口的處理不同。主窗口對不希望處理的消息也要調用DefWindowProc來處理,而每個消息處理分支的返回值是無關緊要的(不像對話框那樣一定要返回TRUE或FALSE那樣)。


非模式對話框跟主窗口使用同一個消息循環,而因爲非模式對話框的消息會被系統主動調用這個對話框的處理函數來處理,所以在消息循環中不應該再對這個消息進行轉換和分發,可以把消息循環改成這樣:
 // 主消息循環:
 while (GetMessage(&msg, NULL, 0, 0))
 {
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   // 不是非模式對話框g_hFlashWnd的消息才分發
   if ( !IsDialogMessage( g_hFlashWnd, &msg ) ) 
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
   
  }
 }




CreateDialog會發出WM_INITDIALOG消息。


一些例子代碼: 
/// 非模式對話框消息處理函數
BOOL __stdcall FlashWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
 switch ( msg )
 {
 case WM_INITDIALOG:
  break;
  
 case WM_PAINT:
  break;


 case WM_LBUTTONDOWN:
  DestroyWindow( hWnd );
  break;


 default:
  return FALSE;  // 沒處理過的消息
 }


 return TRUE; // 處理過的
}


///創建一個非模式對話框
g_hFlashWnd  = CreateDialog( hInst, MAKEINTRESOURCE(IDD_FLASH), hWnd, (DLGPROC)FlashWndProc );
ShowWindow( g_hFlashWnd, SW_SHOW );
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章