Dialog & Windows 使用技巧 (1)

摘自:http://tb.blog.csdn.net/TrackBack.aspx?PostId=658248
作者:lixiaosan
日期:04/11/2006

文章不断更新中,请访问这里

注:以下代码以一个名为CTest6Dlg的对话框类为例


1. 在任务栏隐藏对话框

    ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);


2. 使对话框为顶层窗口

        SetWindowPos(&this->wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);


3. 在运行时添加最大化,最小化按钮

    SetWindowLong(this->m_hWnd, GWL_STYLE,
                  GetWindowLong(this->m_hWnd, GWL_STYLE) |
                  WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
     UpdateWindow();



4. 使能对话框右上角关闭按钮


    在OnInitDialog中

    方法一:
       CMenu* menu = GetSystemMenu(FALSE);
       menu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED );

    方法二:
       CMenu* menu = GetSystemMenu(FALSE);
       menu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);


5. 当对话框一部分在屏幕外时,显示全部对话框

    SendMessage(DM_REPOSITION);


6. 改变鼠标外形


    添加 WM_SETCURSOR 消息映射函数

    BOOL CTest6Dlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
         SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HELP));

         return 0;
    }


7. 改变对话框背景色和文本颜色


    在CTest6App的InitInstance中添加

    SetDialogBkColor(RGB(255,0,0), RGB(0,255,0));


8. 改变对话框caption上的图标


    导入自己的图标资源到工程中,把原来ID为 IDR_MAINFRAME 的资源删除,把新的图标的ID命名为IDR_MAINFRAME


9. 在主对话框显示前,显示一个login对话框


     BOOL CTest6App::InitInstance()
     {
        //...
        int nResponse;
        CLoginDlg loginDlg;

        nResponse = loginDlg.DoModal();
        if (nResponse == IDOK)
        {
        }
        if (nResponse == IDCANCEL)
        {
               return FALSE;
        }

        CTest6Dlg dlg;
        m_pMainWnd = &dlg;
        int nResponse = dlg.DoModal();
        if (nResponse == IDOK )
        {
        }
        else if (nResponse == IDCANCEL)
        {
        }
        return FALSE;
     }

然后重载CLoginDlg对话框的哦OnOK(),在其中判断条件
void CLoginDlg::OnOK()
{
     if (条件满足)
        CDialog::OnOK();
     else
        AfxMessageBox(_T("invalid password!"));
}



10. 在对话框中添加工具栏


    方法一:添加以下代码到 OnInitDialog 中

     if ( !m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_TOOLBAR1) )
     {
        TRACE0("Failed to Create Dialog Toolbar/n");
        EndDialog(IDCANCEL);
     }

     CRect rcClientOld; // 久客户区RECT
     CRect rcClientNew; // 加入TOOLBAR后的CLIENT RECT
     GetClientRect(rcClientOld); //
     // Called to reposition and resize control bars in the client area of a window
     // The reposQuery FLAG does not really traw the Toolbar. It only does the calculations.
     // And puts the new ClientRect values in rcClientNew so we can do the rest of the Math.
     //重新计算RECT大小
     RepositionBars(AFX_IDW_CONTROLBAR_FIRST,
                       AFX_IDW_CONTROLBAR_LAST,
                       0,
                       reposQuery,
                       rcClientNew);

    // All of the Child Windows (Controls) now need to be moved so the Tollbar does not cover them up.
     //所有的子窗口将被移动,以免被TOOLBAR覆盖
     // Offest to move all child controls after adding Tollbar
     //计算移动的距离
     CPoint ptOffset(rcClientNew.left-rcClientOld.left,
       rcClientNew.top-rcClientOld.top);

     CRect rcChild;
     CWnd* pwndChild = GetWindow(GW_CHILD); //得到子窗口
     while(pwndChild) // 处理所有子窗口
     {
        //移动所有子窗口
         pwndChild->GetWindowRect(rcChild);
        ScreenToClient(rcChild);
        rcChild.OffsetRect(ptOffset);
        pwndChild->MoveWindow(rcChild,FALSE);
        pwndChild = pwndChild->GetNextWindow();
     }

     CRect rcWindow;
     GetWindowRect(rcWindow); // 得到对话框RECT
     rcWindow.right += rcClientOld.Width() - rcClientNew.Width(); // 修改对话框尺寸
     rcWindow.bottom += rcClientOld.Height() - rcClientNew.Height();
     MoveWindow(rcWindow,FALSE); // Redraw Window

     RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);

    方法二:

         http://www.codeproject.com/dialog/dlgtoolstatusbar.asp


