透明皮肤控件设计系列(四):皮肤窗口完结篇
经过上面的几篇文章的介绍,相信大家已经会自己做一个透明皮肤窗口了,但是要记住,上文因为是基础教程,所以很多细节仍然是需要处理的,例如:
1、为了加快速度,实际上可以先用MakeBmp函数制作好皮肤图片,平均颜色就是取图片右下角的一个点即可。例如QQ的皮肤包就是这么干的。
2、如果实在想运行时计算,那么可以先将图片缩小,再计算平均颜色。这样一来,循环的次数就减少了,而效果是一样的。
3、为了美观,边框可以画个线条上去,这样一来立体感就强很多:
另外,还要其它一些细节,例如 Caption,如果平均颜色是黑色,那么字体应该自动换成白色。我在这里偷了个懒,直接使用了Blur算法,根据字体直接在下面画一个对应的浅色区域,这样一来,即使背景色偏暗,也不影响标题的字体颜色。
另外,还可以做成控件形式,例如我们的AQ控件:
做成控件形式的话,代码可以更加模块化。我们的控件是分为两个系列:NC系列和 CLIENT 系列。顾名思义,NC系列的控件就是工作于NC区的,CLIENT则是工作于CLIENT区。
看一下我们的鼠标信息函数:
function OnClientMouseMove(): Boolean;
varP: TPoint;
beginP.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;
varP: TPoint;
beginP.X := Short(LoWord(Message.lParam));P.Y := Short(HiWord(Message.lParam));ClientToScreen(FForm.Handle, P);Result := NCMouseUp(P.X, P.Y)
end;WM_NCMOUSEMOVE:beginif (not NCMouseMove(LoWord(Message.lParam), HiWord(Message.lParam))) thenFOldWinProc(Message)elseMessage.Result := 0;
end;......也就是说,窗口、NC的鼠标消息,都是直接传递给NC函数去处理,以鼠标移动为例,处理如下:
function TAQCustomForm.NCMouseDown(X, Y: Integer): Boolean;
vari: Integer;
beginwith FForm dofor i := ComponentCount – 1 downto 0 doif Components[i] is TAQCustomNCCtrlBase thenwith TAQCustomNCCtrlBase(Components[i]) doif PtInRect(GetWindowRect(), Point(X, Y)) thenbeginFIsMouseDown := True;MouseDown(X, Y);Result := True;exit;end;Result := False;
end;
也就是说,如果鼠标位于NC控件上,则通知控件处理:
procedure TAQCustomNCCtrl.MouseDown(X, Y: Integer);
beginif Assigned(FOnMouseDown) thenFOnMouseDown(Self, X, Y);
end;
procedure TAQCustomNCButton.Paint(Canvas: TCanvas);
beginif SkinData = nil thenExit;if not Visible thenExit;if IsMouseDown and IsMouseEnter and (GetPicDown().Graphic <> nil) thenCanvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight),GetPicDown.Graphic)else if IsMouseEnter and (GetPicHighLight().Graphic <> nil) thenCanvas.StretchDraw(Rect(FLeft, FTop – 1, FLeft + FWidth,FTop + FHeight – 1), GetPicHighLight.Graphic)elseCanvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight),GetPicNormal.Graphic);
end;
TAQSysMinButton = class(TAQCustomSysButton)privateprotectedprocedure Click(); override;function GetPicNormal(): TPicture; override;function GetPicDown(): TPicture; override;function GetPicHighLight(): TPicture; override;publicconstructor Create(AOwner: TComponent); override;publishedend;这样处理后,需要多增加一个NC控件的话,只要从基类继承,然后重载GetPicXXX函数,返回状态图片即可,而窗口代码不需要作任何修改。我们的演示代码使用了一个Timer检测状态,改成控件后,是可以去掉的:
function TAQCustomForm.NCMouseDown(X, Y: Integer): Boolean;
vari: Integer;
beginwith FForm dofor i := ComponentCount – 1 downto 0 doif Components[i] is TAQCustomNCCtrlBase thenwith TAQCustomNCCtrlBase(Components[i]) doif PtInRect(GetWindowRect(), Point(X, Y)) thenbeginFIsMouseDown := True;MouseDown(X, Y);Result := True;exit;end;Result := False;
end;也就是说,如果鼠标位于NC控件上,则通知控件处理:
procedure TAQCustomNCCtrl.MouseDown(X, Y: Integer);
beginif Assigned(FOnMouseDown) thenFOnMouseDown(Self, X, Y);
end;
procedure TAQCustomNCButton.Paint(Canvas: TCanvas);
beginif SkinData = nil thenExit;if not Visible thenExit;if IsMouseDown and IsMouseEnter and (GetPicDown().Graphic <> nil) thenCanvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight),GetPicDown.Graphic)else if IsMouseEnter and (GetPicHighLight().Graphic <> nil) thenCanvas.StretchDraw(Rect(FLeft, FTop – 1, FLeft + FWidth,FTop + FHeight – 1), GetPicHighLight.Graphic)elseCanvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight),GetPicNormal.Graphic);
end;
TAQSysMinButton = class(TAQCustomSysButton)privateprotectedprocedure Click(); override;function GetPicNormal(): TPicture; override;function GetPicDown(): TPicture; override;function GetPicHighLight(): TPicture; override;publicconstructor Create(AOwner: TComponent); override;publishedend;
procedure TAQCustomNCCtrl.MouseDown(X, Y: Integer);beginif Assigned(FOnMouseDown) thenFOnMouseDown(Self, X, Y);
end;
procedure TAQCustomNCButton.Paint(Canvas: TCanvas);
beginif SkinData = nil thenExit;if not Visible thenExit;if IsMouseDown and IsMouseEnter and (GetPicDown().Graphic <> nil) thenCanvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight),GetPicDown.Graphic)else if IsMouseEnter and (GetPicHighLight().Graphic <> nil) thenCanvas.StretchDraw(Rect(FLeft, FTop – 1, FLeft + FWidth,FTop + FHeight – 1), GetPicHighLight.Graphic)elseCanvas.StretchDraw(Rect(FLeft, FTop, FLeft + FWidth, FTop + FHeight),GetPicNormal.Graphic);
end;
TAQSysMinButton = class(TAQCustomSysButton)privateprotectedprocedure Click(); override;function GetPicNormal(): TPicture; override;function GetPicDown(): TPicture; override;function GetPicHighLight(): TPicture; override;publicconstructor Create(AOwner: TComponent); override;publishedend;这样处理后,需要多增加一个NC控件的话,只要从基类继承,然后重载GetPicXXX函数,返回状态图片即可,而窗口代码不需要作任何修改。
我们的演示代码使用了一个Timer检测状态,改成控件后,是可以去掉的:
function TAQCustomForm.NCMouseMove(X, Y: Integer): Boolean;procedure CheckPrev(New: TAQCustomNCCtrlBase);vari: Integer;beginwith FForm dofor i := 0 to ComponentCount – 1 doif (Components[i] is TAQCustomNCCtrlBase) and (Components[i] <> New)thenwith TAQCustomNCCtrlBase(Components[i]) doif FIsMouseEnter thenbeginFIsMouseEnter := False;if not FIsMouseDown thenReleaseCapture();MouseLeave();end;end;
vari: Integer;
beginResult := False;with FForm dofor i := ComponentCount – 1 downto 0 doif Components[i] is TAQCustomNCCtrlBase thenwith TAQCustomNCCtrlBase(Components[i]) doif PtInRect(GetWindowRect(), Point(X, Y)) thenbeginMouseMove(X, Y);if not FIsMouseEnter thenbeginCheckPrev(TAQCustomNCCtrlBase(FForm.Components[i]));FIsMouseEnter := True;SetCapture(FForm.Handle);MouseEnter();end;Result := True;exit;endelse if FIsMouseEnter thenbeginFIsMouseEnter := False;if not FIsMouseDown thenReleaseCapture();MouseLeave();end;
end;
另外,为了多个窗口共享一张图片,可以制作一个DATA控件,用于存储图片:
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
