首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

纯代码编写 skin 关于 WM_NCPAINT ,WM_NCCALCSIZE 的有关问题请问

2012-06-14 
纯代码编写 skin 关于 WM_NCPAINT ,WM_NCCALCSIZE 的问题请教!我现在只是想做一个 skin 的 Form 出来。我的

纯代码编写 skin 关于 WM_NCPAINT ,WM_NCCALCSIZE 的问题请教!
我现在只是想做一个 skin 的 Form 出来。
我的做方法 得到窗体的 windowProc 指针,把它指向我的新 windowProc,再在我的 WindowProc 里拦 WM_NCxxx 消息,像对本窗口的边框 与栏题栏进行自画。
 
现在的问题有:
1. 诡异的 WM_NCCALCSIZE. 这个消息在 MSDN 上也说的不是很清楚。
  它在 wParam为真或假时 lParam 分别指向的内容不一样。而 MDSN 上也不是说的太说细,测试了很久也不是很明白,找到的一些代码只是说在 wParam 为真时,第一个矩形为窗口的位置,直接把它改小就可以了。但问题是第一次执行程序,居然不触发 WM_NCCALCSIZE 事件。但拉动窗口大小时,它又会触发。
 
2. 同样诡异的 WM_NCPAINT 与 GetDcEx
  这个消息在绘标题栏时触发。wParam 为 NC 区域的 HRGN (MSDN上说的). 但我的测试用 MSDN 上的代码基本就是不行,MSDN 上是用 GetDcEx 来得到 NC 区域的 DC.但我得到的 HDC 基本就不能绘画。最后用笨方法,用 GetWindowDc 得到窗口的 HDC,但手动算出 NC 区域的 HRGN 再 selectObject 把这个 HRGN 放到 HDC 里。
 
3. 更加诡异的 WM_NCHITTEST
 本来以我的想法,在 WM_NCHITTEST 里返回指定的值如 HTCLOSE,表示鼠标在 close 按钮上。我就这样测试,不窗鼠标在哪里,我都返回 HTCLOSE,这时我随便按那里,都是 close 按钮被按下了。但我松开鼠标,这时窗口居然没有被关闭。好呀,我在 WM_NCLBUTTONUP 里wparam = HTCLOSE 时,我 PostMessage( WM_SYSCOMMAND ,SC_CLOSE)。这样居然有时可能,有时又不行。
 
4. 效率如何提高?
  现在我没用双缓冲。每次都直接在窗口HDC 上画,但效果很低,特别时把一部分窗口移到桌面以外,慢慢向里拉时,CPU 占用很高。很时显停止状。想做成双缓冲,但一时也想不到如何做。在窗口大小变化时,内存 DC 如何处理?也跟着变?然后再画出来?这样我想效率也不会提高。
 
5. 边角不规则如何处理?
  现在要求窗口边角是圆边矩形,那还好做点,用 SetWindowRgn 来处理。但对不是很好描述的奇怪点的窗口呢?又要如何处理?我知道 vclskin 可以做到。
 
 
以上几点疑问,希望能在你有空的时间,给我一点指点,多谢了。
 


[解决办法]
关注...
[解决办法]
自己画不是那么容易的。何苦呢。。。。。。
[解决办法]
不规则窗口,一般是要绘制一张窗口形状的图片,逐行扫描该图片,去除透明色,作为高度为1的矩形,CreateRectRgn,然后CombineRgn把每一行的这些RGN合并起来,就得到了整个不规则形状的RGN.
[解决办法]
up
[解决办法]
http://www.vckbase.com/document/viewdoc/?id=529
和你的思路差不多,用了hook,好像用了双缓冲,没仔细看。我觉得速度还可以,不知是否达到lz的要求。
[解决办法]
没弄过。帮你顶一下了
[解决办法]
感觉很像skin++的设计思路,可下一份skin++代码研究下,其实主要是两部分,1 消息分配 2 绘制
[解决办法]
GDI+中也可以用Bitblt
我这下了Skin 5.0代码,你在网上找,如果还找不到就留个邮箱
[解决办法]
up
[解决办法]
我不发你邮箱了,这个作者真的很厚道,不支持说不过去,csdn应该不少人看过的,感谢作者分享
baidu -> skin+5.0.rar
http://topic.csdn.net/t/20060926/12/5048699.html
[解决办法]
我现在对您的问题一一作个回答。

1. 诡异的 WM_NCCALCSIZE. 这个消息在 MSDN 上也说的不是很清楚。
它在 wParam为真或假时 lParam 分别指向的内容不一样。而 MDSN 上也不是说的太说细,测试了很久也不是很明白,找到的一些代码只是说在 wParam 为真时,第一个矩形为窗口的位置,直接把它改小就可以了。但问题是第一次执行程序,居然不触发 WM_NCCALCSIZE 事件。但拉动窗口大小时,它又会触发。

答:WM_NCCALCSIZE消息就是设置窗体的客户区与非客户区的大小。下面是Skin++的相关代码,你可以参考之。

C/C++ code
LRESULT CSkinObjectBase::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){    switch(msg)    {        case WM_NCCALCSIZE:        return OnNcCalcSize((BOOL)wParam, (NCCALCSIZE_PARAMS *)lParam );        。。。。。。。。。        }}LRESULT CSkinFrameBase::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *lpncsp){    if ( bCalcValidRects )    {        CRect oldrect = lpncsp->rgrc[0];        NcCalcSize(lpncsp->rgrc[0]);        lpncsp->rgrc[1] = lpncsp->rgrc[0];        return 0;    }    return Default();}void CSkinFrameBase::NcCalcSize(RECT& rect){    if (HasCaption())    {        rect.left +=  m_nBorderLeftWidth;//窗体左边框的宽度        rect.right -= m_nBorderRightWidth;//窗体右边框的宽度        rect.top += m_nTitleHeight; //窗体标题栏的高度        rect.bottom -= m_nBorderBottomHeight;//窗体底边框的高度    }                。。。。。。。。} 


[解决办法]
mark
[解决办法]
支持搂主,收藏
[解决办法]
2楼的, happyparrot ,高人终于出来了,连续6年的潜水张于出来了,有他在,csdn社区就有希望。
[解决办法]
21楼的fafa_cai实在,我喜欢!!!虽然你现在还不是专家头衔,但我感觉你还是比较牛。
小弟尚有几个问题需要请教,不知能否帮忙?
[解决办法]
谁有skin5.0代码,请发我一份。一直对这个很感兴趣。
邮箱:dxd_09101011@163.com
谢谢。

热点排行