分享
 
 
 

仿制金山毒霸的标题栏

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

仿制金山毒霸的标题栏

千变一律的界面总是让人觉得缺乏新意,在功能相当的一系列软件中大家肯定偏爱那些界面看起来赏心悦目的,如果我们能够给自己的软件加一个与众不同标题栏是不是也能为我们的软件增色不少呢!下面是我仿照金山毒霸的界面做的一个标题栏,运行效果如下。例子



原理

要定制标题栏,我们可以在 Windows 提供的标题栏上绘制自己所要实现的效果。但因为总的框架在那,再怎么绘制也不过是加几个控件,写一些彩色的字,像上图这样的效果似乎很难实现。在这我采用的方法是:去掉缺省的标题栏,画一个自己的标题栏。

在定制对话框模板时指定 WS_POPUP 风格就可以得到一个没有标题栏的对话框,也可以在对话框初始化时通过 SetWindowLong 设置窗口风格来去掉标题栏。

缺省提供的标题栏没了我们就需要自己画一个标题栏。分为两个部分:外表的实现,功能的实现。通过在 Static 控件上加载位图就能够实现标题栏的外表显示,如上图,一共采用了三个 Static 控件来加载标题栏位图、最小化按钮位图、关闭按钮位图。

功能的实现有:窗口的拖动,关闭按钮的响应,最小化按钮的响应。窗口的拖动我们只需要在鼠标左键按下时判断是否是在我们绘制的标题栏范围内,如果在,就给窗口发送 WM_NCLBUTTONDOWN 消息。按钮的响应有鼠标移到按钮上按钮变亮,鼠标按下时按钮产生按下效果等。首先子类化两个 Static 按钮控件,在其中处理 WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP 等消息,根据不同的消息和鼠标是否按下等来加载不同的位图,从而产生按钮加亮、按钮按下等不同效果。

标题栏画好后如果还继续采用窗口缺省的灰灰的界面势必会影响整体效果,所以我们通过处理 WM_CTLCOLORDLG 消息来改变背景颜色。

例子

.386

.model flat,stdcall

option casemap:none

;****************************************************************************************

include c:\masm32\include\windows.inc

include c:\masm32\include\user32.inc

include c:\masm32\include\kernel32.inc

include c:\masm32\include\gdi32.inc

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

includelib c:\masm32\lib\gdi32.lib

;****************************************************************************************

RGB macro red,green,blue

xor eax,eax

mov ah,blue

shl eax,8

mov ah,green

mov al,red

endm

;****************************************************************************************

DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD

CloseBtnProc proto :DWORD,:DWORD,:DWORD,:DWORD

MinBtnProc proto :DWORD,:DWORD,:DWORD,:DWORD

;****************************************************************************************

.data

DlgName db "DLG_MAIN",0

szCaption db "仿制金山毒霸的标题栏",0

.data?

hInstance HINSTANCE ?

hBmp1 dd ?

hBmp2 dd ?

hBmp3 dd ?

hBmp4 dd ?

hBmp5 dd ?

hBmp6 dd ?

hBmp7 dd ?

hCaption dd ?

hClose dd ?

hMin dd ?

bMouseDown dd ?

.const

IDI_MAIN equ 900

IDB_BITMAP1 equ 901

IDB_BITMAP2 equ 902

IDB_BITMAP3 equ 903

IDB_BITMAP4 equ 904

IDB_BITMAP5 equ 905

IDB_BITMAP6 equ 906

IDB_BITMAP7 equ 907

IDC_STATIC_CAPTION equ 2001

IDC_STATIC_MIN equ 2002

IDC_STATIC_CLOSE equ 2003

;****************************************************************************************

.code

start:

invoke GetModuleHandle, NULL

mov hInstance,eax

invoke DialogBoxParam,hInstance,addr DlgName,NULL,addr DlgProc,0

invoke ExitProcess,eax

;对话框窗口过程**************************************************************************

DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

local pt:POINT

local rect:RECT

local hDC:HDC

.IF uMsg==WM_CLOSE

invoke EndDialog,hWnd,NULL

.ELSEIF uMsg==WM_INITDIALOG

invoke SendMessage, hWnd, WM_SETTEXT, 0, addr szCaption

;加载图像

invoke LoadBitmap, hInstance, IDB_BITMAP1

mov hBmp1, eax

invoke LoadBitmap, hInstance, IDB_BITMAP2

mov hBmp2, eax

invoke LoadBitmap, hInstance, IDB_BITMAP3

mov hBmp3, eax

invoke LoadBitmap, hInstance, IDB_BITMAP4

mov hBmp4, eax

invoke LoadBitmap, hInstance, IDB_BITMAP5

mov hBmp5, eax

