mfc比较复杂的界面如何做到控件随窗口变化大小

qq_35549593 2016-09-26 09:50:58

这个界面

if (pWnd)
{
CRect rect;
pWnd->GetWindowRect(&rect); //获取控件变化前的大小
ScreenToClient(&rect);//将控件大小转换为在对话框中的区域坐标
rect.left=rect.left*cx/m_rect.Width();//调整控件大小 ,cx/m_rect.Width()为对话框在横向的变化比例
rect.right=rect.right*cx/m_rect.Width(); //cx存储的是变化后的宽度,cy存储的是变化后的高度
rect.top=rect.top*cy/m_rect.Height(); //m_rect.height()表示的是变化前主窗体的高度
rect.bottom=rect.bottom*cy/m_rect.Height();
pWnd->MoveWindow(rect);//设置控件大小
}

这样的话缩小的时候控件会乱
用easysize的话控件太多不好处理关系
应该怎样做到控件随窗口变化大小。
...全文
1986 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2016-09-29
  • 打赏
  • 举报
回复
CRect m_CtrlRcOrig[10]; 可以 到 10个 控件。
schlafenhamster 2016-09-29
  • 打赏
  • 举报
回复

#define USE_CLIENT
void CScalerDlg::GetCtrlClientRects()
{
	int iCount = 0;
// right and bottom not used
	CWnd* pWnd = GetTopWindow();// child window
	CRect rc;
	while(pWnd != NULL) 
	{ 
		pWnd->GetWindowRect(&rc);
#ifdef USE_CLIENT
		ScreenToClient(&rc); // Screen dlg's window to dlg's Client. 
#endif
		m_CtrlRcOrig[iCount++]=rc;
		pWnd = pWnd->GetNextWindow();
	}
}
//

BOOL CScalerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
// TODO: Add extra initialization here
// get dlg orignal W H
	CRect rc;
	GetClientRect(&rc);
	m_dlgW=rc.Width();
	m_dlgH=rc.Height();
//	afxDump << m_dlgW << ";" << m_dlgH << "\n";// 720;   450
	GetWindowRect(&rc);//            (L 0, T 0, R 730, B 488)
//	afxDump << rc << "\n";
	m_s2cOffsetX=(rc.Width()-m_dlgW)/2;
	m_s2cOffsetY=rc.Height()-m_s2cOffsetX-m_dlgH;
//	afxDump << m_s2cOffsetX << ";" << m_s2cOffsetY << "\n";// 5;33
//  5=Border; 33=caption height=28+border=5
	m_pStatic= new CStatic;
	m_pStatic->Create(TEXT("Hello"),WS_CHILD|WS_VISIBLE|SS_LEFT, CRect(10,10,200,100),this,0x0201);
	m_pStatic->ModifyStyle(0,SS_OWNERDRAW);
	m_pStatic->ShowWindow(SW_SHOW);//TRUE);
// init rects
	GetCtrlClientRects();
//
	return TRUE;  // return TRUE  unless you set the focus to a control
}
//
void CScalerDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	double xRate=(double)cx/(double)m_dlgW;
	double yRate=(double)cy/(double)m_dlgH;
	int iCount=0;
	CRect rcNow(0);
	CWnd* pWnd = GetTopWindow();
	while(pWnd != NULL) 
	{ 
#ifndef USE_CLIENT
		rcNow.left  =(int)((m_CtrlRcOrig[iCount].left-m_s2cOffsetX)*xRate);
		rcNow.right =(int)((m_CtrlRcOrig[iCount].right-m_s2cOffsetX)*xRate);
		rcNow.top   =(int)((m_CtrlRcOrig[iCount].top-m_s2cOffsetY)*yRate);
		rcNow.bottom=(int)((m_CtrlRcOrig[iCount].bottom-m_s2cOffsetY)*yRate);
#else // has ScreenToClient(&rc); // Screen dlg's window to dlg's Client. 
		rcNow.left  = (int)(m_CtrlRcOrig[iCount].left*xRate);
		rcNow.right = (int)(m_CtrlRcOrig[iCount].right*xRate);
		rcNow.top   = (int)(m_CtrlRcOrig[iCount].top*yRate);
		rcNow.bottom= (int)(m_CtrlRcOrig[iCount].bottom*yRate);
#endif
		pWnd->MoveWindow(&rcNow,TRUE);
		pWnd = pWnd->GetNextWindow();
		iCount++;
	}
}
// in .h
protected:
	HICON m_hIcon;
	int   m_dlgW;
	int   m_dlgH;
	int   m_s2cOffsetX;
	int   m_s2cOffsetY;
	CRect m_CtrlRcOrig[10];
	CStatic *m_pStatic;
soundbird 2016-09-29
  • 打赏
  • 举报
回复
用movewindow没有问题,但是有没有想过,控件大小改变了,而控件上的文字是否也做需要改变,不然自适应的变动只会造成视觉的冲突。
red-fly 2016-09-28
  • 打赏
  • 举报
