使用纯 Win32 API 绘制 Skin 窗口






4.35/5 (31投票s)
展示如何绘制 Skin 窗口的文章

引言
如何在没有 MFC 扩展 UI 库(如 BGCControlBar、Xtreme Toolkit 等)的情况下,制作应用程序自有的皮肤窗口?本文使用纯 Win32 API 来寻找答案。
目录
Windows 消息
对于初学者,我想解释应该处理的窗口消息。任何想要绘制窗口的人都应该处理如下的窗口消息:
Message | 描述 |
WM_NCPAINT |
当窗口的边框需要被绘制时,会向该窗口发送此消息。我们应该在此处绘制窗口。 |
WM_NCCALCSIZE |
当需要计算窗口客户区的大小和位置时,会向该窗口发送此消息。通过处理此消息,应用程序可以在窗口的大小或位置改变时控制窗口客户区的内容。 |
WM_NCACTIVATE |
当窗口的非客户区需要改变以指示激活或非激活状态时,会向该窗口发送此消息。 |
WM_NCHITTEST |
当鼠标移动或按下/释放鼠标按钮时,会向该窗口发送此消息。如果鼠标未被捕获,则消息会发送到光标下方的窗口。否则,消息会发送到已捕获鼠标的窗口。 |
WM_NCLBUTTONUP |
当用户在窗口的非客户区内释放鼠标左按钮时,会发布此消息。此消息会发布给包含光标的窗口。如果窗口已捕获鼠标,则不会发布此消息。 |
WM_GETMINMAXINFO |
当窗口的大小或位置即将改变时,会向该窗口发送此消息。应用程序可以使用此消息来覆盖窗口的默认最大化大小和位置,或其默认的最小/最大跟踪大小。 |
WM_ACTIVATE |
当一个窗口被激活和另一个窗口被取消激活时,会向这两个窗口发送此消息。如果窗口使用相同的输入队列,则消息是同步发送的。首先发送给被取消激活的顶层窗口的过程,然后发送给被激活的顶层窗口的过程。如果窗口使用不同的输入队列,则消息是异步发送的,因此窗口会立即被激活。 |
SkinWindow 类
我们应该创建一个名为 SkinWindow
的类,负责绘制窗口。SkinWindow
类定义了一些函数来处理特殊的窗口消息。
函数 | 描述 |
OnNcPaint |
处理消息 WM_NCPAINT |
OnNcActive |
处理消息 WM_NCACTIVATE |
OnNcCalcSize |
处理消息 WM_NCCALCSIZE |
OnNcHitTest |
处理消息 WM_NCHITTEST |
OnNcLButtonUp |
处理消息 WM_NCLBUTTONUP |
OnNcLButtonDown |
处理消息 WM_NCLBUTTONDOWN |
OnNcLButtonDblClk |
处理消息 WM_NCLBUTTONDBLCLK |
OnNcMouseMove |
处理消息 WM_NCMOUSEMOVE |
OnNcRButtonUp |
处理消息 WM_NCRBUTTONUP |
OnNcRButtonDown |
处理消息 WM_NCRBUTTONDOWN |
OnSize |
处理消息 WM_SIZE |
OnSizing |
处理消息 WM_SIZING |
OnActive |
处理消息 WM_ACTIVE |
OnWindowPosChanging |
处理消息 WM_WINDOWPOSCHANGING |
OnGetMinMaxInfo |
处理消息 WM_GETMINMAXINFO |
OnSetText |
处理消息 WM_SETTEXT |
OnSysCommand |
处理消息 WM_SYSCOMMAND |
示例
首先,我们创建一个包含 SkinWindow
的新 Win32 应用程序项目。
#include "skinwindow.h"
其次,我们应该在主 CPP 文件中定义一个全局变量。
CSkinWindow SkinWin;
第三,我们在 InitInstance
函数中从资源加载皮肤。
SkinWin.Load(hInstance, hWnd);
最后,我们应该在 WndProc
函数中添加一些代码来处理特殊的窗口消息。
// handle some special window's message here
if( SkinWin.IsHandledMessage( message ) )
return SkinWin.WndProc( hWnd, message, wParam, lParam );
问题/Bug
当你尽可能快地调整窗口大小或拖动移动窗口时,显示器会闪烁,并且窗口会占用更多的 CPU 百分比。我尝试了多种方法,但问题仍然存在。有人能解决这个问题吗?问题的图片如下。

其他说明
这绝不是一个完成的产品!这是我第一次尝试编写一个非常复杂的 Win32 应用程序库。我想告诉初学者如何使用纯 Win32 API 而无需 MFC 来为窗口添加皮肤,并为初学者提供一些关于全面理解窗口消息的提示。我想要一个功能上类似于 SkinWindow
的东西,但没有 MFC 的开销。代码中会有 bug 和错误!希望您发现这些代码很有用。如果您有任何改进/建议、评论/批评或问题,请在此处发布。
历史
- 2007 年 9 月 14 日 -- 发布原始版本