invoke LoadBitmap, hInstance, IDB_BITMAP6

mov hBmp6, eax

invoke LoadBitmap, hInstance, IDB_BITMAP7

mov hBmp7, eax

;子类化“关闭”和“最小化”按钮

invoke GetDlgItem, hWnd, IDC_STATIC_CAPTION

mov hCaption, eax

invoke GetDlgItem, hWnd, IDC_STATIC_CLOSE

mov hClose, eax

invoke SetWindowLong, hClose, GWL_WNDPROC, addr CloseBtnProc

invoke SetWindowLong, hClose, GWL_USERDATA, eax

invoke GetDlgItem, hWnd, IDC_STATIC_MIN

mov hMin, eax

invoke SetWindowLong, hMin, GWL_WNDPROC, addr MinBtnProc

invoke SetWindowLong, hMin, GWL_USERDATA, eax

mov bMouseDown, FALSE

;重新设置窗口大小

invoke GetClientRect, hWnd, addr rect

sub rect.right, 2

invoke SetWindowPos, hWnd, 0, 0, 0, rect.right, rect.bottom, SWP_NOZORDER or SWP_NOMOVE

;画出窗口的边缘线

.ELSEIF uMsg==WM_PAINT

invoke GetDC, hWnd

mov hDC, eax

invoke GetClientRect, hWnd, addr rect

sub rect.right, 1

sub rect.bottom, 2

invoke MoveToEx, hDC, 0, 30, NULL

invoke LineTo, hDC, 0, rect.bottom

invoke MoveToEx, hDC, 0, rect.bottom, NULL

invoke LineTo, hDC, rect.right, rect.bottom

invoke MoveToEx, hDC, rect.right, rect.bottom, NULL

invoke LineTo, hDC, rect.right, 29

mov eax, FALSE

ret

;改变对话框的背景色,为了和标题栏协调起来

.ELSEIF uMsg==WM_CTLCOLORDLG

RGB 0F0h, 0F0h, 0F0h

invoke CreateSolidBrush, eax

ret

;拖动窗口

.ELSEIF uMsg==WM_LBUTTONDOWN

invoke GetCursorPos, addr pt

invoke ScreenToClient, hWnd, addr pt

.IF pt.y<30 && pt.x<420

invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, 2, 0

.ENDIF

.ELSE

mov eax,FALSE

ret

.ENDIF

mov eax,TRUE

ret

DlgProc endp

;“关闭”按钮窗口过程********************************************************************

CloseBtnProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

local pt:POINT

.IF uMsg==WM_NCHITTEST

mov eax, TRUE

ret

.ELSEIF uMsg==WM_LBUTTONDOWN

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4

mov bMouseDown, TRUE

.ELSEIF uMsg==WM_MOUSEMOVE

invoke GetCursorPos, addr pt

invoke WindowFromPoint, pt.x, pt.y

.IF eax==hWnd

invoke SetCapture, hWnd

.IF bMouseDown

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4

.ELSE

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3

.ENDIF

.ELSE

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp2

.IF!bMouseDown

invoke ReleaseCapture

.ENDIF

.ENDIF

.ELSEIF uMsg==WM_LBUTTONUP

invoke GetCursorPos, addr pt

invoke WindowFromPoint, pt.x, pt.y

.IF eax==hWnd

.IF bMouseDown

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3

invoke GetParent, hWnd

invoke SendMessage, eax, WM_CLOSE, 0, 0

.ENDIF

.ENDIF

invoke ReleaseCapture

mov bMouseDown, FALSE

.ELSE

invoke GetWindowLong, hWnd, GWL_USERDATA

invoke CallWindowProc, eax, hWnd, uMsg, wParam, lParam

ret

.ENDIF

xor eax,eax

ret

CloseBtnProc endp

MinBtnProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

local pt:POINT

.IF uMsg==WM_NCHITTEST

mov eax, TRUE

ret

.ELSEIF uMsg==WM_LBUTTONDOWN

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp7

mov bMouseDown, TRUE

.ELSEIF uMsg==WM_MOUSEMOVE

invoke GetCursorPos, addr pt

invoke WindowFromPoint, pt.x, pt.y

.IF eax==hWnd

invoke SetCapture, hWnd

.IF bMouseDown

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp7

.ELSE

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp6

.ENDIF

.ELSE

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp5

.IF!bMouseDown

invoke ReleaseCapture

.ENDIF

.ENDIF

.ELSEIF uMsg==WM_LBUTTONUP

invoke GetCursorPos, addr pt

invoke WindowFromPoint, pt.x, pt.y

.IF eax==hWnd

.IF bMouseDown

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp6

invoke GetParent, hWnd

invoke ShowWindow, eax, SW_MINIMIZE

