【Win32】 解惑 WM_SETICON中图标变换异常(细!!!)

在Windows编程中,使用WM_SETICON消息改变窗口图标时,遇到大图标和小图标切换不生效的问题。原因在于WM_SETICON的参数设置。正确做法是始终使用ICON_BIG作为wParam参数,这样无论是大图标还是小图标,都会跟随设置的图标变化。

作者:Mitu_-_

本帖内容著作权归作者所有,转载请务必保留本文链接

今天在用SendMessage函数给WM_SETICON发送消息改变图标时发现:

1.如果刚开始设置了wParam参数为ICON_BIG(即设置大图标类型) 的话,WM_SETICON会将窗口标题栏、任务栏、Alt+Tab的图标都设为由SendMessage传来的lParam参数所指向的图标。
刚打开时

2.而进行第二次变换图标时,将wParam参数设为ICON_SMALL(即小图标类型)时,会发现只有窗口标题栏的图标变成想要的图标,
而任务栏、Alt+Tab的图标却没有发生改变
点击小图标
3.之后无论再点小图标还是大图标,图标都不会再变化了
再点击大图标


这是SendMessage句法:

LRESULT SendMessage(
  HWND   hWnd,
  UINT   Msg,
  WPARAM wParam,
  LPARAM lParam
这里放入部分代码:

*这是在创建窗口时载入图标并获得图标的句柄

.if  eax ==  WM_CREATE
			invoke	LoadIcon, hInstance, ICO_BIG
			mov hIcoBig, eax
			invoke	LoadIcon, hInstance, ICO_SMALL
			mov	hIcoSmall, eax

*这里通过WM_COMMAND消息来处理图标

invoke	SendMessage, hWnd, WM_COMMAND, IDM_BIG, NULL

.elseif	eax == WM_COMMAND
			mov eax, wParam
			movzx eax, ax		;如果加速键唤醒,就把高16位置零
			.if eax == IDM_EXIT
				call _Quit
			.elseif eax == IDM_BIG
				invoke	SendMessage, hWnd, WM_SETICON, ICON_BIG, hIcoBig
				invoke	CheckMenuRadioItem, hMenu, IDM_BIG, IDM_SMALL, IDM_BIG,MF_BYCOMMAND
			.elseif eax == IDM_SMALL
				invoke	SendMessage, hWnd, WM_SETICON, ICON_SMALL, hIcoSmall
				invoke	CheckMenuRadioItem, hMenu, IDM_BIG, IDM_SMALL, IDM_SMALL,MF_BYCOMMAND

我也纳闷过一阵子,不过再仔细一思考就发现其中的原因了:

WM_SETION介绍

上面这句话的意思是:将新的大图标或小图标与窗口关联。系统在ALT + TAB对话框中显示大图标,在窗口标题中显示小图标。



而WM_SetIcon接收的参数为wParam:
WM_SETICON所接收的参数

*上面的意思是:
ICON_BIG 设置窗口的大图标(即Alt+Tab图标)
ICON_SMALL 设置窗口的小图标(即窗口标题栏图标)

那么,如果按我的理解,发生如上所示问题的原因就是:
1.最初设置为大图标时会默认将大图标应用到窗口标题栏、任务栏和Alt+Tab中去;
(但是窗口标题栏没有被真正的覆盖,只是默认使用ICON_BIG设置的图标)
2.再设置小图标时,则由ICON_SAMLL设置窗口图标,仅会设置窗口标题栏的图标,其他还是大图标样式;
(这时窗口标题栏才被ICON_SMALL设置的图标真正地覆盖了)
3.接下来再点击大图标时,由ICON_BIG设置图标,仅会把Alt+Tab和任务栏的图标变换,而窗口标题栏仍是只能由ICON_SMALL掌控。
所以接下来无论怎么换,窗口图标样式都不会变化了。



如果想要切换大小图标按钮时,让所有的图标也随之变换那么如下所示:

解决方法:

将wParam参数都设为ICON_BIG,调用函数时只会默认地用当时ICON_BIG所设置的图标,而窗口标题栏图标并不会真正地被覆盖。你换大标题(wParam参数为ICON_BIG),所有图标就用大图标设置的图标。你换小标题(wParam参数也为IOCN_BIG),就用小标题设置的图标。

/**就打个比方吧~~~:
//
假如食堂每天做的饭都不是你喜欢吃的,而你只能吃食堂的饭。那么今天食堂做这个饭你就只能吃这个饭,明天做那个,就只能吃那个饭,,也就是“所见即所得”。
但它不会覆盖你心中理想的饭。假如你在家,那么这时你就可以做你心中想吃的饭了,无论食堂做什么,你也都不会理会,吃自己做的就OK了。
//

*这里放修改后的样式图
第一次打开
点击小图标
再点击大图标

下面是改过后_ProcWinMain的完整代码:

_ProcWinMain  proc  uses ebx edi esi,hWnd,uMsg,wParam,lParam
  
		mov  eax,uMsg
;***********************************************************************************
		.if  eax ==  WM_CREATE
			invoke	LoadIcon, hInstance, ICO_BIG
			mov hIcoBig, eax
			invoke	LoadIcon, hInstance, ICO_SMALL
			mov	hIcoSmall, eax
			invoke	LoadCursor, hInstance, CUR_1
			mov hCur1, eax
			invoke	LoadCursor, hInstance, CUR_2
			mov hCur2, eax
			invoke	SendMessage, hWnd, WM_COMMAND, IDM_BIG, NULL
			invoke	SendMessage, hWnd, WM_COMMAND, IDM_CUR1, NULL
;***********************************************************************************
;处理菜单及加速键消息
;***********************************************************************************
		.elseif	eax == WM_COMMAND
			mov eax, wParam
			movzx eax, ax		;如果是加速键唤醒,就把高16位置零
			.if eax == IDM_EXIT
				call _Quit
			.elseif eax == IDM_BIG
			;WM_SETICON收到wParam参数,来设置ICO_BIG(大窗标)的类型,lParam是载入的图标
				invoke	SendMessage, hWnd, WM_SETICON, ICON_BIG, hIcoBig
				invoke	CheckMenuRadioItem, hMenu, IDM_BIG, IDM_SMALL, IDM_BIG,MF_BYCOMMAND
			.elseif eax == IDM_SMALL
				invoke	SendMessage, hWnd, WM_SETICON, ICON_BIG, hIcoSmall
				invoke	CheckMenuRadioItem, hMenu, IDM_BIG, IDM_SMALL, IDM_SMALL,MF_BYCOMMAND	
			.elseif eax == IDM_CUR1
				invoke	SetClassLong, hWnd, GCL_HCURSOR, hCur1
				invoke	CheckMenuRadioItem, hMenu, IDM_CUR1, IDM_CUR2, IDM_CUR1,MF_BYCOMMAND
			.elseif eax == IDM_CUR2
				invoke	SetClassLong, hWnd, GCL_HCURSOR, hCur2
				invoke	CheckMenuRadioItem, hMenu, IDM_CUR1, IDM_CUR2, IDM_CUR2,MF_BYCOMMAND
			.endif
;***********************************************************************************
		.elseif  eax ==  WM_CLOSE
			call	_Quit
;***********************************************************************************
		.else
			invoke  DefWindowProc,hWnd,uMsg,wParam,lParam
			ret
		.endif
;***********************************************************************************
		xor  eax,eax
		ret
  
_ProcWinMain  endp

谢谢你能观看到最后^ _ ^ ❤️ ❤️ ❤️
这是我第一次写blog,肯定会有很多的不足之处,还望大家多多指正并提出建议。
我会坚持下去的!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值