使用纯 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 日 -- 发布原始版本