回复
当然这种简单的变化可能会导致你不想看到的效果,所以实际上,你需要对控件进行分类,对不同类型的控件进行不同的处理,比如通常来说文本框只会变长或者变短,而高低不会变化,按钮大小不变,但是位置可能会改变,富文本框或者用于显示多行内容的控件会大小改变
red-fly 2016-09-28
  • 打赏
  • 举报
回复
在启动时获取所有控件的大小及位置,这个称为原始值A,以及窗口大小B,后面窗口大小改变时,全部以此为基础进行变化: m_btn1.GetWindowRect(&rect); ScreenToClient(&rect); rect = A * cx(cy) / B; MoveWindow( rect );
schlafenhamster 2016-09-27
  • 打赏
  • 举报
回复
对话框只有一个 按钮:

init:
//
	CRect rc;
	GetClientRect(&rc);

	m_dlgW=rc.Width();
	m_dlgH=rc.Height();

	afxDump << m_dlgW << ";" << m_dlgH << "\n";// 720;450
	m_Button1.GetWindowRect(m_btRectOrig);
	afxDump << m_btRectOrig << "\n";//  (L 244, T 148, R 460, B 240)
	ScreenToClient(&m_btRectOrig); // 
	afxDump << m_btRectOrig << "\n";//  (L 239, T 115, R 455, B 207)
。。。。。
void CScalerDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	double xRate=(double)cx/(double)m_dlgW;
	double yRate=(double)cy/(double)m_dlgH;
//	afxDump << xRate << ";" << xRate << "\n";
	if(::IsWindow(m_Button1.m_hWnd))
	{
		CRect rcNow;
		rcNow.left=(int)(m_btRectOrig.left*xRate);
		rcNow.right=(int)(m_btRectOrig.right*xRate);
		rcNow.top=(int)(m_btRectOrig.top*yRate);
		rcNow.bottom=(int)(m_btRectOrig.bottom*yRate);
		afxDump << rcNow << "\n";
// 
		m_Button1.MoveWindow(&rcNow);
	}
}
schlafenhamster 2016-09-27
  • 打赏
  • 举报
回复
ScreenToClient(&rect);//将控件大小转换为在对话框中的区域坐标 这句没错。 你的 代码 要 放 OnSize 中, pWnd->GetWindowRect(&rect); //获取控件变化前的大小 要在 init 里 OnSize (的 cx,cy)是 当前客户区。 如 OnInitDialog() CRect rc; GetClientRect(&rc); // 对话框 原 W H m_dlgW=rc.Width(); m_dlgH=rc.Height(); afxDump << m_dlgW << ";" << m_dlgH << "\n";// 720;450 // 按钮 原 rect m_Button1.GetWindowRect(m_btRectOrig); afxDump << m_btRectOrig << "\n";// (L 244, T 148, R 460, B 240) ScreenToClient(&m_btRectOrig); // afxDump << m_btRectOrig << "\n";// (L 239, T 115, R 455, B 207) 。。。
大树学长 2016-09-27
  • 打赏
  • 举报
回复
简单点弄,一个界面初始大小显示和一个最大化显示,设置两种控件的摆放和大小,不一定弄渐变显示
阿源是少年 2016-09-26
  • 打赏
  • 举报
回复
其实可以自己实现一个布局管理器,如盒子布局HBoxLayout,VBoxLayout,其作用就是调整它所管理的控件坐标,内部实现是SetWindowPos,每添加一个控件就手动AddWidget(HWND)当然这些接口都需要你自己实现,很简单。
赵4老师 2016-09-26
  • 打赏
  • 举报
回复
WPF ?
qq_35549593 2016-09-26
  • 打赏
  • 举报
回复

就是会变成这个样子
schlafenhamster 2016-09-26
  • 打赏
  • 举报
回复
“这样的话缩小的时候控件会乱” 不明白 !
qq_35549593 2016-09-26
  • 打赏
  • 举报
回复
上面那个不就是吗,缩小时问题很大应该怎么计算啊
crjwlaq 2016-09-26
  • 打赏
  • 举报
回复
onsize中计算相对位置 然后movewindow挪过去
满衣兄 2016-09-26
  • 打赏
  • 举报
回复
http://www.codeproject.com/Articles/125068/MFC-C-Helper-Class-for-Window-Resizing http://www.codeproject.com/Articles/34292/Helper-Class-for-Resizable-MFC-Dialogs
qq_35549593 2016-09-26
  • 打赏
  • 举报
回复
加上ClientToScreen(&rect); 之后就直接没有控件了
schlafenhamster 2016-09-26
  • 打赏
  • 举报
回复
pWnd->MoveWindow(rect);//这个 rect 必须是 Screen 坐标,你 ScreenToClient(&rect); 后 没有 再 转回去!
hurryboylqs 2016-09-26
  • 打赏
  • 举报
回复
这是MFC比较蛋疼的地方,没有布局管理器,你可以参考下duilib的布局管理器,自己写一个
三岁、就很帅 2016-09-26
  • 打赏
  • 举报
回复
OnSize里面 SetWindowPos的参数用Rect 的长跟宽
加载更多回复(1)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