WM_NCCALCSIZE引发的问题

石岩Maple 2020-11-26 10:27:33
我重写了窗口的CreateParams方法

protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.Style = cp.Style | 0x20000 | 0x00040000;//允许最小化操作;
return cp;
}
}

具体含义就是0x20000=允许任务栏点击窗口标签最大化最小化窗口
0x00040000表示具有一个厚边框,具体厚度应该是上下左右各6个像素
之后我在WndProc里拦截了WM_NCCALCSIZE消息,使这6个像素的边框不被系统重绘出来,使整个界面看起来是无边框的界面,且能让系统按照有边框窗口运行,让窗口能够接收到有边框窗口的消息

但是引发了一些问题,就是当我在任务栏点击窗口标签使界面显示或者最小化的时候,当窗口重新显示,窗口的高度和宽度会自动增加,增加的高度和宽度看起来应该是6*2个像素,好像我拦截了WM_NCCALCSIZE消息后,系统自动把上下边框,左右边框都追加到了下边和右边一样,百思不得其解,最后我在网上找了下方法,看到有人这么说:

if (m.WParam != IntPtr.Zero)
{
NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
AdjustClientRect(ref rcsize.rcNewWindow);
Marshal.StructureToPtr(rcsize, m.LParam, false);
}
else
{
RECT rcsize = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
AdjustClientRect(ref rcsize);
Marshal.StructureToPtr(rcsize, m.LParam, false);
}


RECT 结构:

public struct RECT
{
public int Left; //最左坐标
public int Top; //最上坐标
public int Right; //最右坐标
public int Bottom; //最下坐标
}


NCCALCSIZE_PARAMS 结构:

struct NCCALCSIZE_PARAMS
{
public RECT rcNewWindow;
public RECT rcOldWindow;
public RECT rcClient;
IntPtr lppos;
}


AdjustClientRect方法:

private void AdjustClientRect(ref RECT rc)
{
rc.Left += 6;
rc.Right -= 6;
rc.Top += 6;
rc.Bottom -= 6;
}


但是最终运行起来还是会在每次点击任务栏标签时自动增加窗口宽高,实在没有办法,忘请大神赐教,Win32的Api实在一时难懂
...全文
30501 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
石岩Maple 2021-01-04
  • 打赏
  • 举报
回复
自己顶一下
enaking 2020-12-18
  • 打赏
  • 举报
回复
帮你顶一下。。。。。。。。
石岩Maple 2020-12-17
  • 打赏
  • 举报
回复
没人知道么
石岩Maple 2020-12-08
  • 打赏
  • 举报
回复
理论我是懂得,我现在就是做了一个厚边框的窗体,然后试图用客户区盖住非客户区,但是得到的效果要么是客户区覆盖了非客户区,但是窗口隐藏厚再显示,或者最小化后再显示,右边和下边都会增加一点高度和宽度,要么就是解决了后者问题,当我隐藏窗体或者最小化再显示后,窗体边框就又出现了,我需要一个完整的实现代码,谢谢
石岩Maple 2020-12-02
  • 打赏
  • 举报
回复
没有人知道吗?
八爻老骥 2020-12-02
  • 打赏
  • 举报
回复
稍微解释一下,希望对你有用:

如果想要可变窗体,标题栏(或者最大化、最小化按钮)和边框是必须存在的。标题栏和边框是非客户区,由操作系统创建的,没有多少可定制的空间,但你可以将客户区完全覆盖住非客户区,这样唯一的问题就是最大化的时候,依然会出现边框,这时就要用到WM_NCCALCSIZE消息了,在非客户区尺寸改变之后,重新计算客户区大小,使其继续覆盖住非客户区,然后就是点击任务栏的问题,右击任务栏又会出现边框,点击任务栏不会触发WM_NCCALCSIZE,但此时会触发 WM_NCACTIVATE,可能通过这个消息继续隐藏非客户区。

引用 5 楼 古耕 的回复:


case 0x0001:
case WM_NCCALCSIZE:
case WM_NCACTIVATE:
NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
GetWindowRect(m.HWnd, ref rcsize.rcOldWindow);

SetWindowPos(m.HWnd,
0,
rcsize.rcOldWindow.Left, rcsize.rcOldWindow.Top,
rcsize.rcOldWindow.Right - rcsize.rcOldWindow.Left,
rcsize.rcOldWindow.Bottom - rcsize.rcOldWindow.Top,
0x20);
break;


改为C#的代码后,只出现了右边和下边的边框,应该只有一个像素,左边和右边边框没了,且内容全部都是透明的,我这个页面在右上角有个关闭按钮,我点了下,也是有效的,只是看不见
石岩Maple 2020-11-27
  • 打赏
  • 举报
回复

              case 0x0001: 
                case WM_NCCALCSIZE:
                case WM_NCACTIVATE:
                        NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
                        GetWindowRect(m.HWnd, ref rcsize.rcOldWindow);

                        SetWindowPos(m.HWnd,
                            0,
                            rcsize.rcOldWindow.Left, rcsize.rcOldWindow.Top,
                            rcsize.rcOldWindow.Right - rcsize.rcOldWindow.Left, 
                            rcsize.rcOldWindow.Bottom - rcsize.rcOldWindow.Top,
                            0x20);
                    break;
改为C#的代码后,只出现了右边和下边的边框,应该只有一个像素,左边和右边边框没了,且内容全部都是透明的,我这个页面在右上角有个关闭按钮,我点了下,也是有效的,只是看不见
八爻老骥 2020-11-26
  • 打赏
  • 举报
回复
引用 3 楼 古耕 的回复:
不行啊,我整理了下你的代码,执行程序后界面一直在重绘,且看不到界面


这个是用客户区矩形覆盖非客户区的代码,你要根据你的代码稍调整一下。
石岩Maple 2020-11-26
  • 打赏
  • 举报
回复
不行啊,我整理了下你的代码,执行程序后界面一直在重绘,且看不到界面
八爻老骥 2020-11-26
  • 打赏
  • 举报
回复
处理一下WM_NCACTIVATE消息。


case WM_CREATE:
case WM_NCCALCSIZE:
case WM_NCACTIVATE:
{
RECT rcClient;
GetWindowRect(hWnd, &rcClient);

// Inform the application of the frame change.
SetWindowPos(hWnd,
NULL,
rcClient.left, rcClient.top,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
SWP_FRAMECHANGED);

}break;
石岩Maple 2020-11-26
  • 打赏
  • 举报
回复
没有人会吗?

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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