窗口变化相关消息 OnSize、OnSizing和OnGetMinMaxInfo


 最近用到窗口变化的一些东西,遇到几个相关的消息函数,简要分析,作为备忘。

3个消息分别是:WM_SIZE、WM_SIZING、WM_GETMINMAXINFO;分别对应相应的处理函数:OnSize、OnSizing、OnGetMinMaxInfo。

当窗口大小发生变化时,响应的顺序依次是:WM_GETMINMAXINFO-->WM_SIZING-->WM_SIZE。

 

OnGetMinMaxInfo

这个函数在窗口初始化的时候会被调用一次,当窗口大小发生改变的时候也会被调用。利用这个函数,可以比较方便的实现窗口最大最小尺寸的控制。

参数lpMMI是一个结构体指针,其中包含了有关窗口的最大化大小和位置以及最小、最大跟踪大小的信息。

使用这个函数控制窗口最小尺寸的示例的代码如下:

[cpp] view plaincopy
 
  1. void CXXXDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)   
  2. {  
  3.     lpMMI->ptMinTrackSize.x = 500;   //x宽度  
  4.     lpMMI->ptMinTrackSize.y = 100;   //y高度  
  5.   
  6.     CDialog::OnGetMinMaxInfo(lpMMI);  
  7. }  


以上代码可以使得窗口大小变化时,最小宽度为500px,最小高度为100px。

 

OnSizing

这个函数在窗口大小发生变化时被调用。在这个函数里,也可以控制窗口的最大最小尺寸,但是没有OnGetMinMaxInfo方便。

[cpp] view plaincopy
 
  1. void CXXXDlg::OnSizing(UINT fwSide, LPRECT pRect)   
  2. {  
  3.     if ((pRect->right - pRect->left) < 500)  
  4.     {  
  5.         //return ;  //直接return是无效的,窗口大小还是会改变  
  6.         pRect->right = pRect->left + 500;  
  7.     }  
  8.   
  9.     CDialog::OnSizing(fwSide, pRect);  
  10. }  

用上面的方法,如果是从右边改变大小,可以达到想要的效果,但是从左边改变大小,虽然大小可以控制在最小500,但是当达到最小宽度后,再缩小,会发现整个窗口往右移动了,原因是代码中的pRect->right = pRect->left + 500;这句是针对left来改变right的,所以left移动了,right也移动了,看上去就像是这个窗口右移了。所以针对这种情况又要另外做相应的处理。

 

OnSize

这个函数会在窗口大小改变结束后被调用,通常会在这个函数里重新摆放各个控件的位置及大小。用这个函数暂时没有找到什么办法可以控制窗口的最大最小大小。

 

分享到: 
  • 上一
  •  如果想要实现窗口全屏,并且还有状态栏,会出现问题,那就是OnGetMinMaxInfo函数的作用。你可以试一下,如果把这个函数去掉,则当你按下工具栏中的全屏显示按钮时,框架视图确实变大了,但没有想象的那样实现全屏显示,底边留下一个状态栏——一个有些发育不良的全屏显示窗口。为什么会这样呢?经过调试后,发现问题出在WM_GETMINMAXINFO消息的处理上。在Windows中,无论什么时候以何种方式改变窗口的尺寸或大小,是拖拽窗口边缘也好,或是在代码中调用改变窗口尺寸的函数也好,总之不管你用什么方法,Windows都会首先发送WM_GETMINMAXINFO消息。这个消息的意思是说:“嘿,如果你要强迫我的尺寸变大或变小,就附上详细的MINMAXINFO结构信息,否则我用默认值处理。”大多数应用程序都不用显式处理这个 WM_GETMINMAXINFO消息(也就是说让DefWindowProc窗口过程进行缺省处理),而Windows在进行缺省处理时是不会让一个窗口视图比屏幕还大的,所以我们会碰上前面讲的那个问题。解决的方法是:不要让Windows对WM_GETMINMAXINFO消息进行缺省处理,而是由我们自己处理,方法如下:

    void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpmmi)
    {
    CSize sz = FullScreenHandler.GetMaxSize();
    lpmmi->ptMaxSize = CPoint(sz);
    lpmmi->ptMaxTrackSize = CPoint(sz);
    }

    这里CFullScreenHandler.GetMaxSize 返回的最大尺寸要比整个屏幕稍微大一点。

    CSize CFullScreenHandler::GetMaxSize()
    {
    CRect rc(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
    rc.InflateRect(10,50);
    return rc.Size();
    }

    MINMAXINFO的结构体:
    typedef struct {
    POINT ptReserved; //不用
    POINT ptMaxSize; //最大范围
    POINT ptMaxPosition; //最大的放置点
    POINT ptMinTrackSize; //最小拖动范围
    POINT ptMaxTrackSize; //最大拖动范围
    } MINMAXINFO;

    最后两个字段的意思:
    你用鼠标拖动时,它会实时地跟着你的鼠标改变窗口大小,当达到一定值之后,  
    你再拖它,它也不会变小,这时这个值就是上面说的the   minimum   tracking   width
posted @ 2013-08-07 09:37  FREE小宝  阅读(998)  评论(0编辑  收藏  举报