65.9K
CodeProject 正在变化。 阅读更多。
Home

使用纯 Win32 API 绘制 Skin 窗口

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.35/5 (31投票s)

2007年9月14日

CPOL

3分钟阅读

viewsIcon

143029

downloadIcon

9602

展示如何绘制 Skin 窗口的文章

Screenshot - drawwindow1.gif

引言

如何在没有 MFC 扩展 UI 库(如 BGCControlBar、Xtreme Toolkit 等)的情况下,制作应用程序自有的皮肤窗口?本文使用纯 Win32 API 来寻找答案。

目录

Windows 消息

对于初学者,我想解释应该处理的窗口消息。任何想要绘制窗口的人都应该处理如下的窗口消息:

Message 描述
WM_NCPAINT 当窗口的边框需要被绘制时,会向该窗口发送此消息。我们应该在此处绘制窗口。
WM_NCCALCSIZE 当需要计算窗口客户区的大小和位置时,会向该窗口发送此消息。通过处理此消息,应用程序可以在窗口的大小或位置改变时控制窗口客户区的内容。
WM_NCACTIVATE 当窗口的非客户区需要改变以指示激活或非激活状态时,会向该窗口发送此消息。
WM_NCHITTEST 当鼠标移动或按下/释放鼠标按钮时,会向该窗口发送此消息。如果鼠标未被捕获,则消息会发送到光标下方的窗口。否则,消息会发送到已捕获鼠标的窗口。
WM_NCLBUTTONUP
WM_NCLBUTTONDOWN
WM_NCLBUTTONDBLCLK
WM_NCRBUTTONUP
WM_NCRBUTTONDOWN
WM_NCMOUSEMOVE
当用户在窗口的非客户区内释放鼠标左按钮时,会发布此消息。此消息会发布给包含光标的窗口。如果窗口已捕获鼠标,则不会发布此消息。
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 百分比。我尝试了多种方法,但问题仍然存在。有人能解决这个问题吗?问题的图片如下。

Screenshot - drawwindow2.gif

其他说明

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

历史

  • 2007 年 9 月 14 日 -- 发布原始版本
© . All rights reserved.