1:问题:我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?
解答:把“delete this”加到PostNcDestroy中。这主要用在需要自动删除对象的场合。
2:问题:为什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?
解答:OnNcDestroy只被已建立的窗口调用。如果建立窗口失败(如PreCreateWindow), 则没有窗口处来发送WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除, 在OnNcDestroy后,甚至在窗口建立失败之后调用的。
3:关于DIADOG背景图象在CODEGURU看到一个MDI CLIENT以位图为背景的例子,受到启发,在DIALOG中相似地模仿了以下,效果很好。主要要点是处理背景擦除消息时在DIALOG CLIENT区域画位图,代码如下:
BOOL CBmpbgDlg::OnEraseBkgnd(CDC* pDC){CRect rect;GetClientRect(&rect); BITMAP bm;CDC dcMem;m_pBmp->GetObject(sizeof(BITMAP),(LPVOID)&bm);dcMem.CreateCompatibleDC(NULL);CBitmap* pOldBitmap = dcMem.SelectObject(m_pBmp);for (register int nX=0;nXBitBlt(nX,nY,bm.bmWidth,bm.bmHeight,&dcMem,0,0,SRCCOPY);dcMem.SelectObject(pOldBitmap); return TRUE;}
4:怎么用VC++5.0来编写图像打印程序,我的程序是基于对话框的
void CXXXX::OnBtnPrint() {CPrintDialog cprtDlg(FALSE);DOCINFO diPrint;CString csPortName, csAppName, csPrintError;CDC dc;CSize size; csAppName.LoadString(IDS_APP_NAME);csPrintError.LoadString(IDS_ERROR_PRINT); if ( cprtDlg.DoModal() == IDOK ) {// Retrieve printer portmemset(&diPrint, 0, sizeof(DOCINFO));diPrint.cbSize = sizeof(DOCINFO);diPrint.lpszDocName = csAppName;csPortName = cprtDlg.GetPortName(); diPrint.lpszOutput = csPortName; // Attach to printer’s dcdc.Attach( cprtDlg.GetPrinterDC() );dc.m_bPrinting = TRUE; // 此处取纸的尺寸,单位毫米size.cx = dc.GetDeviceCaps(HORZSIZE);size.cy = dc.GetDeviceCaps(VERTSIZE); if ( dc.StartDoc(&diPrint) == -1 ) {AfxMessageBox(csPrintError);dc.Detach();return;} // Start to print contentPrintContent(&dc); dc.EndDoc();dc.Detach();}} void CXXXX:rintContent(CDC * pDC){// :-) 与OnDraw()函数是何等的相似 CFont NewFont, *pOldFont;CString sOut = "我爱你,中国"; pDC->SetMapMode(MM_LOMETRIC); // set map mode to 0.1mm//打印输出最好使用物理坐标,而不是设备坐标,因为不同的打印机DPI不同 NewFont.CreateFont( 40, 0, 0, 0,FW_HEAVY, 0, 0, 0, DEFAULT_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "宋体");pOldFont = pDC->SelectObject(&NewFont);pDC->TextOut(100, -100, sOut);//注意坐标系为笛卡儿坐标系,如果你想看到输出结果,Y坐标一定要为负数pDC->SelectObject(pOldFont);NewFont.DeleteObject();}
5:怎样改变对话框中控件的字体下面的例子说明了怎样改变一个edit控件的字体.当然也可以将此方法运用于对话框中的其他控件. 在对话框类的头文件中加入下面语句:
CFont m_Font; 在对话框类的重载函数OnInitDialog()中创建字体并设置edit控件的字体 m_Font.CreateFont(-11,0,0,0,100,FALSE,FALSE, 0,ANSI_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, FF_SWISS,"Arial"); CEdit * pEdit; pEdit = (CEdit *)GetDlgItem(IDC_MYEDIT); pEdit->SetFont(&m_Font,FALSE); 在对话框类的析构函数中Delete 字体. m_Font.DeleteObject();
6: 如何在对话框中加入菜单这个实在太简单了,简单地我都不好意思说。 首先创建一个菜单,然后打开对话框属性编辑器。 在general页有一个Menu右边有一个组合框看见了没。 点它然后从中选择一个菜单,大公告成。 (2)发信人: fwg (g1234), 信区: Visual 7: 如何居中系统对话框和性属框?【 在 dragonlu (button) 的大作中提到: 】 : 可以试试用一线程用设置事件的方法监视对话框,当对话框执行时 : 用GETLASTPOPUP判断并得出窗口句柄,设置即可 :
※ 来源:·BBS 一网情深站 bbs.szptt.net.cn·[FROM: ] 已解决了,感谢 Dragonlu 给予提醒,不过尚不必如设置线程般复杂。 请指正 另:欢迎试用光碟资源管理器 www4.netease.com/~forxm/Cdrc32.htm
LRESULT CALLBACK NewPropSheetProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { WNDPROC lpPrevPropSheetProc= (WNDPROC)GetWindowLong( hWnd,GWL_USERDATA); if( msg==WM_SHOWWINDOW ) { RECT r; GetWindowRect(hWnd, &r ); int w=r.right-r.left; int h=r.bottom-r.top; GetWindowRect( GetDesktopWindow(), &r); MoveWindow(hWnd, (r.right-w)/2, (r.bottom-h)/2, w,h,FALSE); //set prev proc SetWindowLong( hWnd,GWL_WNDPROC, (LONG)lpPrevPropSheetProc ); } if( lpPrevPropSheetProc ) return CallWindowProc( lpPrevPropSheetProc,hWnd,msg,wParam,lParam); else return FALSE; } int CALLBACK CenterPropSheetProc( HWND hwndDlg, UINT uMsg,LPARAM lParam) { if( uMsg==PSCB_INITIALIZED ) { //here MoveWindow does not work SetWindowLong( hwndDlg,GWL_USERDATA, GetWindowLong( hwndDlg,GWL_WNDPROC) ); SetWindowLong( hwndDlg,GWL_WNDPROC, (LONG)NewPropSheetProc ); } /* else if( uMag==PSCB_PRECREATE ) { //here settings of x,y,cx,cy //or DS_CENTER do not work //请高手解释 DS_CENTER 为何不起作用 } */ return 1; } void ShowPropertySheet() { PROPSHEETHEADER psh; ... psh.pfnCallback =CenterPropSheetProc; ... } UINT CALLBACK OFNCenterProc( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg) { case WM_INITDIALOG: { //here MoveWindow does work somehow, //but height of window is not set properly. //And notes it’s this window’s parent window HWND hp=GetParent(hdlg); SetWindowLong( hp,GWL_USERDATA, GetWindowLong( hdlg,GWL_WNDPROC) ); SetWindowLong( hp,GWL_WNDPROC, (LONG)NewPropSheetProc ); } break; } return FALSE; } void ShowSystemDlg() { OPENFILENAME ofn; ... ofn.lpfnHook=OFNCenterProc; ... }
8:实现Dialog的Menu中最近使用文件机制 l 如何启动Dialog的Command Update机制? 重载Cdialog的WM_INITMENUPOPUP, 修改使用 void CFrameWnd::OnInitMenuPopup (CMenu* pMenu, UINT, BOOL bSysMenu) 中的source code,启动Command Update机制 l 如何实现Dialog的Menu中最近使用文件机制? 最近使用文件机制是用CWinApp的Command Update机制和以下两个消息处理的: ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1, OnUpdateRecentFileMenu) ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1,ID_FILE_MRU_FILE16, OnOpenRecentFile) void CWinApp::OnUpdateRecentFileMenu(CCmdUI* pCmdUI) { ASSERT_VALID(this); if (m_pRecentFileList == NULL) // no MRU files pCmdUI->Enable(FALSE); else m_pRecentFileList->UpdateMenu(pCmdUI); } / // MRU file list default implementation BOOL CWinApp::OnOpenRecentFile(UINT nID) { ASSERT_VALID(this); ASSERT(m_pRecentFileList != NULL); ASSERT(nID >= ID_FILE_MRU_FILE1); ASSERT(nID GetSize()); int nIndex = nID - ID_FILE_MRU_FILE1; ASSERT((*m_pRecentFileList)[nIndex].GetLength() != 0); TRACE2("MRU: open file (%d) ’%s’.", (nIndex) + 1, (LPCTSTR)(*m_pRecentFileList)[nIndex]); if (OpenDocumentFile((*m_pRecentFileList)[nIndex]) == NULL) m_pRecentFileList->Remove(nIndex); return TRUE; } 因为Dialog没有文档对象,所以需要重写OnOpenRecentFile.
9、如何创建和使用无模式对话框 MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几 个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用 ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的: 模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用 CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel 调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。
void CSampleDialog : : OnOK ( ) { // Retrieve and validate dialog data . if (! UpdateData (TRUE) ) { // the UpdateData rountine will set focus to correct item TRACEO (" UpdateData failed during dialog termination .") ; return ; } //Call DestroyWindow instead of EndDialog . DestroyWindow ( ) ; } void CSampleDialog : : OnCancel ( ) { //Call DestroyWindow instead of EndDialog . DestroyWindow ( ) ; } 其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。 void CSampleDialog : : PostNcDestroy ( ) { // Declete the C++ object that represents this dialog . delete this ; } 最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放, 要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明了应用程序是如何创建无模式对话的: void CMainFrame : : OnSampleDialog ( ) { //Allocate a modeless dialog object . CSampleDilog * pDialog =new CSampleDialog ; ASSERT_VALID (pDialog) ; //Create the modeless dialog . BOOL bResult = pDialog —> Creste (IDD_IDALOG) ; ASSERT (bResult ) ; }
10、如何在对话框中显示一个位图 这要归功于Win 32先进的静态控件和Microsoft的资源编辑器, 在对话框中显示位图是很容易的, 只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。
11、如何改变对话或窗体视窗的背景颜色 调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。 BOOL CSampleApp : : InitInstance ( ) { … //use blue dialog with yellow text . SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ; … } 需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。 首先,给对话基类增加一人成员变量CBursh : class CMyFormView : public CFormView { … private : CBrush m_ brush ; // background brush … } ; 其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。 CMyFormView : : CMyFormView ( ) { // Initialize background brush . m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) ) } 最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。 HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor ) { // Determine if drawing a dialog box . If we are , return +handle to //our own background brush . Otherwise let windows handle it . if (nCtlColor = = CTLCOLOR _ DLG ) return (HBRUSH) m_brush .GetSafeHandle ( ) ; return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor ); } 12:如何获取一个对话控件的指针 有两种方法。其一,调用CWnd: : GetDlgItem,获取一个CWnd*指针调用成员函数。下例调用GetDlgItem,将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl : : SetPos 函数: BOOL CSampleDialog : : OnInitDialog ( ) { CDialog : : OnInitDialog ( ) ; //Get pointer to spin button . CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem (IDC_SPIN) ; ASSERT _ VALID (pSpin) ; //Set spin button’s default position . pSpin —> SetPos (10) ; return TRUE ; } 其二, 可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签,然后选择Add Variable …按钮。如果在对话资源编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对话。 我做了一个基于对话框的应用程序,上面有个按钮,他向windows发送一个连续循环,但在这个循环中它又要响应一些windows消息(如最小化,关闭)我该怎样办? void CMyDialog::OnClickButton( ){ for ( ;;) { MSG msg; while(PeekMessage(&msg, NULL, 0, 0,PM_NOREMOVE)) { if (msg.message == WM_QUIT) {// ..... return; } GetMessage(&msg,NULL,0,0); TranslateMessage(&msg); DispatchMessage(&msg); } // ... other }}13:怎样使Dialog接受OnKeyDown键盘消息答:重载PreTranslateMessage函数如下 CMyDialog:reTranslateMessage(MSG *pMsg) { if(pMsg->message == WM_KEYDOWN) { int virtkeycode = (int)pMsg->wParam; //do your stuff according the key hit } // if no keystroke check if the message will be handled by our dialog if(IsDialogMessage(pMsg)) return TRUE; else return CWnd:reTranslateMessage(pMsg);}