控件布局通用解决方案
来源:互联网 发布:acr软件下载 编辑:程序博客网 时间:2024/04/27 00:16
你是否遇到过这样的问题:用编译器拖出一些控件放到对话框上,并合理安排好了位置;但编译运行,改变对话框的大小后,所有控件的位置都乱了,让人感觉非常糟糕。如果控件不太多,你可以尝试手写代码定位每个控件的位置,但若是控件数量以十或百为单位计数甚至更多,逐一为每个控件指定位置就非常麻烦了。
本文提供一个宏,可以按照通常对话框的布局要求快速为每个控件布局,对话框大小改变时,控件的大小和位置都会随之而改变。改变控件位置和大小的代码都在宏内部,你只需了解宏的作用即可达到所需布局。
注意,编写宏和测试环境为XP + VC++6.0SP6 + MFC,其他编译环境可能需对宏稍加修改,我相信你有这个实力。
// CtrlId : 控件ID// LeftChangeMode : 0:与窗口客户区左边的距离不变; 1:按比例变化; 2:保持控件宽度不变;// RightChangeMode : 0:与窗口客户区右边的距离不变; 1:按比例变化; 2:保持控件宽度不变;// TopChangeMode : 0:与窗口客户区上边的距离不变; 1:按比例变化; 2:保持控件高度不变;// BottomChangeMode : 0:与窗口客户区下边的距离不变; 1:按比例变化; 2:保持控件高度不变;#ifndef AUTO_SET_CONTROL_POS// LeftChangeMode取值宏定义#define LEFT_CHANGE_MODE_FIXED_LEFTPADDING 0#define LEFT_CHANGE_MODE_RATIO 1#define LEFT_CHANGE_MODE_FIXED_WIDTH 2// RightChangeMode取值宏定义#define RIGHT_CHANGE_MODE_FIXED_RIGHTPADDING 0#define RIGHT_CHANGE_MODE_RATIO 1#define RIGHT_CHANGE_MODE_FIXED_WIDTH 2// TopChangeMode取值宏定义#define TOP_CHANGE_MODE_FIXED_TOPPADDING 0#define TOP_CHANGE_MODE_RATIO 1#define TOP_CHANGE_MODE_FIXED_HEIGHT 2// BottomChangeMode取值宏定义#define BOTTOM_CHANGE_MODE_FIXED_LEFEPADDING 0#define BOTTOM_CHANGE_MODE_RATIO 1#define BOTTOM_CHANGE_MODE_FIXED_HEIGHT 2#define AUTO_SET_CONTROL_POS(CtrlId, LeftChangeMode, RightChangeMode, TopChangeMode, BottomChangeMode)\{\static int nFirstCtrlId = -1;\static CRect rectLastClientWindow;\static CRect rectLastClientWindowTmp;\if (-1 == nFirstCtrlId)\{\nFirstCtrlId = CtrlId;\}\if (nFirstCtrlId == CtrlId)\{\rectLastClientWindowTmp = rectLastClientWindow;\}\rectLastClientWindow.right = cx;\rectLastClientWindow.bottom = cy;\CWnd *pWndDlgItem = GetDlgItem(CtrlId);\if (pWndDlgItem)\{\CRect rectDlgItem;\pWndDlgItem->GetWindowRect(rectDlgItem);\ScreenToClient(rectDlgItem);\\static int nDefaultLeftPadding_##CtrlId = rectDlgItem.left;\static float fDefaultLeftRatio_##CtrlId = (float)rectDlgItem.left\/ rectLastClientWindowTmp.right;\static int nDefaultRightPadding_##CtrlId = rectLastClientWindowTmp.right\- rectDlgItem.right;\static float fDefaultRightRatio_##CtrlId = (float)rectDlgItem.right\/ rectLastClientWindowTmp.right;\static int nDefaultCtrlWidth_##CtrlId = rectDlgItem.right - rectDlgItem.left;\int nXChangeMode = (LeftChangeMode << 8) + RightChangeMode;\\static int nDefaultTopPadding_##CtrlId = rectDlgItem.top;\static float fDefaultTopRatio_##CtrlId = (float)rectDlgItem.top\/ rectLastClientWindowTmp.bottom;\static int nDefaultBottomPadding_##CtrlId = rectLastClientWindowTmp.bottom\- rectDlgItem.bottom;\static float fDefaultBottomRatio_##CtrlId = (float)rectDlgItem.bottom\/ rectLastClientWindowTmp.bottom;\static int nDefaultCtrlHeight_##CtrlId = rectDlgItem.bottom - rectDlgItem.top;\int nYChangeMode = (TopChangeMode << 8) + BottomChangeMode;\\if (0x0000 == nXChangeMode)\{\rectDlgItem.right = cx - nDefaultRightPadding_##CtrlId;\}\else if (0x0001 == nXChangeMode)\{\rectDlgItem.right = fDefaultRightRatio_##CtrlId * cx;\}\else if (0x0002 == nXChangeMode)\{\/*这里不用更改*/\}\else if (0x0100 == nXChangeMode)\{\rectDlgItem.left = fDefaultLeftRatio_##CtrlId * cx;\rectDlgItem.right = cx - nDefaultRightPadding_##CtrlId;\}\else if (0x0101 == nXChangeMode)\{\rectDlgItem.left = fDefaultLeftRatio_##CtrlId * cx;\rectDlgItem.right = fDefaultRightRatio_##CtrlId * cx;\}\else if (0x0102 == nXChangeMode)\{\rectDlgItem.left = fDefaultLeftRatio_##CtrlId * cx;\rectDlgItem.right = rectDlgItem.left + nDefaultCtrlWidth_##CtrlId;\}\else if (0x0200 == nXChangeMode)\{\rectDlgItem.right = cx - nDefaultRightPadding_##CtrlId;\rectDlgItem.left = rectDlgItem.right - nDefaultCtrlWidth_##CtrlId;\}\else if (0x0201 == nXChangeMode)\{\rectDlgItem.right = fDefaultRightRatio_##CtrlId * cx;\rectDlgItem.left = rectDlgItem.right - nDefaultCtrlWidth_##CtrlId;\}\else if (0x0202 == nXChangeMode)\{\/*这里不用更改*/\}\\\if (0x0000 == nYChangeMode)\{\rectDlgItem.bottom = cy - nDefaultBottomPadding_##CtrlId;\}\else if (0x0001 == nYChangeMode)\{\rectDlgItem.bottom = fDefaultBottomRatio_##CtrlId * cy;\}\else if (0x0002 == nYChangeMode)\{\/*这里不用更改*/\}\else if (0x0100 == nYChangeMode)\{\rectDlgItem.top = fDefaultTopRatio_##CtrlId * cy;\rectDlgItem.bottom = cy - nDefaultBottomPadding_##CtrlId;\}\else if (0x0101 == nYChangeMode)\{\rectDlgItem.top = fDefaultTopRatio_##CtrlId * cy;\rectDlgItem.bottom = fDefaultBottomRatio_##CtrlId * cy;\}\else if (0x0102 == nYChangeMode)\{\rectDlgItem.top = fDefaultTopRatio_##CtrlId * cy;\rectDlgItem.bottom = rectDlgItem.top + nDefaultCtrlHeight_##CtrlId;\}\else if (0x0200 == nYChangeMode)\{\rectDlgItem.bottom = cy - nDefaultBottomPadding_##CtrlId;\rectDlgItem.top = rectDlgItem.bottom - nDefaultCtrlHeight_##CtrlId;\}\else if (0x0201 == nYChangeMode)\{\rectDlgItem.bottom = fDefaultBottomRatio_##CtrlId * cy;\rectDlgItem.top = rectDlgItem.bottom - nDefaultCtrlHeight_##CtrlId;\}\else if (0x0202 == nYChangeMode)\{\/*这里不用更改*/\}\pWndDlgItem->MoveWindow(rectDlgItem);\}\}#endif
使用时,只需在对话框的WM_SIZE消息处理函数中加上“AUTO_SET_CONTROL_POS(CtrlId, LeftChangeMode, RightChangeMode, TopChangeMode, BottomChangeMode)”即可,各个参数含义见宏定义的头部注释。对话框大小改变,就会自动修改指定控件的位置和大小。
上图是测试中MFC控件初化的位置,下图为修改控件大小后的布局:
代码中所作的处理如下:
void CDialogApplicationDlg::OnSize(UINT nType, int cx, int cy) {CDialog::OnSize(nType, cx, cy);AUTO_SET_CONTROL_POS( IDC_EDIT1, LEFT_CHANGE_MODE_FIXED_LEFTPADDING, RIGHT_CHANGE_MODE_FIXED_RIGHTPADDING, TOP_CHANGE_MODE_FIXED_TOPPADDING, BOTTOM_CHANGE_MODE_FIXED_HEIGHT);AUTO_SET_CONTROL_POS(IDC_RICHEDIT1, LEFT_CHANGE_MODE_FIXED_LEFTPADDING, RIGHT_CHANGE_MODE_FIXED_RIGHTPADDING, TOP_CHANGE_MODE_FIXED_TOPPADDING, BOTTOM_CHANGE_MODE_FIXED_LEFEPADDING);AUTO_SET_CONTROL_POS( IDOK, LEFT_CHANGE_MODE_FIXED_WIDTH, RIGHT_CHANGE_MODE_FIXED_RIGHTPADDING, TOP_CHANGE_MODE_FIXED_TOPPADDING, BOTTOM_CHANGE_MODE_FIXED_HEIGHT);AUTO_SET_CONTROL_POS( IDCANCEL, LEFT_CHANGE_MODE_FIXED_WIDTH, RIGHT_CHANGE_MODE_FIXED_RIGHTPADDING, TOP_CHANGE_MODE_FIXED_TOPPADDING, BOTTOM_CHANGE_MODE_FIXED_HEIGHT);AUTO_SET_CONTROL_POS( IDC_STATIC, LEFT_CHANGE_MODE_FIXED_LEFTPADDING,RIGHT_CHANGE_MODE_FIXED_WIDTH, TOP_CHANGE_MODE_FIXED_HEIGHT, BOTTOM_CHANGE_MODE_FIXED_LEFEPADDING);AUTO_SET_CONTROL_POS( IDC_BUTTON1, LEFT_CHANGE_MODE_FIXED_WIDTH, RIGHT_CHANGE_MODE_FIXED_RIGHTPADDING, TOP_CHANGE_MODE_FIXED_HEIGHT, BOTTOM_CHANGE_MODE_FIXED_LEFEPADDING);}每个控件调用一次AUTO_SET_CONTROL_POS,各个参数以宏的形式提供,非常容易了解,比起手写代码非常清晰。当然,如果想重新设计各个控件的布局,只需重新指定布局参数即可。
- 控件布局通用解决方案
- 控件布局通用解决方案
- Flutter进阶—通用布局控件
- 窗口控件透明的通用解决方案
- WindowsForm多线程设置控件通用解决方案
- Android(UI)布局(文件)控件标签的通用属性
- 通用控件
- 通用控件
- 布局解决方案
- 布局解决方案-居中布局
- 响应式布局通用
- Android通用布局UniversalLayout
- css布局通用类
- 天路CRM通用解决方案
- 天路CRM通用解决方案
- 移动办公通用解决方案
- C++ LOG 通用解决方案
- opacity通用解决方案
- YCbCr 转 RGB 保存成JPEG文件
- 最好的shell入门教程
- centos wget
- centOS install mysql
- DM6446开发攻略——u-boot-1.3.4移植(1)
- 控件布局通用解决方案
- linux之udev
- [jtable]多个源码实例
- 软件工程概述 - 企业架构 - IT企业做大做强之根本
- C语言类型转换 .
- 数据库损坏如何处理?
- 进程共享同内存
- 快速排序算法之我见(附上C代码)
- Android编程之仿微信显示更多文字的View