您的位置:首页 > 编程语言

基于mfc的对话框编程中,实现控件随对话框大小自动缩放以及通过滚动条实现控件移动功能

2016-06-19 17:23 786 查看
1.在OnInitDialog中加入初始化垂直和水平滚动条的属性:

    SCROLLINFO vinfo;
    vinfo.cbSize = sizeof(vinfo);
    vinfo.fMask = SIF_ALL;
    vinfo.nPage = 50;
    vinfo.nMax = 600;
    vinfo.nMin = 0;
    vinfo.nPos = 0;
    SetScrollInfo(SB_HORZ, &vinfo);
    SetScrollInfo(SB_VERT, &vinfo);

之后在对话框类的定义中自定义五个变量:

    POINT Old;

    long lastVscroll;
    long curVscroll;
    long lastHscroll;
    long curHscroll;

2.重载两个消息:WM_HSCROLL和WM_VSCROLL

void CjupiaoDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    int iMin(0), iMax(0), iVisibleCol(0), iVertPos(0);
    SCROLLINFO m_hScrollInfo;

    GetScrollInfo(SB_HORZ, &m_hScrollInfo, SIF_ALL);
    iVertPos = m_hScrollInfo.nPos; //滚动条未滑动前的位置
    iMin = m_hScrollInfo.nMin;
    iMax = m_hScrollInfo.nMax;
    iVisibleCol = m_hScrollInfo.nPage;
    lastHscroll = iVertPos;
    switch (nSBCode)
    {
    case SB_THUMBTRACK://当用户直接拖动滑动条时会触发这个
        m_hScrollInfo.nPos = nPos;
        break;
    case SB_LEFT:
        m_hScrollInfo.nPos = iMin;
        break;
    case SB_RIGHT:
        m_hScrollInfo.nPos = iMax;
    case SB_LINELEFT://这个是点击向左移动的箭头
        m_hScrollInfo.nPos -= 40;
        break;
    case SB_LINERIGHT:
        m_hScrollInfo.nPos += 40;   //加多少自己确定
        break;
    case SB_PAGELEFT:
        //m_hScrollInfo.nPage -= iVisibleCol;
        m_hScrollInfo.nPos -= 40;  //减多少自己确定
        break;
    case SB_PAGERIGHT://这个是点击滑块右边的空白部分
        //m_hScrollInfo.nPage += iVisibleCol;
        m_hScrollInfo.nPos += 40;
        break;
    default:
        break;
    }

    m_hScrollInfo.fMask = SIF_ALL;
    SetScrollInfo(SB_HORZ, &m_hScrollInfo);

    curHscroll = m_hScrollInfo.nPos;

    GetScrollInfo(SB_HORZ, &m_hScrollInfo);
    if (iVertPos != m_hScrollInfo.nPos)
    {
        Invalidate();//会发送WM_PAINT消息
        //ScrollWindow(m_lCellWith*(iVertPos-m_hScrollInfo.nPos),0);
    }
    CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CjupiaoDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    int iMin(0), iMax(0), iVisibleCol(0), iVertPos(0);
    SCROLLINFO m_vScrollInfo;

    GetScrollInfo(SB_VERT, &m_vScrollInfo, SIF_ALL);
    iVertPos = m_vScrollInfo.nPos; //滚动条未滑动前的位置
    iMin = m_vScrollInfo.nMin;
    iMax = m_vScrollInfo.nMax;
    iVisibleCol = m_vScrollInfo.nPage;
    lastVscroll = iVertPos;
    switch (nSBCode)
    {
    case SB_THUMBTRACK:
        m_vScrollInfo.nPos = nPos;
        break;
    case SB_TOP:
        m_vScrollInfo.nPos = iMin;
        break;
    case SB_BOTTOM:
        m_vScrollInfo.nPos = iMax;
    case SB_LINEUP:
        m_vScrollInfo.nPos -= 40;
        break;
    case SB_LINEDOWN:
        m_vScrollInfo.nPos += 40;   //加多少自己确定
        break;
    case SB_PAGEUP:
        m_vScrollInfo.nPage -= iVisibleCol;
        m_vScrollInfo.nPos -= 40;  //减多少自己确定
        break;
    case SB_PAGEDOWN:
        m_vScrollInfo.nPage += iVisibleCol;
        m_vScrollInfo.nPos += 40;
        break;
    default:
        break;
    }

    m_vScrollInfo.fMask = SIF_ALL;
    SetScrollInfo(SB_VERT, &m_vScrollInfo);

    curVscroll = m_vScrollInfo.nPos;

    GetScrollInfo(SB_VERT, &m_vScrollInfo);
    if (iVertPos != m_vScrollInfo.nPos)
    {
        Invalidate();
        //ScrollWindow(m_lCellWith*(iVertPos-m_vScrollInfo.nPos),0);
    }
    CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}

3.自定义一个函数用来对每一个控件改变位置:

void CjupiaoDlg::automove()
{
    float fsp[2];
    POINT Newp; //获取现在对话框的大小
    CRect recta;
    long stepH = curHscroll - lastHscroll;
    long stepV = curVscroll - lastVscroll;
    GetClientRect(&recta); //取客户区大小  
    Newp.x = recta.right - recta.left;
    Newp.y = recta.bottom - recta.top;
    fsp[0] = (float)Newp.x / Old.x;
    fsp[1] = (float)Newp.y / Old.y;
    CRect Rect;
    int woc;
    CPoint OldTLPoint, TLPoint; //左上角
    CPoint OldBRPoint, BRPoint; //右下角
    HWND hwndChild = ::GetWindow(m_hWnd, GW_CHILD); //列出所有控件  
    while (hwndChild)
    {
        woc = ::GetDlgCtrlID(hwndChild);//取得ID
        GetDlgItem(woc)->GetWindowRect(Rect);
        ScreenToClient(Rect);
        OldTLPoint = Rect.TopLeft();
        TLPoint.x = long((OldTLPoint.x - stepH)*fsp[0]);
        TLPoint.y = long((OldTLPoint.y - stepV)*fsp[1]);
        OldBRPoint = Rect.BottomRight();
        BRPoint.x = long((OldBRPoint.x - stepH) *fsp[0]);
        BRPoint.y = long((OldBRPoint.y - stepV) *fsp[1]);
        Rect.SetRect(TLPoint, BRPoint);
        GetDlgItem(woc)->MoveWindow(Rect, TRUE);
        hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
    }
    Old = Newp;
}

4.最后在OnPaint()里面加入:

automove();

大概长成这个样子:

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

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        automove();
        CDialogEx::OnPaint();
    }
}

//Over!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息