MFC使用ShowWindow(SW_MAXIMIZE)任务栏消失的处理

 
  1. ShowWindow(SW_SHOWMAXIMIZED);//窗口最大化  

问题:在写程序时,如果包含了标题栏,但是没有包含最大化按钮或者最小话按钮。

那么人工用ShowWindow(SW_MAXIMIZE),窗口会盖住任务栏,并且窗口最大化后还可以拖动!

解决方法:

1 窗口最大化可以拖动的问题就是在最大化时不让其拖动,

   只要响应WM_NCLBUTTONDOWN时判断是否最大化 IsZoomed如果是则直接返回就OK!

2 解决遮住任务栏就是重载WM_GETMINMAXINFO:

    1. void CTabDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)   
    2. {  
    3. // TODO: Add your message handler code here and/or call default  
    4. lpMMI-> ptMaxSize.y   =   GetSystemMetrics(SM_CYFULLSCREEN)+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYDLGFRAME);  
    5. CDialog::OnGetMinMaxInfo(lpMMI);  
    6. }  

针对这个问题,自己查了很久的资料:有一些问题再次拿出来讨论:

1.afx_msg void OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI );
参数:

lpMMI 指向一个MINMAXINFO结构,其中包含了有关窗口的最大化大小和位置以及最小、最大跟踪大小的信息。有关这个结构的更多信息参见MINMAXINFO结构。

说明:
每当Windows需要知道窗口的最大化位置或大小,或者最小、最大的跟踪大小时,框架就调用这个成员函数。最大化大小是指当窗口的边框被完全扩展时窗口的大小。窗口的最大跟踪大小是指用边框改变窗口的大小时可以达到的最大窗口大小。窗口的最小跟踪大小是指用边框改变窗口大小时可以达到的最小窗口大小。
Windows填充一个点组成的数组,为不同的位置和大小指定了缺省值。应用程序可以在OnGetMinMaxInfo中改变这些值。
注意 框架调用这个成员函数以允许你的应用程序处理一个Windows消息。传递给你的成员函数的参数反映了接收到消息时框架接收到的参数。如果你调用了这个函数的基类实现,则该实现将使用最初传递给消息的参数(而不是你提供给这个函数的参数)。

方法一:重载消息:WM_GETMINMAXINFO。
1. 消息:ON_WM_GETMINMAXINFO
BEGIN_MESSAGE_MAP(COfflineSCDlg, CDialog)
//{{AFX_MSG_MAP(COfflineSCDlg)
ON_WM_GETMINMAXINFO()   //申明方式
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
2. 类定义:afx_msg void OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI );
public:
// Dialog Data
//{{AFX_DATA(COfflineSCDlg)
enum { IDD = IDD_AAA_DIALOG };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(COfflineSCDlg)
public:
virtual BOOL DestroyWindow();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void OnSize(UINT nType, int cx, int cy);
afx_msg void OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI );
//}}AFX_VIRTUAL
3. 实现:OnGetMinMaxInfo
// 限制窗口的大小
void CAAADlg::OnGetMinMaxInfo(MINMAXINFO   FAR*   lpMMI)
{
lpMMI->ptMinTrackSize.x=400; //限定最小宽度
lpMMI->ptMinTrackSize.y=400; //限定最小高度
// lpMMI->ptMaxTrackSize.x=100; //限定最大宽度
// lpMMI->ptMaxTrackSize.y=100; //限定最大高度
CDialog::OnGetMinMaxInfo(lpMMI);  
}
方法二、由于一般窗口大小的改变,都是用户拖动窗口边框而造成的。所以,我们可以截获主窗口消息WM_NCHITTEST在其响应函数中判断CWnd::OnNcHitTest()的返回值是否为HTRIGHT,HTLEFT,HTTOP,HTBOTTOM四个值之一,如果是,说明用户此时已点击了四个边框之一,此时我们应该返回HTCLIENT.那么,鼠标的形状就不会变成水平或垂直的双向箭头,用户就不可能依靠拖动边框来改变窗口大小了。
  另外,还应补上一个小漏洞,就是还要把系统菜单中的SC_SIZE去掉。

2.

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

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

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

OnGetMinMaxInfo

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

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

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

[cpp] view plain copy
 
  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 plain copy
 
  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

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

3.SendMessage 

SendMessage函數是阻塞的。PostMessage函數是非阻塞的。
SendMessage:
函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。

函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);

参数:

hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。

Msg:指定被发送的消息。

wParam:指定附加的消息指定信息。

IParam:指定附加的消息指定信息。

返回值:返回值指定消息处理的结果,依赖于所发送的消息。

备注:需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。

参考:http://blog.csdn.net/tangaowen/article/details/5770816

 在WM_LBUTTONDOWN里面处理
SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
或者
响应NCHITTEST消息,命中测试。

将会导致WM_LBUTTONDOWN响应阻塞,也就是按下鼠标,不会收到WM_LBUTTONDOWN消息,而要等到鼠标放开,才有WM_LBUTTONDOWN和WM_LBUTTONUP进行响应。

到这里很清楚了,就是由于我发送了SendMessage NCLBUTTONDOWN消息,SendMessage消息不能返回,导致WM_LBUTTTONDOWN响应不能返回,当我鼠标松开弹起的时候,系统接管结束,SendMessage返回,我的WM_LBUTTONDOWN返回,表面上看是响应延时。实际是SendMessage阻塞了。

有人提出,我处理拖动应该采用WM_NCHITTEST,经过测试,发现一旦采用对WM_NCHITTEST进行处理拖动,窗口将无法响应任何鼠标点击消息。应该是所有鼠标消息都被系统的拖动接管了。所有这个方法是不行的。

还有人提出,我应该将SendMessage改为PostMessage消息,测试结果就是,能够马上响应WM_LBUTTONDOWN,但是却基本不能响应WM_LBUTTONUP,原因猜测也是在执行拖动的时候,不能响应消息,消息被系统接管。

原文地址:https://www.cnblogs.com/ranjiewen/p/5684814.html