11.响应对话框的最大化、最小化、关闭、恢复事件


     方法一:添加 WM_SYSCOMMAND 消息映射函数

     void CTest6Dlg::OnSysCommand(UINT nID, LPARAM lParam)
     {
        if ( (nID & 0xFFF0) == IDM_ABOUTBOX )
        {
               CAboutDlg dlgAbout;
               dlgAbout.DoModal();
    }
     else
     {
        if ( nID == SC_MAXIMIZE )
        {
               AfxMessageBox(_T("最大化"));
        }
        else if ( nID == SC_MINIMIZE )
        {
               AfxMessageBox(_T("最小化"));
        }
        else if ( nID == SC_CLOSE )
        {
               AfxMessageBox(_T("关闭"));
        }

        CDialog::OnSysCommand(nID, lParam);
    }

     方法二:添加 WM_SIZE 消息映射函数

     void CTest6Dlg::OnSize(UINT nType, int cx, int cy)
     {
        CDialog::OnSize(nType, cx, cy);

        if ( nType == SIZE_MAXIMIZED )
        {
               AfxMessageBox(_T("最大化"));
        }
        else if ( nType == SIZE_MINIMIZED )
        {
               AfxMessageBox(_T("最小化"));
        }
        else if ( nType == SIZE_RESTORED )
        {
               AfxMessageBox(_T("恢复"));
        }
     }


12.代码实现窗口最小化,最大化,关闭


PostMessage(WM_SYSCOMMAND, SC_MINIMIZE);
PostMessage(WM_SYSCOMMAND, SC_MAXIMIZE);
PostMessage(WM_SYSCOMMAND, SC_CLOSE);


13.按下ESC和ENTER键时禁止关闭对话框

  
    方法一:

     (1) 重载OnCancel和OnOk,屏蔽其中的CDialog::OnCancel()和CDialog::OnOk();
     (2) 添加以下代码
     void CTest6Dlg::OnSysCommand(UINT nID, LPARAM lParam)
     {
         if ((nID & 0xFFF0) == IDM_ABOUTBOX)
          {
             CAboutDlg dlgAbout;   //if you have an about dialog
              dlgAbout.DoModal();
          }
          else if ((nID & 0xFFF0) == SC_CLOSE)
          {
              //用户点击右上角"X"
              EndDialog(IDOK);
      
          }
          else
          {
              CDialog::OnSysCommand(nID, lParam);
          }
     }

    方法二:

     BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
     {
        if ( pMsg->message == WM_KEYDOWN )
        {
               switch(pMsg->wParam)
               {
               case VK_ESCAPE:
                return TRUE; //直接返回TRUE
                break;
               case VK_RETURN:
                return TRUE;
                break;
               }
        }
        return CDialog::PreTranslateMessage(pMsg);
     }

     方法三:
         Q122489:
         How to Disable Default Pushbutton Handling for MFC Dialog
         http://support.microsoft.com/kb/122489/en-us


14.在对话框中处理键盘鼠标消息


处理PreTranslateMessage消息

以下代码示例只演示了键盘WM_KEYDOWN消息,你也可以处理鼠标消息,比如WM_LBUTTONDOWN,WM_LBUTTONUP,WM_RBUTTONDOWN等。

BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
{
    /**********************************************************/
    /*    当焦点在combobox(drop down风格)的edit上,响应回车            */
    /***********************************************************/
    if ( pMsg->message == WM_KEYDOWN )
    {        
        switch( pMsg->wParam )
        {
        case VK_RETURN:
            CEdit *pEdit = (CEdit*)m_combo1.GetWindow(GW_CHILD);
            if(pMsg->hwnd == pEdit->m_hWnd )
            {
  
AfxMessageBox("在combobox的edit中按下了Enter!");
            }           
            return TRUE;
        }
    }

    /****************************************/
    /*  
ALT为WM_SYSKEYDOWN                  */
    /****************************************/

    if( pMsg->message == WM_SYSKEYDOWN )
    {   
        switch( pMsg->wParam )
        {
        case VK_F1:   
            if(::GetKeyState(VK_MENU) < 0)//ALT+F1
            {
                AfxMessageBox("按下了ALT+F1");
                return TRUE;
            }           
        }       
    }
  
    /****************************************/
    /*     在clistctrl中按ctrl+A选中所有项 */
    /****************************************/
    if( pMsg->message == WM_KEYDOWN )
    {   
        if(pMsg->hwnd == GetDlgItem(IDC_LIST1)->m_hWnd)
        {
            switch( pMsg->wParam )
            {
            case 65://A   
            if(::GetKeyState(VK_CONTROL) < 0)//Shift+enter
            {
                    for(int i=0; i

15.对话框启动即隐藏


    添加 WM_SHOWWINDOW 的消息映射

     void CTest6Dlg::OnShowWindow(BOOL bShow, UINT nStatus)
     {
        if ( GetStyle() & WS_VISIBLE )
        {
               CDialog::OnShowWindow(bShow, nStatus);
        }
        else
        {
               long Style = ::GetWindowLong(*this, GWL_STYLE);
               ::SetWindowLong(*this, GWL_STYLE, Style | WS_VISIBLE);
               CDialog::OnShowWindow(SW_HIDE, nStatus);
        }
     }


16.对话框自动停靠在屏幕边


    const int DETASTEP = 50;
     BOOL AdjustPos(CWnd *pWnd, CRect* lpRect)
     {
        //自动靠边
        int iSX = GetSystemMetrics(SM_CXFULLSCREEN);
        int iSY = GetSystemMetrics(SM_CYFULLSCREEN);
        RECT rWorkArea;
        BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rWorkArea, 0);

        CRect rcWA;
        if ( !bResult )
        {
            //如果调用不成功就利用GetSystemMetrics获取屏幕面积
            rcWA = CRect(0,0,iSX,iSY);
        }
        else
            rcWA = rWorkArea;

        int iX = lpRect->left;
        int iY = lpRect->top;
        if ( iX < rcWA.left + DETASTEP && iX!=rcWA.left )
        {
            //调整左
            pWnd->SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);
            lpRect->OffsetRect(rcWA.left-iX,0);
            AdjustPos(lpRect);
            return TRUE;
        }
        if ( iY < rcWA.top + DETASTEP && iY!=rcWA.top )
        {
            //调整上
            pWnd->SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);
            lpRect->OffsetRect(0,rcWA.top-iY);
            AdjustPos(lpRect);
            return TRUE;
        }
        if ( iX + lpRect->Width() > rcWA.right - DETASTEP && iX !=rcWA.right-lpRect->Width() )
        {
            //调整右
            pWnd->SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);
            lpRect->OffsetRect(rcWA.right-lpRect->right,0);
            AdjustPos(lpRect);
            return TRUE;
        }
        if ( iY + lpRect->Height() > rcWA.bottom - DETASTEP && iY !=rcWA.bottom-lpRect->Height() )
        {
            //调整下
            pWnd->SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);
            lpRect->OffsetRect(0,rcWA.bottom-lpRect->bottom);
            return TRUE;
        }
        return FALSE;
    }

    //然后在ONMOVEING事件中使用如下过程调用
    CRect r=*pRect;
    AdjustPos(this, &r);
    *pRect=(RECT)r;


17.单击窗口任意位置都可拖动窗口

    方法一:
     添加 WM_LBUTTONDOWN 的消息映射
     void CTest6Dlg::OnLButtonDown(UINT nFlags, CPoint point)
     {
        PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0);

        CDialog::OnLButtonDown(nFlags, point);
     }

    方法二:
   
添加 WM_NCHITTEST 的消息映射
    注意:在classwizard->message中找不到
WM_NCHITTEST的,需要在选项卡class info->message filter中选择window后该消息才会出现在message中。
     void CTest6Dlg::OnNCHitTest(CPoint point)
     {
            return HTCAPTION;
    //    return CDialog::
OnNCHitTest(point);
     }

     或者参考
        http://msdn.microsoft.com/msdnmag/issues/02/12/CQA/default.aspx


18.用Enter键替换Tab键实现焦点切换


     BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
     {
        if ( pMsg->message == WM_KEYDOWN )
          {
              if ( pMsg->wParam == VK_RETURN )
                   pMsg->wParam = VK_TAB;
          }
          return CDialog::PreTranslateMessage(pMsg);
     }


19.在对话框添加快捷键


     (1) 在CXXXApp中类中添加声明
        HACCEL m_haccel;
     (2) 在resource view中右键点击树的根目录,选择insert,添加一个新的Accelerator,默认ID为IDR_ACCELERATOR1。
         在其中添加相应菜单的快捷键。
     (3) 在BOOL CXXXApp::InitInstance()中添加代码
        m_haccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
     (4) 添加CXXXApp类的 ProcessMessageFilter 消息映射函数
         BOOL CTest6App::ProcessMessageFilter(int code, LPMSG lpMsg)
         {
              if ( m_haccel )
              {
                  if ( ::TranslateAccelerator(m_pMainWnd->m_hWnd, m_haccel, lpMsg) )
                       return TRUE;
              }
              return CWinApp::ProcessMessageFilter(code, lpMsg);
         }

或者参考
Q100770:
How to use accelerator keys and a main menu on the dialog box in Visual C++
http://support.microsoft.com/kb/100770/en-us

Adding Hot Keys to your Application
http://msdn.microsoft.com/msdnmag/issues/1200/c/default.aspx


20.对话框全屏


    int cx, cy;
    HDC dc = ::GetDC(NULL);
    cx = GetDeviceCaps(dc,HORZRES) + GetSystemMetrics(SM_CXBORDER);
    cy = GetDeviceCaps(dc,VERTRES) + GetSystemMetrics(SM_CYBORDER);
    ::ReleaseDC(0,dc);

    // Remove caption and border
    SetWindowLong(m_hWnd, GWL_STYLE,
                    GetWindowLong(m_hWnd, GWL_STYLE) & (~(WS_CAPTION | WS_BORDER)));

    // Put window on top and expand it to fill screen
    ::SetWindowPos(m_hWnd, HWND_TOPMOST,
          -(GetSystemMetrics(SM_CXBORDER)+1),
          -(GetSystemMetrics(SM_CYBORDER)+1),
          cx+1,cy+1, SWP_NOZORDER);
    或参考
        http://www.codeguru.com/cpp/w-d/dislog/dialog-basedapplications/article.php/c1837/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很经典的MFC教程。 目 录 译者序 前言 第一部分 基础知识 第1章 窗口 2 1.1 窗口和API环境 2 1.1.1 三种类型窗口 2 1.1.2 客户区和非客户区 3 1.2 窗口和MFC环境 4 1.3 怎样应用MFC创建一个窗口 5 1.4 怎样使用MFC销毁一个窗口 9 1.4.1 捆绑到一个已有的窗口 9 1.4.2 窗口类 10 1.4.3 窗口进程 10 1.5 怎样使用MFC创建一个窗口类 11 1.5.1 使用AfxRegisterWndClass () 函数注册一个窗口类 11 1.5.2 使用AfxRegisterClass ()函数 创建一个窗口类 12 1.6 怎样销毁一个MFC窗口类 14 1.7 厂商安装的窗口类 14 1.8 其他类型窗口 15 1.9 桌面窗口 16 1.10 小结 16 第2章 类 18 2.1 基类 18 2.1.1 CObject 18 2.1.2 CCmdTarget 19 2.1.3 CWnd 19 2.2 应用程序、框架、文档和视图类 19 2.2.1 CWinApp(O/C/W) 20 2.2.2 CView (O/C/W) 21 2.3 其他用户界面类 22 2.3.1 通用控件类 23 2.3.2 菜单类 23 2.3.3 对话框类 24 2.3.4 控制条类 24 2.3.5 属性类 25 2.4 绘图类 25 2.4.1 设备环境类 25 2.4.2 图形对象类 25 2.5 文件类 26 2.6 数据库类 26 2.6.1 ODBC类 26 2.6.2 DAO类 27 2.7 数据集类 27 2.8 其他数据类 27 2.9 通信类 28 2.10 其他类 29 2.11 小结 31 第3章 消息处理 32 3.1 发送或寄送一个消息 32 3.1.1 发送一个消息 32 3.1.2 寄送一个消息 32 3.1.3 发送一个消息与寄送一个消息 的比较 32 3.2 怎样使用MFC发送一个消息 33 3.3 怎样用MFC寄送一个消息 33 3.4 三种类型的消息 34 3.4.1 窗口消息 34 3.4.2 命令消息 34 3.4.3 控件通知 34 3.5 MFC怎样接收一个寄送的消息 36 3.6 MFC怎样处理一个接收到的消息 36 3.7 处理用户界面的对象 44 3.8 创建自定义窗口消息 45 3.8.1 静态分配的窗口消息 45 3.8.2 动态分配的窗口消息 46 3.9 重定向消息 47 3.9.1 子分类和超分类 47 3.9.2 用MFC子分类窗口 48 3.9.3 重载OnCmdMsg ( ) 49 3.9.4 使用SetWindowsHookEx ( ) 49 3.9.5 使用SetCapture ( ) 49 3.9.6 专有的消息泵 50 3.10 小结 50 第4章 绘图 51 4.1 设备环境 51 4.2 在MFC环境中创建一个设备环境 52 4.2.1 屏幕 52 4.2.2 打印机 53 4.2.3 内存 54 4.2.4 信息 54 4.3 绘图例程 55 4.3.1 画点 55 4.3.2 画线 55 4.3.3 画形状 55 4.3.4 形状填充和翻转 55 4.3.5 滚动 56 4.3.6 绘制文本 56 4.3.7 绘制位图和图标 56 4.4 绘图属性 56 4.4.1 设备环境属性 57 4.4.2 画线属性 58 4.4.3 形状填充属性 58 4.4.4 文本绘制属性 58 4.4.5 映像模式 59 4.4.6 调色板属性 62 4.4.7 混合属性 62 4.4.8 剪裁属性 63 4.4.9 位图绘制属性 64 4.5 元文件和路径 65 4.5.1 元文件 65 4.5.2 路径 66 4.6 颜色和调色板 66 4.6.1 抖动色 67 4.6.2 未经抖动色 67 4.6.3 系统调色板 67 4.6.4 使用系统调色板 68 4.6.5 动画色 71 4.7 控制什么时候在哪里绘图 71 4.7.1 处理WM_PAINT 71 4.7.2 只绘制被无效化的区域 72 4.7.3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值