关于WM_NCPAINT的问题

psbeond 2004-07-08 06:08:46
新建一个对话框工程,添加WM_NCPAINT消息:
void CTestPopDlg::OnNcPaint()
{
// TODO: Add your message handler code here
CBitmap bmp;
bmp.LoadBitmap( IDB_BITMAP1 );

CWindowDC dc ( this );
CDC memDC;
memDC.CreateCompatibleDC( &dc );

CRect rect;
GetWindowRect( &rect );
memDC.SelectObject( &bmp );
dc.StretchBlt( 0, 0, rect.Width(), 25, &memDC, 0, 0, 10, 25, SRCCOPY );
// Do not call CDialog::OnNcPaint() for painting messages
}
再对话框中拖一个Button,响应函数为:
void CTestPopDlg::OnButton1()
{
// TODO: Add your control notification handler code here
AfxMessageBox( "a" );
}
现在的问题是:
1、按下Button,当弹出MessageBox时,标题栏的位置就消失了,这时移动MessageBox,位图会重新出现,显示是在MessageBox弹出时没有重绘。请问这个问题
怎么解决,
2、当执行程序时,如果鼠标在最小化、最大化、关闭按钮处按下,然后在其它位置释放,这时相应的按钮就会出现,怎么使用它们不出现,并且还可以有效(即按下最大化时还可以使窗口最大化,因为左边的系统菜单有效,但系统菜单的图标并不会出现)
...全文
737 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
会思考的草 2004-07-12
  • 打赏
  • 举报
回复
呵呵,学习:)
psbeond 2004-07-12
  • 打赏
  • 举报
回复
问题已解决了一半,是在WM_ACTIVATE中调用SendMessage( WM_NCPAINT )解决的,因为弹出一个MessageBox后,主对话框就变为非活动,这时系统就会把标题栏改为非活动状态(灰色渐变条)所以这时发个消息过去重绘一下就可以了。
会思考的草 2004-07-09
  • 打赏
  • 举报
回复
如果非要自己画标题栏的话,会比较麻烦。
前面说过,我自绘过CMiniDockFrameWnd,当时是取消MFS_SYSMENU来取消那个关闭按钮,然后自己画了一个上去。不过Dialog我还真不知道怎么去掉,我想,实在不行就去掉sysmenu风格,然后自己画那个几个按钮。
leon7909 2004-07-09
  • 打赏
  • 举报
回复
記號
psbeond 2004-07-09
  • 打赏
  • 举报
回复
谢谢codewarrior(会思考的草)
那篇文章我很早就看过,我现在想做的是一个换肤的DLL,我以前也是把标题栏去掉,想怎么做就怎么做,不过现在由于每个程序都可能用到我的DLL,所有不能这样做,因为这做做了所有的程序的标题栏都一样了,因为有的标题栏上没有最大化和最小化按钮,有的没有系统菜单,并且这样做了,系统菜单就没有了,我通过GetSystemMenu,然后再弹出来,是可以显示,但不起作用。这个问题郁闷我很久了

另外LockWindowUpdate()我试了,确实可以实现,不过这只能要求客户端调用了,我想在我的SkinDLL中调用。客户端只要一个初始化皮肤就好那种。不过还是非常感谢你。
会思考的草 2004-07-09
  • 打赏
  • 举报
回复
给你看一个仿照金山毒霸的标题栏的例子:http://vbin.51.net/ztsprogram/doc/coolcaption.htm

顺便把我自己重绘的minidockframe的onncpaint贴上来你参考参考:
void CResizableMiniDockFrameWnd::OnNcPaint()
{
CWindowDC dc(this);

CRect rectClient(0,0,0,0);
GetClientRect(rectClient);

CRect rectWindow(0,0,0,0);
GetWindowRect(rectWindow);
ScreenToClient(rectWindow);

rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
dc.ExcludeClipRect(rectClient);
rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);

