modeless dialog(转)

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);}

你可能感兴趣的:(Code)