如何设置对话框的最大(小)高度与宽度

关于如何设置对话框的最大(小)高度与宽度,网上有很多blog介绍了这个方面,我觉得有一篇写的比较好,先扒过来凑点字数


以下内容转自http://www.youranshare.com/push/code/win-c-cpp/427.html:

在MFC中,没有像QT那样的函数可以直接通过某个函数就可以完成对窗口的最大最小SIZE信息进行设置,但是这么强大的MFC,这种弱鸡的问题肯定也就不是问题,这里给大家分享三个方法来完成限定窗口大小的处理。

方法一:响应窗口 WM_SIZE 消息(不推荐)

WM_SIZE 消息是当窗口大小发生改变发送的,所以如果要在这个窗口中限制窗口大小的话,你就需要重新计算窗口的大小信息,代码如下:

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
 CFrameWnd::OnSize(nType, cx, cy);
 // TODO: 在此处添加消息处理程序代码
 CRect rect ;
 BOOL IsNeedReset = FALSE;
 GetWindowRect(&rect);
 if(cx<640){
  IsNeedReset = TRUE;
  rect.right = rect.left+640;
 }
 if(cy<480){
  IsNeedReset = TRUE;
  rect.bottom = rect.top+480;
 }
 if(IsNeedReset){
  SetWindowPos(NULL,
               rect.left,rect.top,rect.Width(),rect.Height(),
               SWP_SHOWWINDOW|SWP_NOMOVE);
 }
}

由于OnSize是在窗口大小已经改变后才执行的,所以如果在代码种再次执行窗口的大小调整将会导致闪烁的问题,所以这种方法不推荐。

方法二:响应窗口 WM_SIZEING 消息(较为推荐)

WM_SIZEING消息是当窗口大小正在发生改变的时候发送的,所以可以在此消息种限制改变的大小从而达到限制窗口大小的目的,但是对于一个窗口来说,其改变大小的方式有很多,例如从窗口的四个方向都可以改变其大小,WM_SIZEING 消息有一个SIDE参数其描述了改变方向边界位置,这里为了简单,不去处理这个参数,如果你从左侧调整大小,可以发现很好玩的状态。

void CMainFrame::OnSizing(UINT fwSide, LPRECT pRect)
{
 //这里还需要知道 dwSide的信息,就是从那个方向进行变动
 //这里省略了,不建议使用这种方法
 //如果不处理方向,你可以试试看窗口从左下角 变小,很好玩的
 if(pRect->right-pRect->left<=840){   pRect->right = pRect->left+840;
 }
 if(pRect->bottom-pRect->top<=480){   pRect->bottom = pRect->top+480;
 }
 //
 CFrameWnd::OnSizing(fwSide, pRect);
 // TODO: 在此处添加消息处理程序代码
}

WM_SIZEING 这种处理是可行的,不会出现闪烁的问题,但是需要处理一个dwSide的参数,处理起来较为复杂。

方法三:响应窗口 WM_GETMINMAXINFO消息(推荐)

当一个窗口的位置或者大小将要改变的时候将会发送一个WM_GETMINMAXINFO的窗口消息,应用程序可以使用这个消息来重设窗口的默认最大化大小和位置,或者窗口的默认最小或最大拖放大小。

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
 //调整最小高度与宽度,如果需要的话
 lpMMI->ptMinTrackSize.x = 640;
 lpMMI->ptMinTrackSize.y = 480;
 //调整最大高度与宽度,如果需要的话
 lpMMI->ptMaxTrackSize.x = 1366;
 lpMMI->ptMaxTrackSize.y = 768;

 CFrameWnd::OnGetMinMaxInfo(lpMMI);
}

WM_GETMINMAXINFO的处理简单易懂,无需繁杂的计算即可限定窗口的拖放大小等信息。


下面我接着写自己遇到的问题。我的对话框是Popup无边框对话框,本打算用上面的二或者三方法解决限制窗口大小的问题,却发现对话框接收不到WM_SIZING和WM_GETMINMAXINFO消息,而用WM_SIZE解决方案有有点丑陋,于是想到了能不能响应WM_WINDOWPOSCHANGING消息解决,还好,可以这此消息里设置对话框的大小:

	void OnWindowPosChanging(LPWINDOWPOS lpWndPos)
	{
		if (m_iMaxWidth != 0 && lpWndPos->cx > m_iMaxWidth)
		{
			lpWndPos->cx = m_iMaxWidth;
		}

		if (m_iMaxHeight != 0 && lpWndPos->cy > m_iMaxHeight)
		{
			lpWndPos->cy = m_iMaxHeight;
		}
	}

结论嘛就是在无边框对话框是不响应 WM_SIZING和 WM_GETMINMAXINFO消息的(我想这是因为没有Resizing属性导致),但是呢可以使用WM_WINDOWPOSCHANGING消息解决限制对话框大小问题。我有回头翻了下E文:

For a window with the WS_OVERLAPPED or WS_THICKFRAME style, the DefWindowProc function sends theWM_GETMINMAXINFO message to the window. This is done to validate the new size and position of the window and to enforce the CS_BYTEALIGNCLIENT and CS_BYTEALIGNWINDOW client styles. By not passing the WM_WINDOWPOSCHANGING message to the DefWindowProc function, an application can override these defaults.

While this message is being processed, modifying any of the values in WINDOWPOS affects the window's new size, position, or place in the Z order. An application can prevent changes to the window by setting or clearing the appropriate bits in the flags member of WINDOWPOS.

根据上面所写,只有窗口具有WS_OVERLAPPED 或者 WS_THICKFRAME时,才会收到 WM_GETMINMAXINFO消息。另外也可以清除WINDOWPOS成员flags某些bit位阻止窗口改变。例如上面的代码也可以这样写:

	void OnWindowPosChanging(LPWINDOWPOS lpWndPos)
	{
		if (lpWndPos->cx > m_iMaxWidth || lpWndPos->cy > m_iMaxHeight)
		{
			lpWndPos->flags |= SWP_NOSIZE;
		}
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值