绘制主题元素的技巧(即如何不拉伸绘制)?
Technique for drawing theme element (i.e. how to not stretch draw)?
我正在考虑将自定义主题元素绘制到设备内容上。
例如,我将使用 Windows XP 中的 HeaderItem header/listview:
(18×18 px)
哪个大家可以炸开看看容易一点:
Note: I am not using the Theme API, nor am i asking about using the Theme API.
如果我有像上面那样的位图,我该如何实际绘制它?
拉伸画破坏了风格
需要解决的重要问题是如何维护重要的细节。你可以看到实际的 Windows XP Header 将右边缘的垂直线绘制得漂亮而清晰:
但如果我盲目StretchBlt图像,细节变得模糊:
当图像垂直拉伸时,具有清晰水平特征的主题元素也会出现此问题。在这种情况下,它还会弄乱垂直渐变。但其他一些元素更明显。
那么可以使用什么技术来解决这个问题?
我应该把 6 px
的顶部、左侧、底部和右侧剪掉吗?:
然后我画了九张而不是一张图片?:
并根据位置使用各种水平或垂直拉伸规则绘制它们?:
Unstretched
Horizontally stretched
Unstretched
Vertically stretched
Horizontally and vertically stretched
Vertically stretched
Unstretched
Horizontally stretched
Unstretched
这一定是一个已经解决的问题;因为Windows已经解决了,谁知道还有多少支持主题的Widget库。
Microsoft 对此问题的解决方案可以通过查看 NormalBlue.ini 文件在 Luna.msstyles 中进行逆向工程.查看 Header.HeaderItem 的条目:
NormalBlue.ini:
[Header.HeaderItem]
bgtype = imagefile
SizingMargins = 8, 8, 3, 4
ContentMargins = 3, 0, 0, 0
ImageFile = Blue\ListViewHeader.bmp
imageCount=5
imageLayout=vertical
sizingType = tile
transparent=true
transparentcolor=255 0 0
FillColorHint = 250 248 243; Average fill color (light beige)
AccentColorHint = 252 194 71; Rollover hilite color (orange)
首先我们看到它引用了 \Blue\ListViewHeader.bmp:
ImageFile = Blue\ListViewHeader.bmp
即:
然后是魔法片:
SizingMargins = 8, 8, 3, 4
这对应于TMT_SIZINGMARGINS
:
TMT_SIZINGMARGINS
: The margins used for sizing a non-true-size image.
您可以在 TmSchema.h 中看到更多提示:
//---- rendering MARGIN properties ----
TM_PROP(3601, TMT, SIZINGMARGINS, MARGINS) // margins used for 9-grid sizing
“用于 9 格大小调整的边距”。这是对将图像拆分为 3x3 网格并根据需要独立调整块大小的想法的参考。
最后一块是 MARGINS
类型的文档 UxTheme.h:
typedef struct _MARGINS
{
int cxLeftWidth; // width of left border that retains its size
int cxRightWidth; // width of right border that retains its size
int cyTopHeight; // height of top border that retains its size
int cyBottomHeight; // height of bottom border that retains its size
} MARGINS, *PMARGINS;
及其 documentation:
- cxLeftWidth: int - 保持其大小的左边框宽度。
- cxRightWidth: int - 保持其大小的右边框宽度。
- cyTopHeight: int - 保持其大小的上边框高度。
- cyBottomHeight: int - 保持其大小的底部边框的高度。
砍和油漆
Luna 主题告诉我们,当我们绘制 ListViewHeader.bmp 时,我们需要使用大小边距:
SizingMargins = 8, 8, 3, 4
并将图像切割成 9 块 (3x3)。但是我们需要使用图像设计者想要的尺寸,而不是到处使用 6px(就像我在我的问题中所说的那样):
- 左: 8
- 右:8
- 顶:3
- 底部:4
所以给定设计师在 Photoshop 中创建的 18×18 主题元素图像:
创建图像的人说我的绘图代码需要截断:
- 左 8 像素
- 右8像素
- 前 3 个像素
- 底部 4 个像素
这意味着我必须绘制九张图片中的每一张:
然后向特定方向拉伸绘制一些部分:
- Top-left:绘制未拉伸
- 左:垂直拉伸
- Bottom-left:绘制未拉伸
- 顶部:水平拉伸
- 中间:绘制水平和垂直拉伸
- 底部:水平拉伸绘制
- Top-right:绘制未拉伸
- 右:绘制垂直拉伸
- Bottom-right:绘制未拉伸
我正在考虑将自定义主题元素绘制到设备内容上。
例如,我将使用 Windows XP 中的 HeaderItem header/listview:
哪个大家可以炸开看看容易一点:
Note: I am not using the Theme API, nor am i asking about using the Theme API.
如果我有像上面那样的位图,我该如何实际绘制它?
拉伸画破坏了风格
需要解决的重要问题是如何维护重要的细节。你可以看到实际的 Windows XP Header 将右边缘的垂直线绘制得漂亮而清晰:
但如果我盲目StretchBlt图像,细节变得模糊:
当图像垂直拉伸时,具有清晰水平特征的主题元素也会出现此问题。在这种情况下,它还会弄乱垂直渐变。但其他一些元素更明显。
那么可以使用什么技术来解决这个问题?
我应该把 6 px
的顶部、左侧、底部和右侧剪掉吗?:
然后我画了九张而不是一张图片?:
并根据位置使用各种水平或垂直拉伸规则绘制它们?:
Horizontally stretched |
Unstretched |
|
Horizontally and vertically stretched |
Vertically stretched |
|
Horizontally stretched |
Unstretched |
这一定是一个已经解决的问题;因为Windows已经解决了,谁知道还有多少支持主题的Widget库。
Microsoft 对此问题的解决方案可以通过查看 NormalBlue.ini 文件在 Luna.msstyles 中进行逆向工程.查看 Header.HeaderItem 的条目:
NormalBlue.ini:
[Header.HeaderItem]
bgtype = imagefile
SizingMargins = 8, 8, 3, 4
ContentMargins = 3, 0, 0, 0
ImageFile = Blue\ListViewHeader.bmp
imageCount=5
imageLayout=vertical
sizingType = tile
transparent=true
transparentcolor=255 0 0
FillColorHint = 250 248 243; Average fill color (light beige)
AccentColorHint = 252 194 71; Rollover hilite color (orange)
首先我们看到它引用了 \Blue\ListViewHeader.bmp:
ImageFile = Blue\ListViewHeader.bmp
即:
然后是魔法片:
SizingMargins = 8, 8, 3, 4
这对应于TMT_SIZINGMARGINS
:
TMT_SIZINGMARGINS
: The margins used for sizing a non-true-size image.
您可以在 TmSchema.h 中看到更多提示:
//---- rendering MARGIN properties ----
TM_PROP(3601, TMT, SIZINGMARGINS, MARGINS) // margins used for 9-grid sizing
“用于 9 格大小调整的边距”。这是对将图像拆分为 3x3 网格并根据需要独立调整块大小的想法的参考。
最后一块是 MARGINS
类型的文档 UxTheme.h:
typedef struct _MARGINS
{
int cxLeftWidth; // width of left border that retains its size
int cxRightWidth; // width of right border that retains its size
int cyTopHeight; // height of top border that retains its size
int cyBottomHeight; // height of bottom border that retains its size
} MARGINS, *PMARGINS;
及其 documentation:
- cxLeftWidth: int - 保持其大小的左边框宽度。
- cxRightWidth: int - 保持其大小的右边框宽度。
- cyTopHeight: int - 保持其大小的上边框高度。
- cyBottomHeight: int - 保持其大小的底部边框的高度。
砍和油漆
Luna 主题告诉我们,当我们绘制 ListViewHeader.bmp 时,我们需要使用大小边距:
SizingMargins = 8, 8, 3, 4
并将图像切割成 9 块 (3x3)。但是我们需要使用图像设计者想要的尺寸,而不是到处使用 6px(就像我在我的问题中所说的那样):
- 左: 8
- 右:8
- 顶:3
- 底部:4
所以给定设计师在 Photoshop 中创建的 18×18 主题元素图像:
创建图像的人说我的绘图代码需要截断:
- 左 8 像素
- 右8像素
- 前 3 个像素
- 底部 4 个像素
这意味着我必须绘制九张图片中的每一张:
然后向特定方向拉伸绘制一些部分:
- Top-left:绘制未拉伸
- 左:垂直拉伸
- Bottom-left:绘制未拉伸
- 顶部:水平拉伸
- 中间:绘制水平和垂直拉伸
- 底部:水平拉伸绘制
- Top-right:绘制未拉伸
- 右:绘制垂直拉伸
- Bottom-right:绘制未拉伸