http://www.vckbase.com/document/viewdoc/?id=1178
相信很多人在VC下开发程序的时候大多都会采用基于对话框的开发吧,我也不例外,大多数的小型测试程序没有必要开发基于文档/视图的结构来测试,只要使用一些基本的对话框程序就可以达到这个目的 。
但是在开发基于对话框的程序时,要使用到一些 Spy++ 的功能检测的时候,就会出现一些问题。什么问题呢?当我使用 Spy++ 去检测一个对话框的窗口类 时,并想得到一个对话框的窗口类,以便我在使用钩子的时候可以指定一个对话框进行 hook,但是结果出乎我意料之外 ,对话框的窗口类不是我在注册时所指定的对话框窗口类名。其类名是 "#32770(Dialog)",这是一个MFC自动为基于对话框的程序产生的默认窗口类 ,所有的基于MFC所产生的对话框程序都使用这一个默认类名。即是说,我在使用一个基于对话框的程序时,无论多少个对话框产生,它们的类名都会是 "#32770(Dialog)",这样我在打开对话框进行测试时,无法指定我需要的对话框的句柄。
但是,当指定一个对话框的窗口标题的时候,这个对话框的名柄就可以找到了:
HWND hWnd = MULL; hWnd = FindWindow( "#32770",lpszWindowName ); _ASSERT( hWnd != NULL ); //其中 lpszWindowName 是对话框的窗口标题目。这种方法也有一定的缺点,就是一个对话框的标题不确定时会怎么样,或对话框的标题在运行过程中要动态改变呢?这样根本无法保证所找到 的句柄就是所需要的句柄。我采取的方法就是在对话框的产生过程中为对话框指定一个唯一的窗口类,这样就可以找到所想要的指定句柄,而不必与其它的对话框混淆。
HWND hWnd = MULL; hWnd = FindWindow( lpszClassName, NULL ); _ASSERT( hWnd != NULL ); //其中 lpszClassName 是对话框的窗口类名。那怎么样实现自已定制的对话框类呢! 看过《深入浅出MFC》的读者一定会想到,在重载 CWinApp 的 InitInstance()函数中进行修改 ,不错,确实要在这儿修改。
// 在派生类的 InitIntace() 中 BOOL CLimitDlgInstanceApp::InitInstance() { WNDCLASS wc; // Get the info for this class。 // #32770 is the default class name for dialogs boxes。 ::GetClassInfo(AfxGetInstanceHandle(), "#32770", &wc); // Change the name of the class。 wc。lpszClassName = "MyPrivateClassName"; // Register this class so that MFC can use it。 AfxRegisterClass(&wc); // ...... }这里采用的方法是在产生注册窗口时,将注册窗口的窗口类名修改。再重新注册窗口类,一切看来很顺利,也不是非常难的操作,但是一切都如你预期一样么。很不辛,你再打开 Spy++ 观察窗口的时候 ,仍是 "#32770(Dialog)"。
// 在派生类的 InitIntace() 中 BOOL CLimitDlgInstanceApp::InitInstance() { WNDCLASS wc; // Get the info for this class。 // #32770 is the default class name for dialogs boxes。 ::GetClassInfo(AfxGetInstanceHandle(), "#32770", &wc); // Change the name of the class。 wc。lpszClassName = "MyPrivateClassName"; // Register this class so that MFC can use it。 AfxRegisterClass(&wc); // ...... }其中 ::GetClassInfo 保证了即使你的资源文件在不同的 Dll 中也能正确得到 HINSTANCE 跟着就是要修改资源文件了,用文本编辑器打开 rc 文件 ,加上" ClASS 类名 "如下图所示: