MFC控件自适应(亲测可用)

注意:

#窗口实现缩放必须先设置窗口Border属性为Resizing

#静态控件需要给定一个控件ID,否则不会缩放

#ComboBox需单独处理, 否则无法下拉

1. 控件缩放类

1)CtrlScale.h

#pragma once
typedef struct TAG_CTRLRECT
{
public:
    int nId;//控件ID
    double dScale[4];//缩放值
    TAG_CTRLRECT()
    {
        nId = 0;//未定义
        dScale[0]=0;
        dScale[1]=0;
        dScale[2]=0;
        dScale[3]=0;
    }
    TAG_CTRLRECT(const TAG_CTRLRECT& cr)
    {
        *this=cr;
    }
    bool operator () (const TAG_CTRLRECT& cr){
        return (cr.nId == nId);
    }
}CTRLRECT;

class CCtrlScale
{
public:
    CCtrlScale(void);
    CCtrlScale(CWnd *pParentWnd);
    virtual ~CCtrlScale(void);

    void Init(CWnd *pParentWnd);
    void Scale(int cx, int cy);

private:
    CWnd *m_pParentWnd;
    CRect m_rect;
    vector m_vecCtrl;//保存控件缩放信息
};

2)CtrlScale.cpp

#include "StdAfx.h"
#include "CtrlScale.h"


CCtrlScale::CCtrlScale(void):m_pParentWnd(NULL)
{
}

CCtrlScale::CCtrlScale(CWnd *pParentWnd):m_pParentWnd(pParentWnd)
{
    Init(pParentWnd);
}

CCtrlScale::~CCtrlScale(void)
{

    m_vecCtrl.clear();
}

void CCtrlScale::Init(CWnd *pParentWnd)
{
    if (pParentWnd){
        m_pParentWnd = pParentWnd;
        m_pParentWnd->GetClientRect(&m_rect); //获取对话框的大小
    }
}

void CCtrlScale::Scale(int cx, int cy)
{
    if (!m_pParentWnd){
        return;
    }

    //判定是否为最小状态,是的话就不进行重绘
    if(cx == 0 || cy == 0){
        return;
    }

    //获取控件得到大小以及原大小方便进行比例调整
    CWnd *pWnd;
    int nID = 0;
    //列出所有控件
    HWND hChild =::GetWindow(m_pParentWnd->m_hWnd, GW_CHILD);
    while(hChild){
        nID = ::GetDlgCtrlID(hChild);//获得控件ID
        pWnd = m_pParentWnd->GetDlgItem(nID);//获取控件指针
        if(pWnd){
            CRect rect;//获取当前控件的大小
            pWnd->GetWindowRect(&rect);
            m_pParentWnd->ScreenToClient(&rect);//将控件大小转换为在窗口的区域坐标
            //防止控件失真
            m_pParentWnd->InvalidateRect(rect);

            CTRLRECT cr;
            cr.nId = nID;
            vector::iterator it = find_if(m_vecCtrl.begin(), m_vecCtrl.end(), cr);
            if (it != m_vecCtrl.end()){//如果保存的有该控件与窗口比值,直接乘上当前窗口大小
                rect.left = it->dScale[0] * cx;
                rect.right = it->dScale[1] * cx;
                rect.top = it->dScale[2] * cy;
                rect.bottom = it->dScale[3] * cy;
            }
            else{//没有找到控件的比值,则加入
                cr.dScale[0] = (double)rect.left/m_rect.Width();//注意类型转换,不然保存成long型就直接为0了
                cr.dScale[1] = (double)rect.right/m_rect.Width();
                cr.dScale[2] = (double)rect.top/m_rect.Height();
                cr.dScale[3] = (double)rect.bottom/m_rect.Height();
                m_vecCtrl.push_back(cr);
                /调整控件大小
                rect.left = cr.dScale[0] * cx;
                rect.right = cr.dScale[1] * cx;
                rect.top = cr.dScale[2] * cy;
                rect.bottom = cr.dScale[3] * cy;
            }

            if (pWnd->IsKindOf(RUNTIME_CLASS(CComboBox))){
                //解决ComboBox缩放后,无法下拉的问题
                pWnd->MoveWindow(rect.left, rect.top, rect.Width(), rect.Height() + 200);
            }else{
                pWnd->MoveWindow(rect);//设置控件大小
            }
        }
        hChild=::GetWindow(hChild, GW_HWNDNEXT);
    }
    m_pParentWnd->GetClientRect(&m_rect);//获取变化后的窗口大小
}


2.在窗口类中定义缩放类变量

CCtrlScale m_scale;


3.在窗口初始化时,初始化缩放类

    

m_scale.Init(this);

4.在窗口类中添加OnSize方法

void CXXXDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);

    m_scale.Scale(cx, cy);
}


 

你可能感兴趣的:(MFC,MFC,窗口自适应,缩放后ComboBox无法下拉)