你是否遇到过这样的问题:用编译器拖出一些控件放到对话框上,并合理安排好了位置;但编译运行,改变对话框的大小后,所有控件的位置都乱了,让人感觉非常糟糕。如果控件不太多,你可以尝试手写代码定位每个控件的位置,但若是控件数量以十或百为单位计数甚至更多,逐一为每个控件指定位置就非常麻烦了。

  本文提供一个宏,可以按照通常对话框的布局要求快速为每个控件布局,对话框大小改变时,控件的大小和位置都会随之而改变。改变控件位置和大小的代码都在宏内部,你只需了解宏的作用即可达到所需布局。

  注意,编写宏和测试环境为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,各个参数以宏的形式提供,非常容易了解,比起手写代码非常清晰。当然,如果想重新设计各个控件的布局,只需重新指定布局参数即可。

控件布局通用解决方案相关推荐

  1. android比较常用的布局,Android_九宫图比较常用的多控件布局(GridView)使用介绍,GridView跟ListView都是比较常用的 - phpStudy...

    九宫图比较常用的多控件布局(GridView)使用介绍 GridView跟ListView都是比较常用的多控件布局,而GridView更是实现九宫图的首选!本文就是介绍如何使用GridView实现九宫 ...

  2. 【Android 初学】3、控件布局初步

    Start Android 什么是控件布局 所谓的控件布局方法,就是指控制控件在Activity当中的位置.大小.颜色以及其他控件样式属性的方法. 控件的布局,在android中,有两种方法: 1.使 ...

  3. 修改WebBrowser控件的内核解决方案

    修改WebBrowser控件的内核解决方案 参考文章: (1)修改WebBrowser控件的内核解决方案 (2)https://www.cnblogs.com/sung/p/3391264.html ...

  4. 学习《GUI Qt4 编程》笔记-02-代码实现控件布局-设计师控件布局

      对话框,之所以被成为对话框,是因为它们为用户和应用程序之间提供了一种可以相互"交谈"的交互方式.   绝大多数的图形用户界面应用程序都带有一个有菜单栏.工具栏构成的主窗口以及几 ...

  5. android 控件布局(顶部、底部......) 留着自己用

    android 控件布局(顶部.底部......) 留着自己用 android:layout_above 将该控件的底部至于给定ID的控件之上 android:layout_below 将该控件的顶部 ...

  6. Android笔记之Android基本控件布局与Activity的生命周期

    前言 喜欢安卓里千奇百怪的app,酷炫的UI或者好玩的游戏.想知道那些软件是如何做的,为什么我在微博里发一条消息,就能一直存在网上,让别人看到?为什么我点击一个按钮就出现了一个效果,某个功能?为什么滑 ...

  7. 手把手教你写移动端瀑布流控件布局篇

    1.了解每个平台的基础的布局控件: Android:FrameLayout,LinearLayout,AbsoluteLayout(已废弃) (http://developer.android.com ...

  8. Android 控件布局常用属性

    <!--单个控件经常用到 android:id -- 为控件指定相应的ID android:text -- 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符 ...

  9. Android控件布局属性全解(一看就会)

    Android有太多的布局属性繁琐又晦涩,下面结合了网上很多资料汇总. 内容太多,可以Ctrl+F进行搜索 第一类:属性值为true或false android:layout_centerHrizon ...

最新文章

  1. TextInputLayout
  2. vs2019怎么调整字体大小_考研倒计时23天,答题卡怎么使用?来看看正确的使用方法吧!...
  3. Java各种对象(PO,BO,VO,DTO,POJO,DAO,Entity,JavaBean,JavaBeans)的区分
  4. jq鼠标移入移除事件
  5. Bob‘s Problem
  6. java 异常处理向处机制笔记
  7. IBM 重磅开源 Power 芯片指令集!国产芯迎来新机遇?
  8. 《JavaScript忍者秘籍》——1.3 跨浏览器注意事项
  9. 代理模式(Proxy)--静态代理
  10. c语言上机实验作业答案,第十二次C语言上机实验参考答案
  11. 做个简单的Java学生考勤系统04--签到功能的开发
  12. S3C2440开发板烧录笔记
  13. VMware12虚拟机中安装win7(安装好的解压版Win7_64-cl1.vmdk)
  14. 怎么彻底卸载cad2017_Win10系统怎么彻底卸载cad【图文教程】
  15. 不同转录组测序方法总结
  16. 我心中最敬业的天王 刘德华|分析天王近700多首歌曲
  17. 开源应用中心 | KodBox快捷高效的私有云在线文档管理系统
  18. Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作)
  19. 【图像处理 -1图像恢复】非线性过滤器修复图像
  20. SuperSocket.WebSocket WebSocketServer设置文本编码

热门文章

  1. LaTex科学论文写作
  2. VC知识库之应用控制
  3. QComboBox 设置下拉列表颜色
  4. 解决蓝牙耳机自动暂停播放音乐的问题
  5. rowid与rownum的含义是什么?
  6. Android系统版本在6.0+以上需要动态申请权限
  7. 【智哪儿评测】轻松玩转智能家居,萤石B1智家护卫传感套装评测
  8. ViewPager API
  9. 如何快速实现数组/字符串的逆序(用reverse函数实现)
  10. 生活随笔与读书笔记20140302