win32 api 实现不规则形状按钮

最近在看<<Windows环境下32位汇编语言程序设计>>这本书。与其说在看汇编,更像是在看windows sdk.这本书基本上就是<<Windows程序设计>>的汇编版。但是我觉得这本书比<<Windows程序设计>>看起来更舒服,也许是那本书是翻译过来的原因吧,总觉得看起来没有这本书说得透彻。


看了78章,收获非常大,都是win32 api方面的收获。具体的知识点就不罗列了,总的说有几个关键性的技术比一下了解了,感觉很爽。当然,收获大也跟自己太菜的原因有关,要是我特别牛奔,早就啥都知道了,看啥也就都不会觉得有收获了~


比较让我兴奋的,是创建不规则窗口、窗口的随意拖动等东西。这些东西书上都有例子,照着例子按也不觉得如何复杂。创建不规则窗口主要依赖SetWindowRgn这个API.窗口能够不规则了,按钮可不可以呢?


直接给按钮这个子窗口SetWindowRgn是行不通的。

上网上搜索了许多不规则按钮,都是MFC的例子,没有SDK的,于是自己琢磨了琢磨,也上网上提问了,终于解决了问题。


给子窗口设置形状,依然需要SetWindowRgn.

但是区别在于,子窗口都包含CS_PARENTDC,需要把这个东西从Class中去除,才能使得SetWindowRgn生效.


步骤

1.GetClassLong,取出Style,

2.Style=Style and (not CS_PARENTDC)

3.SetClassLong,设置为新的Style

做完了这3步骤,就可以像设置对话框一样形状一样,SetWindowRgn~


汇编代码主要是这几句

 

; Get handle of btn

invoke GetDlgItem,hWnd,IDC_NOTBLOCK

mov @hBtn,eax


; Delete CS_PARENTDC from btn

invoke GetClassLong,@hBtn,GCL_STYLE

mov @BtnStyle,eax

mov eax,0ffffH

xor eax,CS_PARENTDC

and @BtnStyle,eax

invoke SetClassLong,@hBtn,GCL_STYLE,@BtnStyle


; Set btn's region

invoke CreateEllipticRgn,0,0,130,130

push eax

invoke SetWindowRgn,@hBtn,eax,FALSE

pop eax

invoke DeleteObject,eax


 


这里面有个值得注意的地方,

那就是 Set/GetClassLongSet/GetWindowLong的区别。把SetClassLong换成SetWindowLong就不管用了。


网上许多地方都说,这两个的区别,一个是设置整个所有类的属性,另外一个是设置单个窗口的。我到现在也不是很理解,也非常希望路过的高人给我留言指点指点。


说说自己的猜测吧:

SetWindowLong能够修改除了类别以外,所能控制的属性

SetClassLong能够修改类别而决定的属性

而且还可能是因为

只有CS_PARENTDC(Class Style)

而没有 "WS_PARENTDC",

所以只能 SetClassLong来消除掉这个属性

上代码:

ns.rc

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include	<resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define		DLG_MAIN		1000
#define		IDC_NOTBLOCK		1001
#define		IDB_BACK		100
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDB_BACK	BITMAP			"back.bmp"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN	DIALOG	100,100,200,200
STYLE	DS_MODALFRAME|WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU
CAPTION	"MiaoLearn"
FONT 9,"宋体"
{
PUSHBUTTON	"我不是方块!",IDC_NOTBLOCK,50,50,100,100
}


ns.asm

		.386
		.model flat,stdcall
		option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include		windows.inc
