单文档非客户区重绘如何保持重绘效果

磐石区 2013-08-09 04:26:31
说一下现在的情况,新建单文档应用程序,
重载 OnNcPaint() ,在里面 用 StretchBlt() TransparentBlt() 贴图重绘非客户区

画好了之后,程序启动肯定是贴的那个样子,但是移动,放大,缩小,无焦点等等情况,它就会成为原来的样子,这是就要用 DefWindowProc()
我的代码是这样写的
LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
if (message == WM_MOVE || message == WM_NOTIFY || message == WM_NCACTIVATE)
{
OnNcPaint();
}
return CFrameWnd::DefWindowProc(message, wParam, lParam);
}


初衷是,收到这些消息,就再画一下非客户区,但是问题就在,这里好像没有涵盖完所有情况,假设一种情况,程序启动,程序有焦点,但是点一下其它程序,我写的程序没有焦点,就没有我贴的图了,更甚的是就算点我写的程序给他焦点,也不会有贴图,第二种情况就是我的系统是win7,我写的程序最小化后,鼠标放在底部程序时,win7生成预览,点预览,依然是没有贴图,点程序是有贴图的 第三种情况,按着程序底部程序按钮不放,程序就没有贴图,此时松开,就有贴图然后程序最小话,如果点着的时候,鼠标移到其他地方松开,程序不最小化,也一直没有贴图了

说了这么多情况,我只是希望大家能知道我问的是什么,我只所以坚信问题能得到解决,是当我不判断消息的时候 在 defWindowProc 中 直接 OnNcPaint();我上面说的那些情况都不存在,但是我觉得这样做并不好,因为消息那么多,每收到一个消息不管有关没有关都去重画非客户区,并不好。

求高手给我说我应该都在接收到那些消息时 调用OnNcPaint();

提供建议都给分
...全文
649 60 打赏 收藏 转发到动态 举报
写回复
用AI写文章
60 条回复
切换为时间正序
请发表友善的回复…
发表回复
ooicc 2014-07-10
  • 打赏
  • 举报
回复
afx_msg BOOL OnNcActivate( BOOL bActive ); The default implementation draws the title bar and title-bar text in their active colors if bActive is TRUE and in their inactive colors if bActive is FALSE. 确实是这货悄悄添了不少麻烦...
小龙王2010 2013-08-21
  • 打赏
  • 举报
回复
这个问题我已经解决了, 我的情况是,当窗口为非Active时 才会不绘制, 所以我在OnActive中选择在非Active时 重新调用 OnNcPaint 就解决了问题
only_delusion 2013-08-16
  • 打赏
  • 举报