.ENDIF

.ENDIF

invoke ReleaseCapture

mov bMouseDown, FALSE

.ELSE

invoke GetWindowLong, hWnd, GWL_USERDATA

invoke CallWindowProc, eax, hWnd, uMsg, wParam, lParam

ret

.ENDIF

xor eax,eax

ret

MinBtnProc endp

end start

分析

invoke GetDlgItem, hWnd, IDC_STATIC_CAPTION

mov hCaption, eax

invoke GetDlgItem, hWnd, IDC_STATIC_CLOSE

mov hClose, eax

invoke SetWindowLong, hClose, GWL_WNDPROC, addr CloseBtnProc

invoke SetWindowLong, hClose, GWL_USERDATA, eax

invoke GetDlgItem, hWnd, IDC_STATIC_MIN

mov hMin, eax

invoke SetWindowLong, hMin, GWL_WNDPROC, addr MinBtnProc

invoke SetWindowLong, hMin, GWL_USERDATA, eax

mov bMouseDown, FALSE

首先取得“关闭”按钮和“最小化”按钮的句柄,然后分别子类化以截获消息处理消息。

invoke GetClientRect, hWnd, addr rect

sub rect.right, 2

invoke SetWindowPos, hWnd, 0, 0, 0, rect.right, rect.bottom, SWP_NOZORDER or SWP_NOMOVE

改变窗口的大小,主要是为了匹配标题栏的宽度。

.ELSEIF uMsg==WM_PAINT

invoke GetDC, hWnd

mov hDC, eax

invoke GetClientRect, hWnd, addr rect

sub rect.right, 1

sub rect.bottom, 2

invoke MoveToEx, hDC, 0, 30, NULL

invoke LineTo, hDC, 0, rect.bottom

invoke MoveToEx, hDC, 0, rect.bottom, NULL

invoke LineTo, hDC, rect.right, rect.bottom

invoke MoveToEx, hDC, rect.right, rect.bottom, NULL

invoke LineTo, hDC, rect.right, 29

mov eax, FALSE

ret

处理 WM_PAINT 消息,分别在窗口的左边、下边和右边画上边界线,这样一来有一种平面效果正好匹配我们的标题栏。

.ELSEIF uMsg==WM_LBUTTONDOWN

invoke GetCursorPos, addr pt

invoke ScreenToClient, hWnd, addr pt

.IF pt.y<30 && pt.x<420

invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, 2, 0

.ENDIF

在鼠标按下时判断是不是在我们绘制的标题栏范围内,在这除去了右边“关闭”按钮和“最小化”按钮占去的位置。

.IF uMsg==WM_NCHITTEST

mov eax, TRUE

ret

返回 TRUE 从而实现鼠标消息的截获。

.ELSEIF uMsg==WM_LBUTTONDOWN

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4

mov bMouseDown, TRUE

.ELSEIF uMsg==WM_MOUSEMOVE

invoke GetCursorPos, addr pt

invoke WindowFromPoint, pt.x, pt.y

.IF eax==hWnd

invoke SetCapture, hWnd

.IF bMouseDown

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4

.ELSE

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3

.ENDIF

.ELSE

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp2

.IF!bMouseDown

invoke ReleaseCapture

.ENDIF

.ENDIF

.ELSEIF uMsg==WM_LBUTTONUP

invoke GetCursorPos, addr pt

invoke WindowFromPoint, pt.x, pt.y

.IF eax==hWnd

.IF bMouseDown

invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3

invoke GetParent, hWnd

invoke SendMessage, eax, WM_CLOSE, 0, 0

.ENDIF

.ENDIF

invoke ReleaseCapture

mov bMouseDown, FALSE

在鼠标按下时加载按下效果的位图,并设置标志位标志鼠标处在按下状态。在 WM_MOUSEMOVE 消息中先取得鼠标位置,判断是否在按钮上,如果在按钮上,则锁定鼠标消息,然后根据鼠标是否正按下来加载按钮按下的位图或按钮加亮的位图。如果不在按钮上,则加载正常的位图,然后判断鼠标是否正处在按下的状态,如果不是,则说明只是鼠标经过按钮上而已,可以释放鼠标;如果正处在按下状态,则不能释放鼠标,因为如果这时候释放鼠标,当鼠标移出按钮然后弹起时我们就接收不到消息,所以要留到 WM_LBUTTONUP 消息中释放鼠标。在 WM_LBUTTONUP 消息中也是先取得鼠标位置,判断是否在按钮上,如果在,再判断鼠标是否处在按下状态,接着就可以发送消息实现按钮的功能。最后释放鼠标,设置标志位标志鼠标已经弹起。

CopyRight (C) 2001-2002 一块三毛钱

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有