我重画了标题栏,可是当我用鼠标点击标题栏的时候,我画的关闭窗口的按钮就会被系统的按钮覆盖掉,这怎么办?

解决方案 »

  1.   

    我已经处理了WM_NCLBUTTONDOWN,可是还是不行
      

  2.   

    http://www.csdn.net/cnshare/soft/10/10802.shtm好像没有这个毛病。
      

  3.   

    我没有发现Winamp有这个问题呀。就算有也好,哪位知道怎么解决?
      

  4.   

    在 MainFrame里重画
    LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    // TODO: Add your specialized code here and/or call the base class LRESULT lrst=CFrameWnd::DefWindowProc(message, wParam, lParam);
    if(!::IsWindow(m_hWnd))
    {
    return lrst;
    }
    if(message==WM_MOVE||message==WM_NCACTIVATE||message==WM_PAINT||message==WM_NOTIFY)
    {
    CDC* pWndDC=GetWindowDC();
    if(pWndDC)
    {
    DrawTitleBar(pWndDC);//自己重画标题栏的函数
    }
    ReleaseDC(pWndDC);
    }
    return lrst;
    }
      

  5.   

    其实最彻底的方法是把窗口设为无边框无标题的,也就是全是客户区的那种。这样你要负责绘制所有的客户区和非客户区内容,Windows什么都不会绘。而且要重载OnNcHitTest(), 在你自己的“非客户区”内返回相应的值,欺骗Windows。
      

  6.   

    我就是象楼上的那样处理的。
    问题就出在按下Button的时候,如果你按下鼠标左键,不放开,也不做别的动作,就会出问题,如果移动鼠标,就又恢复正常了
      

  7.   

    delphihero(阿蒙(C++)) :这样会很闪的!
      

  8.   

    To easyrock:
    有MDI例子吗?
    我正需要这样的,是Dialog就算了
    [email protected]
      

  9.   

    我一个从Dialog 改过来的程序
    当我启动MDI程序时,没问题
    只要一打开系统菜单就出毛病,然后就再没有毛病了郁闷
      

  10.   

    我也碰到类似的问题,不过我已经解决了,不过是基于Dialog的,而且我碰到的问题更怪,在鼠标放在窗口的边缘,准备改变窗口的大小的时候,
    即 WM_NCMOUSEMOVE 消息里处理 nHitTest
    switch(nHitTest)
    {
    case HTTOP:
    case HTTOPLEFT:
    case HTTOPRIGHT:
    case HTBOTTOM:
    case HTBOTTOMLEFT:
    case HTBOTTOMRIGHT:
    case HTLEFT:
    case HTRIGHT:
    case HTSIZE:
         ...........
    }
    等HitTest时,Caption按钮竟然会重绘,造成闪烁,我用了很变态的方法来解决,
    m_pWndHooked->SendMessage(WM_CONTEXTMENU, (WPARAM) m_pWndHooked->GetSystemMenu(TRUE), MAKELONG(4,4));
    以后再绘制Caption就没事了,但是在Win98下不是很稳定(用鼠标右键在Caption弹出系统菜单以后就又闪烁了),Win2000效果很好。不知道哪位大虾有好的办法。
      

  11.   

    to swordbroken(断剑书生):
        我给你一点建议,我是这么做的,因为狗屁的Windows对于别人做的事情总是要插一手(而且有些时候都莫名其妙,不知道他还处理了没有),没有办法,我们只能多做一些处理,首先在OnNCHitTest()里自己定义好HTCLOSE, HTMINBUTTON, HTMAXBUTTON, HTSYSMENU, HTCAPTION, HTBORDER 等的区域并正确返回HitTest的结果。然后在OnNCLButtonDown()里做如下: switch(nHitTest)
    {
    case HTSYSMENU:
    {
    m_nLastHit = C_ICON;
    // 画Button,因为系统只重绘了Button部分
    PaintButtons();
    // 然后让系统自己弹出系统菜单
    return Default();
    }
    case HTCAPTION:
    {
    // 是否窗口已经最大化?
    if(!m_pWndHooked->IsZoomed()) {
    m_nLastHit = C_CAPTION;
    // 画整个Caption, 也可以试试只画Button
    PaintCaption();
    ReleaseCapture();
    CWnd * MainWnd;
    MainWnd = AfxGetMainWnd();
    // 窗口拖动
    MainWnd->SendMessage(WM_SYSCOMMAND, SC_MOVE | HTCLIENT, 0 );
    return 0;
    }
    else {
    PaintCaption();
    return 0;
    }
    }
    case HTMAXBUTTON:
    {
    m_nLastHit = C_MAX;
    // 重绘Button
    PaintButtons();
    return 0;
    }
    case HTMINBUTTON:
    {
    m_nLastHit = C_MIN;
    // 重绘Button
    PaintButtons();
    return 0;
    }
    case HTCLOSE:
    {
    m_nLastHit = C_CLOSE;
    // 重绘Button
    PaintButtons();
    return 0;
    }
    case HTTOP:
    case HTTOPLEFT:
    case HTTOPRIGHT:
    case HTBOTTOM:
    case HTBOTTOMLEFT:
    case HTBOTTOMRIGHT:
    case HTLEFT:
    case HTRIGHT:
    case HTSIZE:
    case HTBORDER:
    {
    m_nLastHit = C_SIZE;
    // 重绘Button
    PaintButtons();
    return Default();
    }
    }然后在 OnNCLButtonUp() 里:
    {
    ............ // 重绘Button
    PaintButtons(); return Default();
    }在 OnNCMouseMove() 里处理一些变态的东西: switch(nHitTest)
    {
    case HTTOP:
    case HTTOPLEFT:
    case HTTOPRIGHT:
    case HTBOTTOM:
    case HTBOTTOMLEFT:
    case HTBOTTOMRIGHT:
    case HTLEFT:
    case HTRIGHT:
    case HTSIZE:
    case HTBORDER:
    {
    // 奇怪的SendMessage却很奏效,移到边框的时候不再闪烁
    if(!m_pWndHooked->IsZoomed())
    m_pWndHooked->SendMessage(WM_CONTEXTMENU, (WPARAM) m_pWndHooked->GetSystemMenu(TRUE), MAKELONG(4,4));

    // 重绘整个Caption, 不仅仅是重绘Button,是为了应付win98的某些特殊情况
    PaintCaption();
    //return 0;
    return Default();
    }
    }
    if(m_nLastHit == C_NONE )
    return Default(); if(m_nLastHit == nHitTest)
    return 0; m_nLastHit = C_NONE;
    // 重绘Button
    PaintButtons();
    return 0;
    <--完-->有不对的,请多多指教
      

  12.   

    to cline(营营):
       你的软件做得很好,也很小:)你的是怎么做的啊,我看了,很好,可是你能做成Resizing的对话框吗,试试看,看会有闪烁吗?往指教
      

  13.   

    shines(Othelloing):
    可以呀!要不要Demo?
      

  14.   

    好啊:) give me, [email protected]
      

  15.   

    shines(Othelloing) :
    看RESIZE的效果,请用它放电影剪节(*.mpeg/*.mpg...)
      

  16.   

    大家这么积极,我想还是加些分吧。看谁还有更好的办法?To cline(营营):
    我也要->[email protected]
      

  17.   

    你的关闭按钮是不是一个按钮,如里是的话,把TAB 的顺序设置一下可能会有用。
      

  18.   

    to z_yheart(年轻的心):
    词霸和瑞星的都是假的Caption,还有联众也是,你可以使用Spy++看看,只有MSN Explorer最酷,直接用一个窗口把Caption换掉了,就是不知道怎么做的,但是自己完全重绘Caption就已经算不错了,不敢跟微软比。
      

  19.   

    如果直接用“一个窗口把Caption换掉了”,那可能就更简单了。
    1。先把Caption“抠掉/挖掉”
    2。然后再用一个窗口填上去
    3。它得到消息通知它,它得到消息它再通知它。就像一个窗一样!
      

  20.   

    回cline(营营) :
    shines(Othelloing) :
    看RESIZE的效果,请用它放电影剪节(*.mpeg/*.mpg...)我已经看到了,确实很好,跟主界面不是一个类::直接用“一个窗口把Caption换掉了”,这个我也试过了,可行,但做起来毕竟还是满麻烦的:P能不能贴一下你的部分代码,我们看看。
      

  21.   

    “一个窗口把Caption换掉了”是比较麻烦,每一个窗口都如此,是很累了。
    源代码?一方面太乱,真的很乱,没有逻辑性;另一方面,现在大家已习惯了那种不要标题或者有点瑕疵的软件了(比如Cognos的PowerPlay for Windows,是一个不错的数据仓库产品,它也会出现系统的按钮)。
      

  22.   

    没关系,我的代码也很乱:) 先搞懂了是怎么回事先,我现在在看你说的MSDN的例子,发现跟我这个很像,原来是这MSDN里来的:(,只是功能强度了一点,但代码风格没有ShadeCap的好,看起来舒服许多,你要是方便的话,把实现Caption部分的代码发到我的邮箱,乱我不怕
      

  23.   

    说错了,不是PowerPlay for Windows,是它的Impromptu Administrator Version.
      

  24.   

    我也把我的Demo共享一下吧,
    http://www.guozi.com/files/EZSkinDemo.zip
    众所周知,这是codecuru上的一个源码,这个呢,是我改得基本上没有BUG的,在win98下,用鼠标右键在Caption弹出系统菜单以后,移到窗口边缘就会有少许的闪烁现象。
      

  25.   

    codeguru上源码在什么地方,请指教
      

  26.   

    如果我把System menu去掉就不存在这个问题了,可是那样的话,任务栏里就没有图标了,如果有人告诉我怎么在任务栏里画图标也可以(我是说最小化窗口里标题文字左侧的图标)
      

  27.   

    to swordbroken(断剑书生):
    这有 http://www.codeproject.com/dialog/ezskin.asp
    但是同样的,他也有很多问题,跟你的类似。如果先把对话框变为无标题无边框,然后再加上这些属性WS_SYSMENU,
    WS_ICONIC,WS_MINIMIZEBOX即可以在任务栏上显示图标,虽然是有了图标,
    但是在Win98下会出现,单击任务栏上的标题时不会最小化,Win2000一切
    正常,这也是瑞星,金山词霸,联众等假的Caption最容易识别的一个方法,
    所以说还是做个彻底最好,而且Caption的大小是不能改变的,所以如果要
    做一个比现在的Caption区还大的Caption,那么有一部分要画到客户区上,
    如果想省掉麻烦,就只有像微软MSN Explorer那么做,有一个窗口来覆盖
    Caption,想放什么就放什么。
      

  28.   

    有一个很简单的方法,就是可以重载OnNcActivate这个函数,
    代码如下:
    BOOL CTestDialog::OnNcActivate(BOOL bActive) 
    {
    if(bActive ==0)
    OnNcPaint();
    return true;
    }
      

  29.   

    To jyu1221(天同) 
    你的办法也不行,因为我的代码里已经有了这个处理。
    而且出问题是在鼠标按下的一瞬间,可是如果你不释放鼠标的话就不行。如果你移动窗口,显示就又没有问题了
      

  30.   

    我在delhi下做过,主要处理这几个消息:
    我自己做了,没有问题的:
    wm_ncpaint;
    wm_ncactivate;
    wm_settext;
    wm_nchittest;
      

  31.   

    还好我在,swordbroken(断剑书生): 你的问题是,你在OnNCLButtonDown()执行的时候,
    要重绘一次按钮,或者是整个Caption,你可能漏掉了哪一个HitTest,至少要包括
    HTSYSMENU,HTCAPTION,HTMAXBUTTON,HTMINBUTTON,HTCLOSE,如果还是不行,
    可能是你的HitTest区域定义的不对,不然,你可以在OnNCLButtonDown()里
    不管什么HitTest都重绘试试,估计你就知道问题在哪了。
      

  32.   

    这次真的走了,现在是用猫拨号的,如果cline(营营)的代码愿意寄给我的话,还是寄到[email protected],我回家以后也许会抽空去网吧看看。 bye
      

  33.   

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;

    SetMenu(NULL);
    m_SkinBorder.Install(this);
    m_SkinCaption.Install(this);
    m_SkinCaption.m_pWndHooked->SendMessage(WM_CONTEXTMENU, (WPARAM) (GetSystemMenu(TRUE)), MAKELONG(4,4));
    ...
    }
    //我这样已经差不多了(Win2000 P)
    //多谢shines
      

  34.   

    我回来了,我在网吧,我的方法是超级愚蠢的方法,可惜cline(营营)不舍得,我们只要Caption部分的参考代码就可以了。
      

  35.   

    我终于找到了 MSN Explorer 的 Skins 原理了,跟我们想的完全不一样,跟上面说的想差很大。呵呵
      

  36.   

    我用Modelless dialog直接覆盖caption,自己做了一个
      

  37.   

    我提示一下,在WM_NCCALCSIZE这个消息做文章,把客户区的区域扩大到Caption,然后接管WM_NCCREATE, WM_NCPAINT, WM_NCACTIVE..., 等消息,你可以用www.Google.com搜索一下"WM_NCCALCSIZE",第一页里有一个关于Delphi的Custom Title Bar的文章,里面有详细说明,我就不多说了。
      

  38.   

    我在实际应用中也遇到如楼主的问题,不知那位好心人能寄一个较为良好
    的代码给我,最好说明一下思路,多谢。([email protected])