C/C++自动调整界面布局的对话框

简介: 来源:http://blog.csdn.net/xianglitian/article/details/5667015 例子:http://download.csdn.net/download/xianglitian/2425531 CodeProject上的例子: EasySize - Dialog resizing in no time! http://www.

来源:http://blog.csdn.net/xianglitian/article/details/5667015

例子:http://download.csdn.net/download/xianglitian/2425531

CodeProject上的例子:

EasySize - Dialog resizing in no time!

http://www.codeproject.com/Articles/1657/EasySize-Dialog-resizing-in-no-time

早在2007年我就写过一篇博客叫可适配控件对话框那个时候一方面是工作需要研究了这个问题,另一方面是发现论坛里有很多人问相关的问题,于是就把自己的研究成果做了一个小例子发了上来,还写了那篇博客。

说来惭愧,首先那时那个例子其实是我照着网上一个例子改的,而且基本框架也差不多,我简单加了些自己的东西改了改名就发出来了,唉......如今原作者以无法考正了,在此对其表示感谢吧。然后那个例子其实不是很好用,当时并没有发现什么问题,但是随着工作中使用的增多我发现了不少缺陷,也在工作中不断的改进,终于做出了一个自己用的很舒服的版本。如今三年过去了,再看CSDN界面版仍然有很多网友问及此类问题,VisualEleven力推codeproject上的easysize。easysize当初我也简单看过,不过那时我并没看懂,估计我现在也看不懂,呵呵。不过我觉得我用的这个方法也蛮好的,所以决定再写一篇博客把现在的方法介绍一下,同时整理了一个例子供大家研究。

处理过这个问题的朋友们就应该知道,所谓的控件动态调整就是在主窗口的OnSize消息里处理一下,根据窗口的大小重新布置控件的位置。而解决这个问题的关键在于如何管理界面中的控件信息,从而可以比较方便的实现对控件的重新布局。我的处理方式是这样的,我定义了一个结构tagCONTROL,其内容如下

/**
 *  控件随窗口变化的控制单元
**/
typedef struct tagCONTROL
{
	CWnd*	m_pWnd;				//指向控件的指针
	CRect	m_rectWnd;			//控件所占区域
	int		m_nMoveXPercent,	//控件沿x轴移动的百分比
			m_nMoveYPercent,	//控件沿y轴移动的百分比
			m_nZoomXPercent,	//控件沿x轴缩放的百分比
			m_nZoomYPercent;	//控件沿y轴缩放的百分比
}ControlInfo, *lpControlInfo;


从这个定义中我们可以看出tagCONTROL里保存了丰富的对于控件布局的控制信息,这里m_pWnd是指向被控控件的指针,他可以是一个控件也可以是一个窗口,这样就把界面布局的控制元素全都囊括进来了。而移动、缩放的百分比控制使界面布局的控制更加灵活,更加方便。每一个需要调整布局的界面元素都会通过这个结构来保存其信息,而在界面主窗口中维护一个这种结构的列表即可在OnSize函数中方便的实现控件布局的自动调整。

所谓界面动态调整布局实际上应该有一个参照,也就是说我们应该记录初始显示时界面的大小和此时界面中控件的位置。以后的调整都是基于这些信息的,也就是说tagCONTROL中保存的信息都是通过初始的基本数据起作用的。按着这个思路,在OnSize函数中我是这样实现的

