新建一个对话框工程,添加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、当执行程序时,如果鼠标在最小化、最大化、关闭按钮处按下,然后在其它位置释放,这时相应的按钮就会出现,怎么使用它们不出现,并且还可以有效(即按下最大化时还可以使窗口最大化,因为左边的系统菜单有效,但系统菜单的图标并不会出现)

解决方案 »

  1.   

    问题1: 不晓得
    问题2: 可以通过使OnNcHitTest返回HTCLIENT来解决, 但是也不能通过他来移动窗口了
      

  2.   

    OnNcPaint,当非客户区需要重画时,框架调用这个成员函数。缺省的实现画出窗口的框架。应用程序可以重载这个调用并画出自己定义的窗口边框。裁剪区域通常是矩形,即使框架的形状已经改变。
      

  3.   

    现在的问题是:
    1、按下Button,当弹出MessageBox时,标题栏的位置就消失了,这时移动MessageBox,位图会重新出现,显示是在MessageBox弹出时没有重绘。请问这个问题
    怎么解决,
    这个问题是因为AfxMessageBox有自己的消息循环,系统帮忙代办了你的Dialog的Nc Paint动作。只要在Afxmessagebox之前调用LockWindowUpdate()禁止系统重画,在AfxMessageBox之后调UnlockWindowUpdate()即可。但是这样会出现重绘问题。我的建议还是你不要用系统的captionbar,直接自己绘制。2、当执行程序时,如果鼠标在最小化、最大化、关闭按钮处按下,然后在其它位置释放,这时相应的按钮就会出现,怎么使用它们不出现,并且还可以有效(即按下最大化时还可以使窗口最大化,因为左边的系统菜单有效,但系统菜单的图标并不会出现)
    这个好像没有办法。这些按钮是窗口风格决定的。还是老办法,自己画按钮。
      

  4.   

    给你看一个仿照金山毒霸的标题栏的例子: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));

    //&Ecirc;&auml;&sup3;&ouml;&Icirc;&Auml;±&frac34;(&Oacute;&Ograve;&para;&Euml;&iquest;&Ucirc;&sup3;&yacute;Button&Euml;ù&Otilde;&frac14;&micro;&Auml;&Icirc;&raquo;&Ouml;&Atilde;)
    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();
    }
      

  5.   

    谢谢codewarrior(会思考的草) 
    那篇文章我很早就看过,我现在想做的是一个换肤的DLL,我以前也是把标题栏去掉,想怎么做就怎么做,不过现在由于每个程序都可能用到我的DLL,所有不能这样做,因为这做做了所有的程序的标题栏都一样了,因为有的标题栏上没有最大化和最小化按钮,有的没有系统菜单,并且这样做了,系统菜单就没有了,我通过GetSystemMenu,然后再弹出来,是可以显示,但不起作用。这个问题郁闷我很久了另外LockWindowUpdate()我试了,确实可以实现,不过这只能要求客户端调用了,我想在我的SkinDLL中调用。客户端只要一个初始化皮肤就好那种。不过还是非常感谢你。
      

  6.   

    如果非要自己画标题栏的话,会比较麻烦。
    前面说过,我自绘过CMiniDockFrameWnd,当时是取消MFS_SYSMENU来取消那个关闭按钮,然后自己画了一个上去。不过Dialog我还真不知道怎么去掉,我想,实在不行就去掉sysmenu风格,然后自己画那个几个按钮。
      

  7.   

    问题已解决了一半,是在WM_ACTIVATE中调用SendMessage( WM_NCPAINT )解决的,因为弹出一个MessageBox后,主对话框就变为非活动,这时系统就会把标题栏改为非活动状态(灰色渐变条)所以这时发个消息过去重绘一下就可以了。