在程序运行时用鼠标调整对话框上的控件

来源:互联网 发布:淘宝女装模特图片 编辑:程序博客网 时间:2024/05/23 13:32

【转自http://blog.csdn.net/mackz/archive/2005/10/27/517747.aspx】

有时候,我们需要在程序中调整界面,比如对话框上的控件位置和大小,以实现用户定义对话框。下面我实现一个例子,程序运行时,可以用鼠标调整对话框上的控件。

  建立一个对话框程序,添加两个成员:

protected:
    CRectTracker m_rtTracker;
    CWnd* m_pSelectedCtrl;  //初始化为NULL

 

public:
    afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);

 

BOOL CEditableDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
......
    // TODO: 在此添加额外的初始化代码
    m_rtTracker.m_nStyle = m_rtTracker.dottedLine | m_rtTracker.resizeOutside;
    m_rtTracker.m_nHandleSize = 6;
    m_rtTracker.m_sizeMin.SetSize(10, 10);
    
    return TRUE;  // 除非设置了控件的焦点,否则返回 TRUE
}

  在对话框的绘制函数中:

void CEditableDlg::OnPaint()
{
    CPaintDC dc(this); // 用于绘制的设备上下文
    if (IsIconic())
    {

......

    }
    else
    {
        CDialog::OnPaint();
        if (m_pSelectedCtrl)
        {
            m_rtTracker.Draw(&dc);
        }
    }
}

  在相应鼠标消息中添加代码:

int CEditableDlg::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CPoint point;
    ::GetCursorPos(&point);
    ScreenToClient(&point);
    CWnd *pWnd = ChildWindowFromPoint(point);
    if (pWnd && IsChild(pWnd))
    {
        while (pWnd && pWnd->GetParent() != this) pWnd = pWnd->GetParent();
        CRect   rcWnd;
        m_rtTracker.GetTrueRect(rcWnd);
        InvalidateRect(rcWnd);
        pWnd->GetWindowRect(rcWnd);
        ScreenToClient(rcWnd);
        m_rtTracker.m_rect.CopyRect(rcWnd);
        m_rtTracker.GetTrueRect(rcWnd);
        InvalidateRect(rcWnd);
        m_pSelectedCtrl = CWnd::FromHandle(pWnd->GetSafeHwnd());
        return MA_ACTIVATEANDEAT;
    }
    return CDialog::OnMouseActivate(pDesktopWnd, nHitTest, message);
}

void CEditableDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CWnd *pWnd = ChildWindowFromPoint(point);
    if (pWnd && IsChild(pWnd) && pWnd->GetParent() == this)
    {
        CRect   rcWnd;
        m_rtTracker.GetTrueRect(rcWnd);
        InvalidateRect(rcWnd);
        pWnd->GetWindowRect(rcWnd);
        ScreenToClient(rcWnd);
        m_rtTracker.m_rect.CopyRect(rcWnd);
        m_rtTracker.GetTrueRect(rcWnd);
        InvalidateRect(rcWnd);
        m_pSelectedCtrl = CWnd::FromHandle(pWnd->GetSafeHwnd());
        return;
    }
    CRect rectSave;
    m_rtTracker.GetTrueRect(rectSave);
    if (m_rtTracker.HitTest(point) >= 0 && m_rtTracker.Track(this, point, false))
    {
        InvalidateRect(rectSave);
        if (m_pSelectedCtrl)
            m_pSelectedCtrl->MoveWindow(m_rtTracker.m_rect);
        m_rtTracker.GetTrueRect(rectSave);
        InvalidateRect(rectSave);
    }
    else if (m_pSelectedCtrl)
    {
        m_pSelectedCtrl = NULL;
        InvalidateRect(rectSave);
    }
 

   CDialog::OnLButtonDown(nFlags, point);
}

  下面是设置光标:

BOOL CEditableDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    if ( m_pSelectedCtrl && m_rtTracker.SetCursor( this, nHitTest ))
    {
        return TRUE;
    }
    else
    {
        SetCursor(::LoadCursor(NULL, IDC_ARROW));
        return true;
    }
 

   return CDialog::OnSetCursor(pWnd, nHitTest, message);
}

  下面再说说保存的问题。修改了对话框,希望下次可以调用,可以采用保存对话框模板的方法。不过我们这里只需要保存各个控件的大小和位置,因此可以简化处理,下面是保存代码:


void CEditableDlg::OnClose()
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CFile dlgTempFile(_T("dlgtemp.dtf"), CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
    if (dlgTempFile)
    {
        CWnd *pWnd = FindWindowEx(GetSafeHwnd(), NULL, NULL, NULL);
        while (pWnd)
        {
            int nID = pWnd->GetDlgCtrlID();
            dlgTempFile.Write(&nID, sizeof(int));
            RECT rcWnd;
            pWnd->GetWindowRect(&rcWnd);
            ScreenToClient(&rcWnd);
            dlgTempFile.Write(&rcWnd, sizeof(RECT));
            pWnd = FindWindowEx(GetSafeHwnd(), pWnd->GetSafeHwnd(), NULL, NULL);
        }
        dlgTempFile.Close();
    }

    CDialog::OnClose();
}

  下面是调用代码:

BOOL CEditableDlg::OnInitDialog()
{
..... 

   CFile dlgTempFile(_T("dlgtemp.dtf"), CFile::modeRead | CFile::typeBinary);
    if (dlgTempFile)
    {
        int nID;
        RECT rcWnd;
        while (dlgTempFile.Read(&nID, sizeof(nID)))
        {
            if (dlgTempFile.Read(&rcWnd, sizeof(RECT)))
            {
                CWnd *pWnd = GetDlgItem(nID);
                if (pWnd)
                {
                    //ScreenToClient(&rcWnd);
                    pWnd->MoveWindow(&rcWnd);
                }
            }
        }
        dlgTempFile.Close();
    }
    return TRUE;  // 除非设置了控件的焦点,否则返回 TRUE
}

  在OnClose中保存,在OnInitDialog中调用,简化了文件处理。如果需要,可以增加选择保存文件和调用文件的代码提供更多的选择。为了保证调用正确的对话框设置,还需要在文件头部写入一个标识号,可以用GUID之类生成唯一标识,就更加保险了。

  最后一个问题,对话框要用,可以用一个布尔型变量来切换可编辑状态,只要上面鼠标消息中德语句放到一个条件判断中就可以了。


  再添加三个消息函数:   在对话框的初始化中:
原创粉丝点击