CSize sizeFrame(GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
CSize sizeBorder(GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
CSize sizeSmIcon(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
CMemoryDC dcMemory;
dcMemory.Create(&dc, rectWindow);

//±ß¿ò
dcMemory.DrawEdge(&rectWindow, EDGE_RAISED, BF_RECT);
CRect rectCaption(rectWindow);
rectCaption.DeflateRect(sizeFrame.cx, sizeFrame.cy);
rectCaption.bottom = rectCaption.top + sizeSmIcon.cy - sizeBorder.cy;

//±êÌâÀ¸µ×É«
BOOL bGradient = FALSE;
::SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradient, 0);
COLORREF clrLeft = ::GetSysColor(COLOR_ACTIVECAPTION);
COLORREF clrRight = ::GetSysColor(COLOR_GRADIENTACTIVECAPTION);
COLORREF clrGray = ::GetSysColor(COLOR_INACTIVECAPTION);
if(bGradient && m_bActive)
{
int nShift = 6;
int nSteps = 1 << nShift;
for(int i=0; i<nSteps; ++i)
{
int nRed = (GetRValue(clrLeft) * (nSteps - i) + GetRValue(clrRight) * i) >> nShift;
int nGreen = (GetGValue(clrLeft) * (nSteps - i) + GetGValue(clrRight) * i) >> nShift;
int nBlue = (GetBValue(clrLeft) * (nSteps - i) + GetBValue(clrRight) * i) >> nShift;

CRect rect(rectCaption);
rect.left = rectCaption.left +((i * rectCaption.Width()) >> nShift);
rect.right = rectCaption.left +(((i + 1) * rectCaption.Width()) >> nShift);

if(rect.Width() > 0)
{
dcMemory.FillSolidRect(rect, RGB(nRed, nGreen, nBlue));
}
}
}
else
{
dcMemory.FillSolidRect(&rectCaption, m_bActive ? clrLeft:clrGray);
}
LOGFONT fontCaption = {0};
::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &fontCaption, 0);
fontCaption.lfWeight = FW_BOLD;
HFONT hCaptionFont = CreateFontIndirect(&fontCaption);
HGDIOBJ hOldFont = dcMemory.SelectObject(hCaptionFont);
dcMemory.SetTextColor(::GetSysColor(COLOR_CAPTIONTEXT));
dcMemory.SetBkMode(TRANSPARENT);

CString strCaption(_T(""));
GetWindowText(strCaption);
if(strCaption.IsEmpty())
{
strCaption = _T("ToolBar");
}
CSize sizeText(dcMemory.GetTextExtent(strCaption));

//Êä³öÎı¾(ÓҶ˿۳ýButtonËùÕ¼µÄλÖÃ)
CRect rectText(rectCaption);
rectText.left += sizeBorder.cx * 2;
rectText.right -= sizeSmIcon.cx * 2 + sizeBorder.cx;
dcMemory.DrawText(strCaption, &rectText, DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS);
dcMemory.SelectObject(hOldFont);
DeleteObject(hCaptionFont);

DrawButton(&dcMemory, rectCaption);

dcMemory.Flush();
}
会思考的草 2004-07-09
  • 打赏
  • 举报
回复
现在的问题是:
1、按下Button,当弹出MessageBox时,标题栏的位置就消失了,这时移动MessageBox,位图会重新出现,显示是在MessageBox弹出时没有重绘。请问这个问题
怎么解决,
这个问题是因为AfxMessageBox有自己的消息循环,系统帮忙代办了你的Dialog的Nc Paint动作。只要在Afxmessagebox之前调用LockWindowUpdate()禁止系统重画,在AfxMessageBox之后调UnlockWindowUpdate()即可。但是这样会出现重绘问题。我的建议还是你不要用系统的captionbar,直接自己绘制。

2、当执行程序时,如果鼠标在最小化、最大化、关闭按钮处按下,然后在其它位置释放,这时相应的按钮就会出现,怎么使用它们不出现,并且还可以有效(即按下最大化时还可以使窗口最大化,因为左边的系统菜单有效,但系统菜单的图标并不会出现)
这个好像没有办法。这些按钮是窗口风格决定的。还是老办法,自己画按钮。
Kudeet 2004-07-08
  • 打赏
  • 举报
回复
OnNcPaint,当非客户区需要重画时,框架调用这个成员函数。缺省的实现画出窗口的框架。应用程序可以重载这个调用并画出自己定义的窗口边框。裁剪区域通常是矩形,即使框架的形状已经改变。
vontc2003 2004-07-08
  • 打赏
  • 举报
回复
问题1: 不晓得
问题2: 可以通过使OnNcHitTest返回HTCLIENT来解决, 但是也不能通过他来移动窗口了

15,978

社区成员

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

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