void CAutoFitDlg::OnSize(UINT nType, int cx, int cy)
{
	//计算窗口宽度和高度的改变量
    int nIncrementX = cx - m_nWinWidth;
    int nIncrementY = cy - m_nWinHeight;

	INT_PTR	nCount	= m_listCtrlTag.GetSize();

    for (int i=0; i<nCount; i++)
    {
		//获取变化控制系数
		int	nMoveXPercent	= m_listCtrlTag[i]->m_nMoveXPercent;
		int	nMoveYPercent	= m_listCtrlTag[i]->m_nMoveYPercent;
		int	nZoomXPercent	= m_listCtrlTag[i]->m_nZoomXPercent;
		int	nZoomYPercent	= m_listCtrlTag[i]->m_nZoomYPercent;

        CWnd*	pWndCtrl;
		//获取控件指针
		pWndCtrl = m_listCtrlTag[i]->m_pWnd;

        if(IsWindow(pWndCtrl->GetSafeHwnd()))
        {
            int nLeft	= m_listCtrlTag[i]->m_rectWnd.left;
            int nTop	= m_listCtrlTag[i]->m_rectWnd.top;
            int nWidth	= m_listCtrlTag[i]->m_rectWnd.Width();
            int nHeight	= m_listCtrlTag[i]->m_rectWnd.Height();

			//设置新的位置参数
			nLeft	+= (nIncrementX*nMoveXPercent/100);
			nTop	+= (nIncrementY*nMoveYPercent/100);
			nWidth	+= (nIncrementX*nZoomXPercent/100);
			nHeight	+= (nIncrementY*nZoomYPercent/100);

            //  把控件移动到新位置
			pWndCtrl->MoveWindow(nLeft, nTop, nWidth, nHeight);
		}
	}

	CDialog::OnSize(nType, cx, cy);
}


同时,一个设计良好的界面的一般会有一个最小大小,在这个范围内安排界面布局。通常情况下我们不希望界面小于这个最小大小,这个需求可以通过重载WM_GETMINMAXINFO消息来实现

void CAutoFitDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	//设置窗口的最小大小
	lpMMI->ptMinTrackSize = m_ptMinTrackSize;

	CDialog::OnGetMinMaxInfo(lpMMI);
}


这样一来,只要我们设计好控制信息,我们设计的界面即使被用户缩放和拖拽也可以体现出良好的布局。这个方案是我这些年来一直在项目中采用的,我不敢说它是完美的,但是却是能够满足一般的需求。如果大家在对这个方案的研究和使用中发现什么问题或是可以改进的地方还希望可以告诉我,我会加以改进再和朋友们分享。

以上是原文内容,下面是个人在使用中进行的扩展:

/**
 *  控件随窗口变化的控制单元
**/
typedef struct tagCONTROL
{
	CWnd*	m_pWnd;				//指向控件的指针
	CRect	m_rectWnd;			//控件所占区域
	int		m_nMoveXPercent,	//控件沿x轴移动的百分比
			m_nMoveYPercent,	//控件沿y轴移动的百分比
			m_nZoomXPercent,	//控件沿x轴缩放的百分比
			m_nZoomYPercent,	//控件沿y轴缩放的百分比
			m_nMinVisibleWidth, //控件可见的最小宽度,当窗口的宽度小于该值,则隐藏此控件;如果该值为-1则从不隐藏;
			m_nMinVisibleHeight;//控件可见的最小高度,当窗口的高度小于该值,则隐藏此控件;如果该值为-1则从不隐藏;
	BOOL 	m_bCanHideShow;		//指示窗口缩放时是否根据“最小宽度和最小高度”显示或隐藏控件;
}ControlInfo, *lpControlInfo;


目录
相关文章
|
C++
C++ 自动导入数字证书
C++ 自动导入数字证书
172 0
|
安全 Java 程序员
总结一下Qt内存泄漏检测与处理策略,并附个人写的C++单例类,用于内存自动释放
总结一下Qt内存泄漏检测与处理策略,并附个人写的C++单例类,用于内存自动释放
1456 0
|
BI C++
C++文件(夹)选择对话框
由于各种应用,我们需要调用系统的打开文件对话框或者打开文件夹对话框,或两者兼有。今遇到这个情况已经解决,特写下这篇博文。 1.打开文件对话框常用的方法是使用系统的CFileDialog。这里介绍另外一种方法就是使用OPENFILENAME这个结构体和GetOpenFileName()这个函数,可以实现单选文件或者多选文件,代码如下: 需引入头文件#include "CommDlg.
2747 0
C++函数中,两个自动释放内存的动态内存申请类
C++函数中,两个自动释放内存的动态内存申请类最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if free/delete,代码长而且不好管理 因此,利用C...
1285 0
|
C++
C++11新特性:自动类型推断和类型获取
声明:本文是在Alex Allain的文章http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html的基础上写成的。
1005 0