回复
引用 26 楼 panshiqu 的回复:
[quote=引用 23 楼 lin98666lin 的回复:] [quote=引用 20 楼 panshiqu 的回复:] [quote=引用 16 楼 schlafenhamster 的回复:] 在 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 改 cs 是 没用的 。必须在窗口 产生后: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; ModifyStyle(WS_CAPTION,0) ;
好吧,我百度“单文档去掉非客户区”我好像发现了什么 ModifyStyle(WS_CAPTION, 0, SWP_FRAMECHANGED); 好像应该这样写呀,这样写就是你贴图的那个样式了[/quote] 除了WS_CAPTION 以外 还有ws_border ws_sizebox什么的 都要去掉 然后得到一个纯净的客户区,然后截获鼠标消息,模拟非客户区消息 基本都是这么用的, wn7的 非客户区绘制 采用的是另外一种模式,尤其在失去焦点的时候 绘制半透明的效果 不太好用,至少我是没弄明白。[/quote] 才看到你的回答,谢谢为我解惑,但是 ModifyStyle(WS_SIZEBOX, 0, SWP_FRAMECHANGED); 不用加 WS_BORDER 边框就没有了,好奇怪呀! 你好像做过这方面的程序,我觉得25楼的方法就很好,剩下的目标就是把那个DialogBar做的漂亮些,但是按你说的,去了上面那两项后最大化最小话就不说了,拖动边改变大小,拖动DialogBar来实现单文档的拖动,我要怎么做呢,就想对话框是响应 OnNcHitTest(),我现在这个单文档呢。 还有就是边没有了,看现在的主流浏览器,在不是最大化的时候,他们还是有个边框,就是不去掉上面两个属性,边框还是可以拖动大小的,只是还是上面那个问题,没有标题栏我要怎么让DialogBar成为我的标题栏呢?[/quote] 标题栏 就是响应一些鼠标操作 发送一些nc消息,那你截获的鼠标消息加判断 例如: 1.当鼠标在窗口上侧按下时,你要截获WM_LBUTTONDOWN消息,并发送 WM_NCLBUTTONDOWN,同样的当鼠标点击 四个边和四个角的时候 你要发送其他的消息,这样就模拟了非客户区。 给你一个我曾经写过的 lbuttondown消息处理 你看看吧,也许会了解下。 JudgePos 函数 根据鼠标位置判断鼠标时候点击在边框或者标题栏 如果是 那么发送相关的消息, WM_NCLBUTTONDOWN,HTLEFT,MAKELPARAM(point.x, point.y) 例如这个,发送鼠标点在左侧的拖动大小操作。 同样的 MOUSEMOVE消息也要有判断 设置鼠标显示状态。 鼠标双击标题栏放大什么的,都需要模拟下,不过也不麻烦 没几个消息,相信楼主 可以成功。 无论是单文档还是对话框都是一样的。
LRESULT CAncestorWindow::OnLButtonDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	bHandled = FALSE;
	if (!_isDrag||IsZoomed())
	{
		return FALSE;
	}

	POINT point = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
	_drag_sign = JudgePos(point);
	if (_drag_sign!=0)ReleaseCapture();
	switch(_drag_sign)
	{
	case WMSZ_LEFT:
		PostMessage(WM_NCLBUTTONDOWN,HTLEFT,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_RIGHT:
		PostMessage(WM_NCLBUTTONDOWN,HTRIGHT,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_TOP:
		PostMessage(WM_NCLBUTTONDOWN,HTTOP,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_TOPLEFT:
		PostMessage(WM_NCLBUTTONDOWN,HTTOPLEFT,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_TOPRIGHT:
		PostMessage(WM_NCLBUTTONDOWN,HTTOPRIGHT,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_BOTTOM:
		PostMessage(WM_NCLBUTTONDOWN,HTBOTTOM,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_BOTTOMLEFT:
		PostMessage(WM_NCLBUTTONDOWN,HTBOTTOMLEFT,MAKELPARAM(point.x, point.y));
		break;
	case WMSZ_BOTTOMRIGHT:
		PostMessage(WM_NCLBUTTONDOWN,HTBOTTOMRIGHT,MAKELPARAM(point.x, point.y));
		break;
	default:
		bHandled = FALSE;
		break;
	}
	return TRUE;
}
磐石区 2013-08-15
  • 打赏
  • 举报
回复
引用 54 楼 schlafenhamster 的回复:
“windows7自带的边框肯定会覆盖我画的” 那么你不画, 就让 win7 画 。 行不行。 我画 是因为 , 不画的话 只有一点 灰色, 难看。 如果 win7 画的 好看, 你又 何必 画?
唉,win7画的确实还好,可是如果这样的话,我就要把dialogbar的色彩风格去迎合他的边框,但是到了其他系统XP,正如你所说只是灰色线条而已,又不好看了,我就是想看看有没有解决这个问题的办法,我还在尝试...
schlafenhamster 2013-08-15
  • 打赏
  • 举报
回复
“windows7自带的边框肯定会覆盖我画的” 那么你不画, 就让 win7 画 。 行不行。 我画 是因为 , 不画的话 只有一点 灰色, 难看。 如果 win7 画的 好看, 你又 何必 画?
磐石区 2013-08-15
  • 打赏
  • 举报
回复
引用 52 楼 schlafenhamster 的回复:
我没有 win7 。 win 7 边框 是 4个 点 ? 我 只 画了 3个 点 , 你加一点 试试。 把他覆盖掉。
我可以这样说吗,现在的情况是,我无论怎么画,但是如果只用OnNcPaint的话,windows7自带的边框肯定会覆盖我画的,但是要按我以前写的程序,响应DefWindowProc让他再重画,一打开程序,我花的会显示,这样不是回到我题目中问的问题了吗?
schlafenhamster 2013-08-15
  • 打赏
  • 举报
回复
我没有 win7 。 win 7 边框 是 4个 点 ? 我 只 画了 3个 点 , 你加一点 试试。 把他覆盖掉。
磐石区 2013-08-15
  • 打赏
  • 举报
回复
在上两个我随遍贴的图:
这小红框都是在 MainFrame 里面的 OnNcPaint 里面帖的图片
这大红框当然就是在DialogBar 里面 OnEraseBkgnd 里面贴的图片

区别就是这个是Windows经典界面显示的情况


这就是Win7里面显示的情况


这你也就可以看出你的程序在Win7界面中多出一个边框,却没有显示你花的边框的情况了吧,情况就是这么个情况
磐石区 2013-08-15
  • 打赏
  • 举报
回复
引用 49 楼 schlafenhamster 的回复:
“如果这样就是重绘非客户区边框,就会出现我一开始纠结的那些问题” 那个图是你重绘的非客户区边框,还是 我的 代码 ? 单单 重绘非客户区边框,应该不会“出现我一开始纠结的那些问题” “这个时候我能不能去掉自带的“ 你 怎么 HitTest 在 那边?
第一个问号: 是你的代码 第二个问号:我好像没有看太懂,边框也是非客户区呀,一旦用windows自带的,然后贴图上去,就会出现一开始问题中几种情况贴图消失, 我去掉windows自带的边框,不能响应 OnNcHitTest才问的
schlafenhamster 2013-08-15
  • 打赏
  • 举报
回复
“如果这样就是重绘非客户区边框,就会出现我一开始纠结的那些问题” 那个图是你重绘的非客户区边框,还是 我的 代码 ? 单单 重绘非客户区边框,应该不会“出现我一开始纠结的那些问题” “这个时候我能不能去掉自带的“ 你 怎么 HitTest 在 那边?
磐石区 2013-08-15
  • 打赏
  • 举报
回复
引用 46 楼 schlafenhamster 的回复:
我不是已经画了边框吗 ? void CMainFrame::OnNcPaint() { // TODO: Add your message handler code here CFrameWnd::OnNcPaint();// for menu CRect rc; GetWindowRect(&rc); rc.OffsetRect(-rc.left,-rc.top); CDC *pDC=GetWindowDC(); if(m_Active==WA_INACTIVE) //=0 { pDC->Draw3dRect(0,0,rc.Width(),rc.Height(),RGB(90,105,206),RGB(74,81,189)); pDC->Draw3dRect(1,1,rc.Width()-2,rc.Height()-1,RGB(115,130,222),RGB(115,130,222)); pDC->Draw3dRect(2,2,rc.Width()-4,rc.Height()-1,RGB(115,130,222),RGB(115,130,222)); } else // active border { pDC->Draw3dRect(0,0,rc.Width(),rc.Height(),RGB(0,48,222),RGB(0,16,140)); pDC->Draw3dRect(1,1,rc.Width()-2,rc.Height()-1,RGB(16,105,239),RGB(0,28,165)); pDC->Draw3dRect(2,2,rc.Width()-4,rc.Height()-1,RGB(8,85,222),RGB(0,60,222)); } ReleaseDC(pDC); } 你觉得颜色不好, 改改就可以了。
你看看我上面发的图片,就会这样子,从根本上的话我想就是去掉 边框,但是去掉后我就没有了绘画的地方,还有响应鼠标移动的地方 这个时候我能不能去掉自带的,自己把客户向外眼神5px作为边框来绘图响应消息,之类的
磐石区 2013-08-15
  • 打赏
  • 举报
回复
Windows经典的界面

Windows7的界面


如果这样就是重绘非客户区边框,就会出现我一开始纠结的那些问题
schlafenhamster 2013-08-15
  • 打赏
  • 举报
回复
我不是已经画了边框吗 ?

void CMainFrame::OnNcPaint() 
{
// TODO: Add your message handler code here
CFrameWnd::OnNcPaint();// for menu
CRect rc;
GetWindowRect(&rc);
rc.OffsetRect(-rc.left,-rc.top);
CDC *pDC=GetWindowDC();
if(m_Active==WA_INACTIVE) //=0
{
pDC->Draw3dRect(0,0,rc.Width(),rc.Height(),RGB(90,105,206),RGB(74,81,189));
pDC->Draw3dRect(1,1,rc.Width()-2,rc.Height()-1,RGB(115,130,222),RGB(115,130,222));
pDC->Draw3dRect(2,2,rc.Width()-4,rc.Height()-1,RGB(115,130,222),RGB(115,130,222));
}
else // active border
{
pDC->Draw3dRect(0,0,rc.Width(),rc.Height(),RGB(0,48,222),RGB(0,16,140));
pDC->Draw3dRect(1,1,rc.Width()-2,rc.Height()-1,RGB(16,105,239),RGB(0,28,165));
pDC->Draw3dRect(2,2,rc.Width()-4,rc.Height()-1,RGB(8,85,222),RGB(0,60,222));
}
ReleaseDC(pDC);
}

你觉得颜色不好, 改改就可以了。
磐石区 2013-08-15
  • 打赏
  • 举报
回复
引用 43 楼 VisualEleven 的回复:
在不同的主题风格下也会出现问题的,比如在Win7 Areo那中风格下,可能OnNcPaint并不一定好使
谢谢回答我的问题哈,我现在正按 schlafenhamster 提供的思路放弃非客户区重绘来实现我想要的界面...
磐石区 2013-08-15
  • 打赏
  • 举报
回复
引用 42 楼 schlafenhamster 的回复:
“我自己来实现拖动四周来实现改变大小” 那个边框 还是 NC 你 要 用 OnNcHitTest 来 确定 是 那 个 边。 windows 很讨嫌 的, 各版本 都 不一样。
这个OnNcHitTest我也测试过呀,但是是这种情况,ModifyStyle(WS_THICKFRAME, 0 , SWP_FRAMECHANGED);去掉这个属性后好像也是像OnMouseMove一样得不到响应 正因为各版本都不一样,我才想看看能不能统一一下边框,让样式变好看些。 我又新建工程,去掉Caption和ThickFrame后,OnMouseMove和OnNcHitTest都不响应 保留ThickFrame,当鼠标移动到边框的时候会响应OnNcHitTest,如果这样的话,就没有必要响应OnNcHitTest啦,因为windows自带边框拖动呀,就算是有必要重新实现拖动,但是又回到我题目中的问题了,OnNcPaint里面绘制的背景很容易出状况... 我的解决这问题原本是这样想的虚拟出四条边(假象的,四个角先不说)不管响应什么函数鼠标移到上面 点击左键 进入拖动模式...
schlafenhamster 2013-08-15
  • 打赏
  • 举报
回复
那就 查 版本 信息, 再分别 对待。
磐石区 2013-08-15
  • 打赏
  • 举报
回复
结贴散分了,先研究到这吧,行不通呀,如果那个朋友有幸看到帖子,但是坚持找到了解决办法,欢迎挖坟通知我呀,谢谢...
磐石区 2013-08-14
  • 打赏
  • 举报
回复
引用 37 楼 schlafenhamster 的回复:
已发 带 exe
首先谢过了,还没有收到,等一会儿 我在MainFrame中添加OnMouseMove也不会响应,我现在准备重建工程了...
schlafenhamster 2013-08-14
  • 打赏
  • 举报
回复
已发 带 exe
磐石区 2013-08-14
  • 打赏
  • 举报
回复
引用 30 楼 schlafenhamster 的回复:
“看到你的代码,我首先想到的不科学,怎么一个MouseMove就能实现点击DialogBar拖动单文档呢...” 何以见得“不科学”? 这是 已经 实现的 代码!!!!
我可以说我还是被同一个问题困扰吗?我看你其他函数只是美化DialogBar而已,我按我上面说的步骤添加的OnMouseMove函数为什么不执行呢? 你方便的话吧把你的示例工程发我邮箱吧:panshiqu@sina.com
加载更多回复(40)

15,976

社区成员

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

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