透明皮肤控件设计系列(四):皮肤窗口完结篇
来源:互联网 发布:北方网络视频 编辑:程序博客网 时间:2024/06/05 05:18
经过上面的几篇文章的介绍,相信大家已经会自己做一个透明皮肤窗口了,但是要记住,上文因为是基础教程,所以很多细节仍然是需要处理的,例如:
1、为了加快速度,实际上可以先用MakeBmp函数制作好皮肤图片,平均颜色就是取图片右下角的一个点即可。例如QQ的皮肤包就是这么干的。
2、如果实在想运行时计算,那么可以先将图片缩小,再计算平均颜色。这样一来,循环的次数就减少了,而效果是一样的。
3、为了美观,边框可以画个线条上去,这样一来立体感就强很多:
另外,还要其它一些细节,例如 Caption,如果平均颜色是黑色,那么字体应该自动换成白色。我在这里偷了个懒,直接使用了Blur算法,根据字体直接在下面画一个对应的浅色区域,这样一来,即使背景色偏暗,也不影响标题的字体颜色。
另外,还可以做成控件形式,例如我们的AQ控件:
做成控件形式的话,代码可以更加模块化。我们的控件是分为两个系列:NC系列和 CLIENT 系列。顾名思义,NC系列的控件就是工作于NC区的,CLIENT则是工作于CLIENT区。
看一下我们的鼠标信息函数:
我们的演示代码使用了一个Timer检测状态,改成控件后,是可以去掉的:
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.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;
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控件,用于存储图片:
- 透明皮肤控件设计系列(四):皮肤窗口完结篇
- 透明皮肤控件设计系列(二):皮肤窗口初级篇
- 透明皮肤控件设计系列(三):皮肤窗口进阶篇
- 透明皮肤控件设计系列(五):透明控件
- 透明皮肤控件设计系列(一):前言
- Windows mobile 透明/半透明控件组(皮肤控件)
- 皮肤控件---------------------皮肤控件
- QT 实现子控件的透明,可以实现主窗口设置背景皮肤
- 皮肤
- [Box2D]四.添加皮肤
- fckeditor的皮肤系列:皮肤更换
- Winform 皮肤控件
- c# 程序皮肤控件
- vc皮肤控件
- winform皮肤控件
- c# 程序皮肤控件
- c# 程序皮肤控件
- DevExpress控件之皮肤
- 软件实施--1,写这一模块的目的
- corona scene createScene(创建结构)
- vi的复制粘贴命令
- 线上问题解决的自我总结
- QSqlDatabase 简单入门介绍
- 透明皮肤控件设计系列(四):皮肤窗口完结篇
- LINUX FTP安装与配置
- 一个Mina实例
- httpmime-4.1.3 简单使用
- 监听外拨电话
- JSON与XML
- test
- Clojure命名空间中use与require的区别
- ActionBar - Action View