如何优雅的写UI——(5)选项卡功能实现
先在我们的选项卡可以说能用了,每个标签页都能点进去,但是这还远远没到能用的地步,比如说你把窗口最大化后。
立马就露出马脚了,所以这篇我们要先讲讲tabctrl的最基本的功能实现
改变选项卡大小
上图的原因就是主窗口在改变的大小的时候没有通知选项卡让他跟着主窗口一起变,所以我们现在通知选项卡一下
添加ON_WM_SIZE消息,实现函数
void CtabView::OnSize(UINT nType, int cx, int cy)
{
//CFormView::OnSize(nType, cx, cy); if (m_tab && m_tab.GetSafeHwnd())
{
m_tab.SetWindowPos (NULL, -, -, cx, cy,
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
}
}
在主窗体改变大小的时候,会时时通知选项卡,主窗体我已经变成多大了(cx,cy),你赶快跟上。
改变控件位置
选项卡现在已经可以跟着主窗体一起变了,但是发现没有,里面的控件的位置却没有变,如果里面的控件位置都没变,那我们最大化还有什么意义呢?所以我们还得通知子窗体里面的控件“子窗体大小已经改变了,你控件也赶快挪位置跟上。”
既然是子窗体里的控件,那肯定是要在子窗体去实现,但是一个子窗口会有很多控件,我们一个一个去取句柄然后再通知他们会不会很麻烦,当然麻烦,但是我们有简单方法。
GetWindow函数会给我们返回子窗口里所有控件ID,这样我们就不用一个一个找了。所以我们只需要一个循环就能改变控件位置和大小
HWND GetWindow(HWND hWnd,UNIT nCmd)。 参数说明:
hWnd:窗口句柄。这个函数要返回的窗口句柄是依据nCmd参数值相对于hWnd参数的关系。
nCmd:说明指定窗口与要获得句柄的窗口之间的关系。该参数值可以是下列之一:
GW_CHILD(&H5):如果指定窗口是父窗口,则获得的是在Tab序顶端的子窗口的句柄,否则为NULL。函数仅检查指定父窗口的子窗口,不检查继承窗口。 GW_ENABLEDPOPUP(&H6):(WindowsNT 5.0)返回的句柄标识了属于指定窗口的处于使能状态弹出式窗口(检索使用第一个由GW_HWNDNEXT 查找到的满足前述条件的窗口);
如果无使能窗口,则获得的句柄与指定窗口相同。 GW_HWNDFIRST(&H0):返回的句柄标识了在Z序最高端的相同类型的窗口。如果指定窗口是最高端窗口,则该句柄标识了在Z序最高端的最高端窗口;
如果指定窗口是顶层窗口,则该句柄标识了在z序最高端的顶层窗口:如果指定窗口是子窗口,则句柄标识了在Z序最高端的同属窗口。 GW_HWNDLAST(&H1):返回的句柄标识了在z序最低端的相同类型的窗口。如果指定窗口是最高端窗口,则该柄标识了在z序最低端的最高端窗口:
如果指定窗口是顶层窗口,则该句柄标识了在z序最低端的顶层窗口;如果指定窗口是子窗口,则句柄标识了在Z序最低端的同属窗口。 GW_HWNDNEXT(&H2):返回的句柄标识了在Z序中指定窗口下的相同类型的窗口。如果指定窗口是最高端窗口,则该句柄标识了在指定窗口下的最高端窗口:
如果指定窗口是顶层窗口,则该句柄标识了在指定窗口下的顶层窗口;如果指定窗口是子窗口,则句柄标识了在指定窗口下的同属窗口。 GW HWNDPREV(&H3):返回的句柄标识了在Z序中指定窗口上的相同类型的窗口。如果指定窗口是最高端窗口,则该句柄标识了在指定窗口上的最高端窗口;
如果指定窗口是顶层窗口,则该句柄标识了在指定窗口上的顶层窗口;如果指定窗口是子窗口,则句柄标识了在指定窗口上的同属窗口。 GW_OWNER(&H4):返回的句柄标识了指定窗口的所有者窗口(如果存在)。GW_OWNER与GW_CHILD不是相对的参数,没有父窗口的含义,如果想得到父窗口请使用GetParent()。
例如:例如有时对话框的控件的GW_OWNER,是不存在的。 返回值:如果函数成功,返回值为窗口句柄;如果与指定窗口有特定关系的窗口不存在,则返回值为NULL。 若想获得更多错误信息,请调用GetLastError函数。
POINT m_old;
创建一个chang函数并在OnSize中调用
void CDialog1::ChangeSize(/*CWnd * pWnd, int cx, int cy*/)
{
float fsp[];
POINT Newp; //获取现在对话框的大小
CRect recta;
GetClientRect(&recta); //取客户区大小
Newp.x=recta.right-recta.left;
Newp.y=recta.bottom-recta.top;
fsp[]=(float)Newp.x/m_old.x;
fsp[]=(float)Newp.y/m_old.y;
CRect Rect;
int woc;
CPoint OldTLPoint,TLPoint; //左上角
CPoint OldBRPoint,BRPoint; //右下角
HWND hwndChild=::GetWindow(m_hWnd,GW_CHILD); //列出所有控件 while(hwndChild)
{
woc=::GetDlgCtrlID(hwndChild);//取得ID
GetDlgItem(woc)->GetWindowRect(Rect);
ScreenToClient(Rect);
OldTLPoint = Rect.TopLeft();
TLPoint.x = long(OldTLPoint.x*fsp[]);
TLPoint.y = long(OldTLPoint.y*fsp[]);
OldBRPoint = Rect.BottomRight();
BRPoint.x = long(OldBRPoint.x *fsp[]);
BRPoint.y = long(OldBRPoint.y *fsp[]);
Rect.SetRect(TLPoint,BRPoint);
GetDlgItem(woc)->MoveWindow(Rect,TRUE);
hwndChild=::GetWindow(hwndChild, GW_HWNDNEXT);
}
m_old=Newp;
}
现在感觉好多了,中间的文本框字体需要另外的代码去改变它
实现关闭标签页功能
最后有没有发现,标签页上的按钮是没有反应的,这是我们没有实现这个按钮
添加一个MFC类CMFCTabCtrlEx,继承与CMFCTabCtrl
给CMFCTabCtrlEx类添加ON_WM_LBUTTONDOWN()事件,因为是动态创建选项卡,所以这个事件只能自己手写。
//.h class CMFCTabCtrlEx : public CMFCTabCtrl
{
DECLARE_DYNAMIC(CMFCTabCtrlEx) public:
CMFCTabCtrlEx();
virtual ~CMFCTabCtrlEx(); protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
};
//.cpp
// MFCTabCtrlEx.cpp : 实现文件
//
#include "stdafx.h"
#include "MFCTabCtrlEx.h"
// CMFCTabCtrlEx
IMPLEMENT_DYNAMIC(CMFCTabCtrlEx, CMFCTabCtrl)
CMFCTabCtrlEx::CMFCTabCtrlEx()
{
}
CMFCTabCtrlEx::~CMFCTabCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CMFCTabCtrlEx, CMFCTabCtrl)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void CMFCTabCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CMFCTabCtrl::OnLButtonDown(nFlags, point); // 获取Tab的数量
int n = GetTabsNum(); if (n == ) return; CRect rc; // 获取整个Tab区域
CalcRectEdit(rc);
GetTabsRect(rc);
// 获取当前选项卡窗口的指针
CWnd *pTabWnd = GetActiveWnd();
pTabWnd->GetClientRect(rc); int sel; // 获取当前选择的Tab
sel = GetActiveTab(); // 获取单个Tab区域
GetTabRect(sel, rc); // 获取单个Tab的最大宽度
int nWidth = GetTabMaxWidth(); // 获取关闭按钮的区域
CRect rcCloseBtn;
rcCloseBtn = GetTabCloseButton(); if (rcCloseBtn.PtInRect(point))
{
if(MessageBox(_T("确认关闭该标签页?"), _T("关闭提示"), MB_YESNO) == IDYES)
{
// 关闭Tab页关联窗口
pTabWnd->SendMessage(WM_CLOSE);
// 删除Tab
RemoveTab(sel);
}
} }
将主窗口选项卡基类替换为CMFCTabCtrlEx就完成了。
如何优雅的写UI——(5)选项卡功能实现的更多相关文章
- 如何优雅的写UI——(4)选项卡美化
现在做出来的选项卡实在太丑的,咱们怎么把他弄得好看一点呢 tabctrl是可以添加icon图标的,那派生与tabctrl的mfctabctrl肯定也能添加图标,他们两个添加图标的原理一样,但是还是有点 ...
- 如何优雅的写UI——(3)添加MFC选项卡
窗体创建完成,接下来我们讲讲控件的使用 首先在CFormView窗体下选项卡的成员变量,这里我选择MFC下的选项卡类库:CMFCTabCtrl class CtabView : public CFor ...
- 如何优雅的写UI——(2)MFC下基于CFormView的文档视图程序
在MFC中可以创建多种类型的窗口程序,如对话框程序.单文档结构程序(非文档/视图结构).单文档(文档/视图结构)以及多文档视图结构程序等. 在编写一般的小工具时,我们的首选显然是对话框程序,不过基于对 ...
- 如何优雅的写UI——(1)MFC六大核心机制-程序初始化
很多做软件开发的人都有一种对事情刨根问底的精神,例如我们一直在用的MFC,很方便,不用学太多原理性的知识就可以做出各种窗口程序,但喜欢钻研的朋友肯定想知道,到底微软帮我们做了些什么,让我们在它的框架下 ...
- 如何优雅的写UI——(6)内存泄漏
控件讲了这么久,其实我的程序有两个Bug不知道大家有没有发现,这两个Bug都不会报错,对程序运行来说都没有阻碍,但是这种Bug对整个代码来说是一个很大的安全隐患. 什么是内存泄漏 内存泄漏(Memor ...
- 关于如何写UI及屏幕适配的一些技巧
因为公司开启了一个新的iOS项目, 所以近期比较忙, 没有更新博客,今天打算总结一下关于UI布局及屏幕适配的一些实战技巧,尤其使用纯代码,会对提升效率及代码易于维护等方面有明显帮助,这里提到的没有使用 ...
- 如何优雅的写一篇安利文-以Sugar ORM为例
前言 我最近喜欢把写的十分优美的技术文章叫做安利文.首先,文章必须是原创而非软广:其次,阅读之后不仅能快速吸纳技术要点并入门开发,还能感同身受的体会作者热情洋溢的赞美和急于分享心得体验的心情,让人感觉 ...
- 【Xamarin挖墙脚系列:代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧(转)】
正愁如何选择构建项目中的视图呢,现在官方推荐画板 Storybord...但是好像 xib貌似更胜一筹.以前的老棒子总喜欢装吊,用代码写....用代码堆一个HTML页面不知道你们尝试过没有.等页面做出 ...
- 针对SO交期回写的工厂日历功能调整
针对所有SO回写的交期,在最终写入SAP系统时,如果交期落在周日的,则自动往后延迟一天到周一,前期已经开发的长节假日UI维护的功能不变(按照UI的开始和结束时间跳过此段时间不规划). 当加1天时落在国 ...
随机推荐
- caffe(4) 激活层(Activation Layers)及参数
在激活层中,对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的.从bottom得到一个blob数据输入,运算后,从top输入一个blob数据.在运算过程中,没有改变数据的大小,即输入 ...
- [笔记-图论]Floyd
用于可带负权的多源最短路 时间复杂度O(n^3) 注意一定不要给Floyd一个带负环的图,不然就没有什么意义了(最短路不存在) 模板 // Floyd // to get minumum distan ...
- win10如何设置开机自动启动热点WIFI?
1.编写脚本文件(先新建txt文件,编写代码内容netsh wlan start hostednetwork,最后重命名成HotSpot.bat):文件名称:HotSpot.bat,代码内容: net ...
- CSU 1446 Modified LCS 扩展欧几里得
要死了,这个题竟然做了两天……各种奇葩的错误…… HNU的12831也是这个题. 题意: 给你两个等差数列,求这两个数列的公共元素的数量. 每个数列按照以下格式给出: N F D(分别表示每个数列的长 ...
- C语言调试小技巧
经常看到有人介绍一些IDE或者像gdb这样的调试器的很高级的调试功能,也听人说过有些牛人做工程的时候就用printf来调试,不用特殊的调试器.特别是在代码经过编译器一些比较复杂的优化后,会变得“难以辨 ...
- CMSIS-RTOS 简介
CMSIS-RTOS API是基于Arm®Cortex®-M处理器的设备的通用RTOS接口.CMSIS-RTOS为需要RTOS功能的软件组件提供标准化API,从而为用户和软件行业带来了巨大的好处. C ...
- ECNUOJ 2142 放书
放书 Time Limit:1000MS Memory Limit:65536KBTotal Submit:409 Accepted:173 Description 你要把一叠书放进一些箱子里面,为 ...
- BZOJ 3236 莫队+树状数组
思路: 莫队+树状数组 (据说此题卡常数) yzy写了一天(偷笑) 复杂度有点儿爆炸 O(msqrt(n)logn) //By SiriusRen #include <cmath> #in ...
- 网站及监控利器 Pandora FMS使用体验
Pandora FMS 是一个 开源的应用程序 ,用来监测网站的各种活动,它可以收到实时的监测报告,并发送到你指定的邮箱,也可以通过e-mail, SMS 发送. 650) this.width=65 ...
- BFS(广度优先搜索)
Catch That Cow Farmer John has been informed of the location of a fugitive cow and wants to catch he ...