include		kernel32.inc
includelib	kernel32.lib
include		user32.inc
includelib	user32.lib
include		gdi32.inc
includelib	gdi32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>		
DLG_MAIN	equ		1000
IDC_NOTBLOCK	equ		1001
IDB_BACK	equ		100
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.data?
hInstance	dd		?	
hDlgMain	dd		?	
hBmpBack	dd		?
hBrushBack	dd		?

		.const
		
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain	proc	uses ebx edi esi hWnd,wMsg,wParam,lParam
		
		LOCAL	@hDc
		LOCAL	@stPs:PAINTSTRUCT
		
		LOCAL	@hBtn
		LOCAL	@BtnStyle
		
		mov	eax,wMsg
		.if	eax==WM_INITDIALOG
			push	hWnd
			pop	hDlgMain
			
			;	Get handle of btn
			invoke	GetDlgItem,hWnd,IDC_NOTBLOCK
			mov	@hBtn,eax
			
			;	Delete CS_PARENTDC from btn
			invoke	GetClassLong,@hBtn,GCL_STYLE
			mov	@BtnStyle,eax
			mov	eax,0ffffH
			xor	eax,CS_PARENTDC
			and	@BtnStyle,eax
			invoke	SetClassLong,@hBtn,GCL_STYLE,@BtnStyle
			
			;	Set btn's region
			invoke	CreateEllipticRgn,0,0,130,130
			push	eax
			invoke	SetWindowRgn,@hBtn,eax,FALSE
			pop	eax
			invoke	DeleteObject,eax
			
		.elseif eax==WM_PAINT
		
			;	draw a background for seeing result
			invoke	BeginPaint,hWnd,addr @stPs	
			mov	@hDc,eax
			
			invoke	LoadBitmap,hInstance,IDB_BACK
			mov	hBmpBack,eax
			invoke	CreatePatternBrush,hBmpBack
			mov	hBrushBack,eax
			invoke	SelectObject,@hDc,hBrushBack
			invoke	PatBlt,@hDc,0,0,300,300,PATCOPY
			invoke	DeleteObject,eax
			
			invoke	EndPaint,hWnd,addr @stPs
			
			
			
		.elseif	eax==WM_CLOSE
			invoke	DeleteObject,hBmpBack
			invoke	EndDialog,hWnd,NULL
		.else
			mov	eax,FALSE
			ret
		.endif
		mov	eax,TRUE
		ret
_ProcDlgMain	endp
start:
	invoke	GetModuleHandle,NULL
	mov	hInstance,eax
	invoke	DialogBoxParam,hInstance,DLG_MAIN,NULL,_ProcDlgMain,NULL
	invoke	ExitProcess,NULL
end	start		
		



 

截图:

ns.exe


Ps:

为了便于观察,给了DIALOG一个背景.中间那个圆形的是按钮,可以点的……

如果想用位图绘制按钮,就在父窗口里处理WM_DRAWITEM事件即可。

如果想实现一个比较复杂的窗口,可以控制Rgn,具体可以参考Rgn相关的API.

本想把这个实例做复杂点,把最近觉得新鲜的东西全用上,但是时间有限啊~

而且我想做的其它功能书上都有,就择出来这个书上没提的功能,把它说清楚吧

ps:

本来打算和小静静十一期间浪漫浪漫的,但是限制于各种因素,没浪起来…………

但是咱们那天去怀柔,玩的也挺好的。

 


最近的小静静很烦....都在烦些什么呢?

1.十一休息完了,又该上班了,小静静迎来了不爽期。

2.因为一下要上7天班,导致小静静一直愁眉苦脸;

3.再加上胃疼、肚子疼、牙碎等身体因素困扰小静静,小静静的心情更是雪上加霜了;

4.再再加上小静静总觉得自己胖了(其实一点也没有鄙视),所以小静静的心情一下跌落到了谷底。

 

乖乖的小静静呀~

咱们周六就去医院看看你的胃、肚子和牙,

然后咱们跑跑步锻炼锻炼,别不高兴了~

至于上班连续7天……

这个没办法了,还请可爱的小静静再忍忍吧!

 

小静静不爽没有关系,我最大的兴趣爱好同时也是我所有课余时间都投身的事业,就是当小静静的出气筒阿!!

有啥不爽就来A我吧!!



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值