2011-03-10 46 views
0

我有一个相当大的应用程序,显示许多不同的MFC CDialog派生的对话框窗口。所有的对话都是由中央功能类似于这样显示:拦截CDialog创建

void ShowDialog(CDialog& dlg) 
{ 
    dlg.DoModal(); 
} 

现在我需要基本调用一个函数在每一个对话框的OnInitDialog方法。它在技术上并不需要在OnInitDialog中,但最好在对话框可见之前。

蛮力方法是通过代码并找到每个最后一个对话框,并将函数调用添加到OnInitDialog方法(如果它有一个,如果它没有,则添加一个)。但它似乎必须有一个更优雅的方式...

请注意,dlg实际上不是一个CDialog,但它是从它派生的东西。

任何想法,技巧或黑客?我没有修改消息映射,但希望找到更干净/更安全的东西。

回答

-1

原来这是很容易做到:

HHOOK gPrevHook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookProc, NULL, myGUIThreadID); 


LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    if(NULL != wParam) 
    { 
     CWPRETSTRUCT* pS = (CWPRETSTRUCT*)lParam; 
     if(WM_INITDIALOG == pS->message) 
      CallFuncOnWindow(pS->hwnd); 
    } 

    return CallNextHookEx(gPrevHook, nCode, wParam, lParam); 
} 

可能不适合高性能应用做的事,但对于东西是一个简单的GUI它完美的作品。无需更改其他代码。

+0

官方称此为“技术性债务” – 2011-03-12 21:55:55

+0

这简直令人惊讶。以正确的方式做到这一点会更快!你所要做的只是在类上使用正则表达式。* CDialog并用CMyCommonAncestor替换CDialog。 1小时绝对上衣。而且你将永远受益。 – 2011-03-12 22:02:53

+0

除了不会处理所有没有实现OnInitDialog的对话框。它不会处理已有基类的对话框,并在它们的OnInitDialog中调用Base :: OnInitDialog。任何错过的案例都会是bug。这是7行代码,不会错过任何东西,不会依赖人类记住从基类中派生将来的代码等。如果这是一个“拦截框架”,那么将会有关于它的文章:) – DougN 2011-03-15 18:59:35

1

如果你有一个共同的祖先对所有对话,你似乎暗示你有,那么你可以简单地把代码放在共同的祖先在你选择的合适的位置。例如OnInitDialog()是虚拟的。

+0

CDialog的是唯一的共同祖先:( – DougN 2011-03-10 19:56:16

+1

@Doug将一个共同的祖先呢。 – 2011-03-10 19:56:59

+0

这不是从蛮力“找到所有的OnInitDialog”的方法非常不同。我希望这样的事情重定向到WM_INITDIALOG一个单独的函数(钩子)或其他一些技巧,所以我不必更改所有其他代码 – DougN 2011-03-10 21:48:37