2011-04-01 76 views
1

我一直使用標準方法來包裝對話框過程,通過在類中使用靜態對話框過程以及稍後派生的純虛擬對話框過程。這很好,但我有一些設計問題。考慮我的靜態對話過程的定義:包裝對話框過程

INT_PTR __stdcall ModalDialog::router(HWND dlg, UINT msg, WPARAM wp, LPARAM lp) 
{ 
    ModalDialog *thisPtr = 0; 

    if (msg == WM_INITDIALOG) 
    { 
     thisPtr = reinterpret_cast< ModalDialog *>(lp); 

     ::SetWindowLongPtr(dlg, DWLP_USER, reinterpret_cast<LONG_PTR>(thisPtr)); 

     thisPtr->_dlg = dlg; 

     return static_cast<INT_PTR>(TRUE); 
    } 
    else 
     thisPtr = reinterpret_cast< ModalDialog *>(::GetWindowLongPtr(dlg, DWLP_USER)); 

    if (thisPtr) 
     //the virtual procedure from which to derive from 
     return thisPtr->proc(msg, wp, lp); 
    else 
     //return false when not processing a message, look we should 
     return static_cast<INT_PTR>(FALSE); 
} 

可以說,我想添加下列虛擬方法到ModalDialog基類:

virtual bool onInitDialog(HWND dlg) = 0; 
virtual bool onCommand(HWND dlg, int high_word, int low_word) = 0; 
virtual bool onClose(HWND dlg) = 0; 

難道是所有權利,如果我放棄了虛擬對話程序,以及改變像這樣的靜:

INT_PTR __stdcall ModalDialog::router(HWND dlg, UINT msg, WPARAM wp, LPARAM lp) 
{ 
    ModalDialog *thisPtr = 0; 

    if (msg == WM_INITDIALOG) 
    { 
     thisPtr = reinterpret_cast< ModalDialog *>(lp); 

     ::SetWindowLongPtr(dlg, DWLP_USER, reinterpret_cast<LONG_PTR>(thisPtr)); 

     thisPtr->_dlg = dlg; 

     //ADDED 
     onInitDialog(dlg); 

     return static_cast<INT_PTR>(TRUE); 
    } 
    else 
     thisPtr = reinterpret_cast< ModalDialog *>(::GetWindowLongPtr(dlg, DWLP_USER)); 

    //ADDED 
    switch (msg) 
    { 
    case WM_COMMAND: 
     if (thisPtr && thisPtr->onCommand(dlg, HIWORD(wp), LOWORD(lp))) 
      return static_cast<INT_PTR>(TRUE); 
     break; 
    case WM_CLOSE: 
     if (thisPtr && thisPtr->onClose(dlg)) 
      return static_cast<INT_PTR>(TRUE); 
     break; 
    defualt: 
     return static_cast<INT_PTR>(FALSE); 

    //if (thisPtr) 
    // return thisPtr->proc(msg, wp, lp); 
    //else 
    // return static_cast<INT_PTR>(FALSE); 
} 

在基類這樣,我只需要重新定義虛擬「上......」的命令?我還注意到:: EndDialog(thisPtr - > _ dlg,0)僅適用於WM_CLOSE?我是否還需要像這樣分配thisPtr中的_dlg:thisPtr - > _ dlg = dlg?

謝謝你給予的任何幫助。

回答

2

這給你更少的靈活性 - 最好是從虛擬對話框過程中調用事件處理程序,這樣可以覆蓋單個子類的行爲。如果您希望默認調用這些「事件處理程序」以用於ModalDialog的所有子類,那麼不要使虛擬對話框過程是純虛擬的 - 也可以爲ModalDialog實現它,並從子類明確調用它。

ModalDialog::dialogProc(...) { 
    switch (...) { 
    case ...: onInitDialog(...); break; 
    } 
} 

ModalDialogSubClass::dialogProc(...) { 
    switch (...) { 
    case ...: break; 
    default: return ModalDialog::dialogProc(...); 
} 

鑑於這種情況,你可以做出決定呼籲onInitDialogdialogProc一個特定的基類的基類。

通常情況下,你要在靜態的過程做的是簡單的:

if (is first message) { 
    SetWindowLong... 
} 
((ModalDialog *) GetWindowLong())->dialogProc(); // Also for the initial message 
+0

是啊,這就是我做太多,隨時調用'GetWindowLongPtr'如果nullptr,調用'SetWindowLongPtr'無論第一條消息是。然而,這適用於我,因爲我內部使用了新的(std :: nothrow)類實例,而不是通過LPARAM傳遞,並且它可能不適用於rem45acp的方法,因爲他似乎在外部創建類並傳入指針,並且收到的第一條消息可能不是WM_INITDIALOG,它具有CreateDialogParam的數據指針。 – 2015-07-13 22:05:52