我也碰到类似的问题,不过我已经解决了,不过是基于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效果很好。不知道哪位大虾有好的办法。
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));
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;
}
问题就出在按下Button的时候,如果你按下鼠标左键,不放开,也不做别的动作,就会出问题,如果移动鼠标,就又恢复正常了
有MDI例子吗?
我正需要这样的,是Dialog就算了
[email protected]
当我启动MDI程序时,没问题
只要一打开系统菜单就出毛病,然后就再没有毛病了郁闷
即 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效果很好。不知道哪位大虾有好的办法。
我给你一点建议,我是这么做的,因为狗屁的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;
<--完-->有不对的,请多多指教
你的软件做得很好,也很小:)你的是怎么做的啊,我看了,很好,可是你能做成Resizing的对话框吗,试试看,看会有闪烁吗?往指教
可以呀!要不要Demo?
看RESIZE的效果,请用它放电影剪节(*.mpeg/*.mpg...)
我也要->[email protected]
词霸和瑞星的都是假的Caption,还有联众也是,你可以使用Spy++看看,只有MSN Explorer最酷,直接用一个窗口把Caption换掉了,就是不知道怎么做的,但是自己完全重绘Caption就已经算不错了,不敢跟微软比。
1。先把Caption“抠掉/挖掉”
2。然后再用一个窗口填上去
3。它得到消息通知它,它得到消息它再通知它。就像一个窗一样!
shines(Othelloing) :
看RESIZE的效果,请用它放电影剪节(*.mpeg/*.mpg...)我已经看到了,确实很好,跟主界面不是一个类::直接用“一个窗口把Caption换掉了”,这个我也试过了,可行,但做起来毕竟还是满麻烦的:P能不能贴一下你的部分代码,我们看看。
源代码?一方面太乱,真的很乱,没有逻辑性;另一方面,现在大家已习惯了那种不要标题或者有点瑕疵的软件了(比如Cognos的PowerPlay for Windows,是一个不错的数据仓库产品,它也会出现系统的按钮)。
http://www.guozi.com/files/EZSkinDemo.zip
众所周知,这是codecuru上的一个源码,这个呢,是我改得基本上没有BUG的,在win98下,用鼠标右键在Caption弹出系统菜单以后,移到窗口边缘就会有少许的闪烁现象。
这有 http://www.codeproject.com/dialog/ezskin.asp
但是同样的,他也有很多问题,跟你的类似。如果先把对话框变为无标题无边框,然后再加上这些属性WS_SYSMENU,
WS_ICONIC,WS_MINIMIZEBOX即可以在任务栏上显示图标,虽然是有了图标,
但是在Win98下会出现,单击任务栏上的标题时不会最小化,Win2000一切
正常,这也是瑞星,金山词霸,联众等假的Caption最容易识别的一个方法,
所以说还是做个彻底最好,而且Caption的大小是不能改变的,所以如果要
做一个比现在的Caption区还大的Caption,那么有一部分要画到客户区上,
如果想省掉麻烦,就只有像微软MSN Explorer那么做,有一个窗口来覆盖
Caption,想放什么就放什么。
代码如下:
BOOL CTestDialog::OnNcActivate(BOOL bActive)
{
if(bActive ==0)
OnNcPaint();
return true;
}
你的办法也不行,因为我的代码里已经有了这个处理。
而且出问题是在鼠标按下的一瞬间,可是如果你不释放鼠标的话就不行。如果你移动窗口,显示就又没有问题了
我自己做了,没有问题的:
wm_ncpaint;
wm_ncactivate;
wm_settext;
wm_nchittest;
要重绘一次按钮,或者是整个Caption,你可能漏掉了哪一个HitTest,至少要包括
HTSYSMENU,HTCAPTION,HTMAXBUTTON,HTMINBUTTON,HTCLOSE,如果还是不行,
可能是你的HitTest区域定义的不对,不然,你可以在OnNCLButtonDown()里
不管什么HitTest都重绘试试,估计你就知道问题在哪了。
{
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
的代码给我,最好说明一下思路,多谢。([email protected])