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;


目录
相关文章
|
5月前
|
C++
C++ Qt开发:自定义Dialog对话框组件
在之前的文章中笔者已经为大家展示了默认`Dialog`组件的使用方法,虽然内置组件支持对数据的输入,但有时候我们需要一次性输入多个数据,此时如果之使用默认模态对话框似乎不太够用,此时我们需要自己创建一个自定义对话框,需要说明的是此类对话框也是一种窗体,所以可以在其上面放置任何通用组件,以实现更多复杂的开发需求。自定义对话框需要解决的问题是,如何让父窗体与子窗体进行数据交换,要实现数据的交换有两种方式,第一种方式是通过动态加载模态对话框,当用户点击确定后通过`GetValue()`来拿到数据,而第二种方式则是通过发送信号的方式将数据投递给父窗体,这两种方式都可以,读者可根据自身需求来选择不同的通
43 1
C++ Qt开发:自定义Dialog对话框组件
|
5月前
|
数据安全/隐私保护 C++ 开发者
C++ Qt开发:标准Dialog对话框组件
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍标准对话框`QInputDialog`、`QFileDialog `这两种对话框组件的常用方法及灵活运用。在 Qt 中,标准对话框提供了一些常见的用户交互界面,用于执行特定任务,例如获取用户输入、选择文件路径、显示消息等。这些对话框通常具有标准化的外观和行为,使得在不同的平台上能够保持一致性。在一般的开发过程中,标准对话框是开发者常用的工具之一。
51 1
C++ Qt开发:标准Dialog对话框组件
|
C++
C++ 自动导入数字证书
C++ 自动导入数字证书
128 0
|
C++
C/C++ Qt 标准Dialog对话框组件应用
在Qt中对话框分为两种形式,一种是标准对话框,另一种则是自定义对话框,在一般开发过程中标准对话框使用是最多的了,标准对话框一般包括 QMessageBox,QInputDialog,QFileDialog 这几种,这里我将总结本人在开发过程中常用到的标准对话框的使用技巧。
303 0
C/C++ Qt 标准Dialog对话框组件应用
|
C++
C/C++ Qt 自定义Dialog对话框组件应用
在上一篇博文 `《C/C++ Qt 标准Dialog对话框组件应用》` 中我给大家演示了如何使用Qt中内置的标准对话框组件实现基本的数据输入功能。
337 0
C/C++ Qt 自定义Dialog对话框组件应用
|
安全 Java 程序员
总结一下Qt内存泄漏检测与处理策略,并附个人写的C++单例类,用于内存自动释放
总结一下Qt内存泄漏检测与处理策略,并附个人写的C++单例类,用于内存自动释放
1096 0
C++函数中,两个自动释放内存的动态内存申请类
C++函数中,两个自动释放内存的动态内存申请类最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if free/delete,代码长而且不好管理 因此,利用C...
1205 0