VC++编程常见问题解答二十一 问:如何使一个按钮Disable? 我使用下面代码来Disable一个为ID_BUTTON的按钮,为什么会没有变化. GetDlgItem(IDC_BUTTON)->EnableWindow(FALSE); 答:CWnd类中的EnableWindow函数用来Enable或Disable一个窗口类的对象,因为 CButton类继承于类CWnd,所以你可以使用来操作一个按钮. Enable一个基于窗口类的对象可以用以下代码: pWnd->EnableWindow(TRUE); Disable一个对象可用 pWnd->EnableWindow(FALSE); 其中pWnd为一个指向窗口对象的指针,VC++中消息WM_ENABLE告诉窗口它正在 Disable或Enable,但它并不能使一个窗口Enable或Disable. 问:怎样从MFC扩展动态链结库(DLL)中显示一个对话框? 问:我在过去的几天中试着在DLL中定义的函数中显示一个对话框,可是已经在DLL 中定义好的对话框资源,在常规DLL调用时,我可以正常的显示出来,为什么在扩展 DLL中同样的资源我却不能显示. 答:当你在DLL中使用资源时,有些小细节需要注意,首先,在DLL运行时,必须保存 DLL的实例,可以通过AfxInitExtensionModule static AFX_EXTENSION_MODULE extensionDLL; extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) { if (dwReason == DLL_PROCESS_ATTACH) { // Extension DLL one-time initialization if (!AfxInitExtensionModule(extensionDLL, hInstance)) return false; } return(true); } 然后,每次使用DLL资源时,你必须改变资源的句柄,使其指向DLL,并保存exe的资源 ,以便以后正确恢复 void get_DLL_resource(void) { /* this function changes the resource handle to that of the DLL */ //这个函数改变资源句柄使其指向DLL if (resource_counter == 0) { save_hInstance = AfxGetResourceHandle(); AfxSetResourceHandle(extensionDLL.hModule); } resource_counter++; } 接着你需要其它函数来恢复资源句柄 void reset_DLL_resource(void) { /* this function restores the resource handle set by 'get_DLL_resource()' */ if (resource_counter > 0) resource_counter--; if (resource_counter == 0) AfxSetResourceHandle(save_hInstance); } 接下来一点非常重要,只要有可能就必须恢复资源句柄,否则,你将会遇到许多问 题.原因是可执行文件必须重画工具条等等,比如说,如果用户移动DLL的对话框,如 果资源句柄仍然为DLL的资源,程序就崩溃了,我发现最好恢复句柄的时机在对话框 的OnInitDialog()中,这时对话框的模板等已经读出了. 问:想隐藏用户界面怎么办? 问:我编了一个小巧而有趣的工具,当用户使用时我不想让它显示出任何用户界 面。听听各位有办法可将视关闭。 答:你可以注册一个新的窗口类型,它拥有除了WS_VISBLE属性外的任何属性,类 似CFrameWnd,在PreCreateWindow方法中实现。另外,你能在OnCreate方法中通 过设置m_nCmdShow为SW_HIDE来实现,具体方法如下: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // hide our app AfxGetApp()->m_nCmdShow = SW_HIDE; return 0; } 问:如何实现SDI与MDI的转换? 问:我想将一个编好的SDI应用程序转换为MDI,很明显要有多处的改变。 答:你可以这样做:建立一个继承于CMDIChidWnd的类,不防设为CChldFrm.在CWinApp中作如下变化。 InitInstance() { ...... //instead of adding CSingleDocTemplate // Add CMultiDocTemplate. pDocTemplate = new CMultiDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CSDIDoc), RUNTIME_CLASS(CChldFrm), // For Main MDI Frame change this frame window from // CFrameWnd derivative ( i.e. CMainFrame ) // to your CMDIChildWnd derived CChldFrm. RUNTIME_CLASS(CSDIView)); // After this it is required to create the main frame window // which will contain all the child windows. Now this window is // what was initially frame window for SDI. CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; ..... } 在从CMDIFrameWnd中继承的类CMainFrame代替CFramWnd后,所有的类都将从 CMDIFrame继承,而不是CFrameWnd,编译运行后你就会发现程序已经从SDI变 换到MDI。 注意:在CMainFram中必须将构造函数从private改为public.否则会出错。