透明皮肤控件设计系列(四):皮肤窗口完结篇
12 Comments 2013-08-11 admin
经过上面的几篇文章的介绍,相信大家已经会自己做一个透明皮肤窗口了,但是要记住,上文因为是基础教程,所以很多细节仍然是需要处理的,例如:
1、为了加快速度,实际上可以先用MakeBmp函数制作好皮肤图片,平均颜色就是取图片右下角的一个点即可。例如QQ的皮肤包就是这么干的。
2、如果实在想运行时计算,那么可以先将图片缩小,再计算平均颜色。这样一来,循环的次数就减少了,而效果是一样的。
3、为了美观,边框可以画个线条上去,这样一来立体感就强很多:
另外,还要其它一些细节,例如 Caption,如果平均颜色是黑色,那么字体应该自动换成白色。我在这里偷了个懒,直接使用了Blur算法,根据字体直接在下面画一个对应的浅色区域,这样一来,即使背景色偏暗,也不影响标题的字体颜色。
另外,还可以做成控件形式,例如我们的AQ控件:
做成控件形式的话,代码可以更加模块化。我们的控件是分为两个系列:NC系列和 CLIENT 系列。顾名思义,NC系列的控件就是工作于NC区的,CLIENT则是工作于CLIENT区。
看一下我们的鼠标信息函数:
function OnClientMouseMove(): Boolean;
var
P: TPoint;
begin
P.X := Short(LoWord(Message.lParam));
P.Y := short(HiWord(Message.lParam));
ClientToScreen(FForm.Handle, P);
Result := NCMouseMove(P.X, P.Y – 1)
end;
function OnClientMouseUp(): Boolean;
var
P: TPoint;
begin
P.X := Short(LoWord(Message.lParam));
P.Y := short(HiWord(Message.lParam));
ClientToScreen(FForm.Handle, P);
Result := NCMouseUp(P.X, P.Y)
end;
WM_NCMOUSEMOVE:
begin
if (not NCMouseMove(LoWord(Message.lParam), HiWord(Message.lParam))) then
FOldWinProc(Message)
else
Message.Result := 0;
end;
……
也就是说,窗口、NC的鼠标消息,都是直接传递给NC函数去处理,以鼠标移动为例,处理如下:
function TAQCustomForm.NCMouseDown(X, Y: Integer): Boolean;
var
i: Integer;
begin
with FForm do
for i := ComponentCount – 1 downto 0 do
if Components[i] is TAQCustomNCCtrlBase then
with TAQCustomNCCtrlBase(Components[i]) do
if PtInRect(GetWindowRect(), Point(X, Y)) then
begin
FIsMouseDown := True;
MouseDown(X, Y);
Result := True;
exit;
end;
Result := False;
end;
也就是说,如果鼠标位于NC控件上,则通知控件处理:
procedure TAQCustomNCCtrl.MouseDown(X, Y: Integer);
begin
if Assigned(FOnMouseDown) then
FOnMouseDown(Self, X, Y);
end;
procedure TAQCustomNCButton.Paint(Canvas: TCanvas);
begin
if SkinData = nil then
Exit;
if not Visible then Exit;
if IsMouseDown and IsMouseEnter and (GetPicDown().Graphic <> nil) then
Canvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight), GetPicDown.Graphic)
else
if IsMouseEnter and (GetPicHighLight().Graphic <> nil) then
Canvas.StretchDraw(Rect(FLeft, FTop – 1, FLeft + FWidth, FTop + FHeight – 1), GetPicHighLight.Graphic)
else
Canvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight), GetPicNormal.Graphic);
end;
TAQSysMinButton = class(TAQCustomSysButton)
private
protected
procedure Click(); override;
function GetPicNormal(): TPicture; override;
function GetPicDown(): TPicture; override;
function GetPicHighLight(): TPicture; override;
public
constructor Create(AOwner: TComponent); override;
published
end;
这样处理后,需要多增加一个NC控件的话,只要从基类继承,然后重载GetPicXXX函数,返回状态图片即可,而窗口代码不需要作任何修改。
我们的演示代码使用了一个Timer检测状态,改成控件后,是可以去掉的:
function TAQCustomForm.NCMouseMove(X, Y: Integer): Boolean;
procedure CheckPrev(New: TAQCustomNCCtrlBase);
var
i: Integer;
begin
with FForm do
for i := 0 to ComponentCount – 1 do
if (Components[i] is TAQCustomNCCtrlBase) and (Components[i] <> New) then
with TAQCustomNCCtrlBase(Components[i]) do
if FIsMouseEnter then
begin
FIsMouseEnter := False;
if not FIsMouseDown then
ReleaseCapture();
MouseLeave();
end;
end;
var
i: Integer;
begin
Result := False;
with FForm do
for i := ComponentCount – 1 downto 0 do
if Components[i] is TAQCustomNCCtrlBase then
with TAQCustomNCCtrlBase(Components[i]) do
if PtInRect(GetWindowRect(), Point(X, Y)) then
begin
MouseMove(X, Y);
if not FIsMouseEnter then
begin
CheckPrev(TAQCustomNCCtrlBase(FForm.Components[i]));
FIsMouseEnter := True;
SetCapture(FForm.Handle);
MouseEnter();
end;
Result := True;
exit;
end else
if FIsMouseEnter then
begin
FIsMouseEnter := False;
if not FIsMouseDown then
ReleaseCapture();
MouseLeave();
end;
end;
另外,为了多个窗口共享一张图片,可以制作一个DATA控件,用于存储图片:
后面我们将介绍透明控件、滚动条等的处理。
分类:界面设计
12 Comments 发表评论
施主,能否借源码一阅?
还是自己写的好,因为我那个已经作为公司界面库了,实在不好意思。
楼主大侠不能发源码,发个exe也行,
让俺们欣赏一下,过过眼瘾
请教一下,如果前面的那些东西。作成一个控件呢?
新手求教;
关于控件的教材网上非常多,你可以自己搜索看看。
你就当成是一个新手教程,教教吧。谢谢。
我觉得,网上讲那些,都看不懂
还是你讲得清楚。
我太菜了。不好意思。
我是不会写这种到处都有的东西的,实在不好意思。毕竟我也不是专业靠写教程吃饭的。
开始讲得还算细致,后来就很模糊了
博主标题栏文字具有阴影效果,能贴一下代码么?如果整个界面用这种文字效果,会不会很卡?
不会卡。窗口阴影效果倒不是这样弄的。
能发一个blur的算法给我么?是不是就是阿发伯的那个?另外,你的这些皮肤控件貌似还没用到gdi+和分层窗口?牛。。
就是那个,你自己提取吧。我不懂gdi+的。
发表评论
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
TrackBack URL | RSS feed for comments on this post.