本帖最后由 xiehuahere 于 2012-10-8 17:12 编辑
问题如下图,右上角的关闭按钮,鼠标移走后还有红色残影显示。
如何消除呢?
为了方便,我把图片以二进制写在了代码里。
#include <GUIConstants.au3>
#Include <SendMessage.au3>
#include <WindowsConstants.au3>
#include <GDIPlusEx.au3>
#include <Memory.au3>
#include "GUICtrlSetOnHover_UDF.au3" ;get it from 本论坛 http://goo.gl/Dj8cM
Opt("GUIOnEventMode", 1)
Local Const $STM_SETIMAGE = 0x0172
Local Const $iWidth = 230, $iHeight = 45
Local $hGUI, $pic, $hBMPObj
Local Const $hCloseBMP = _ImgProcess(Binary("0x89504E470D0A1A0A0000000D494844520000000E0000000E08060000001F" & _
"482DD10000008F494441542891A592B10DC4200C45CDE976618C140C9405E8C802D98714D902D6489BE25D8504C4" & _
"B9D3912F51F0E5FFFD655B6410061812BEEACFB265962D5F9C541E1040424C1C271C278498F8C5BFB518F364A574" & _
"9827AB672D0EBD7BFFEA6E402BBC13F722A01DCE5F781CB5178598D0B8AF51D73D8B77D67867CDBA673569733965" & _
"05DE59531769FCF0C90DE3036C9213179B46BF4D0000000049454E44AE426082"))
Local Const $hCloseBMPOver = _ImgProcess(Binary("0x89504E470D0A1A0A0000000D494844520000000E0000000E08060000" & _
"001F482DD10000011C494441542891BD91314FC24018861F2CC6D5F82FBAB0BBF90B880B386062EAEC220B83C681" & _
"C0C0024B27064913871A96863F40B7CEB8184646164C484C29E5FA3934D7D050191C7C934BEE9ECB9BEFBDF7E08F" & _
"2AE9CDD87644053E00C6E515B587BBD2315ED64615F8DCBCBD02F07E7BCFD876A4886B9DEC8F977887C43BEAA321" & _
"2AF051814F7D34CC78A1C6B6236EC312B5FE2E5C6EC3129DE2D0DC1988DBB0245EAE64335FC866BE9078B94A4D9D" & _
"41CE54CE39CF2F0048C20DEA6B9DB677769ABBD33A68F5FAE9A5308DD76DE75ACDCA51814FB5D92209239230C2EB" & _
"B6F1BAEDEC5C6DB6D0DF92330224D19624DA32E9F730CC0A865961D2EF65FC685400C3AC507B7E2CE9C2D4E747CA" & _
"F7A2E6DF319D89379D1D54FE1BFF5FFD001CDDBCCF470267760000000049454E44AE426082"))
$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOR($WS_BORDER, $WS_POPUP), BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))
GUISetBkColor(0x19619C)
$pic = GUICtrlCreatePic("", $iWidth - 18, 1, 14, 14)
;MSDN: http://goo.gl/F61tA :The return value is a handle to the image previously associated with the static control, if any; otherwise, it is NULL.
$hBmObj = GUICtrlSendMsg(-1, $STM_SETIMAGE, 0, $hCloseBMP)
If IsHWnd($hBmObj) Then _WinAPI_DeleteObject($hBMPObj) ;http://goo.gl/7DtzU
GUICtrlSetOnHover(-1, "_Hover", "_Leave_Hover")
GUICtrlSetOnEvent(-1, "_Exit")
GUISetState()
While 1
Sleep(100)
WEnd
Func _Hover($ctrlId)
If $ctrlId = $pic Then
$hBMPObj = GUICtrlSendMsg($pic, $STM_SETIMAGE, 0, $hCloseBMPOver)
If IsHWnd($hBmObj) Then _WinAPI_DeleteObject($hBMPObj)
EndIf
EndFunc
Func _Leave_Hover($ctrlId)
If $ctrlId = $pic Then
$hBMPObj = GUICtrlSendMsg($pic, $STM_SETIMAGE, 0, $hCloseBMP)
If IsHWnd($hBmObj) Then _WinAPI_DeleteObject($hBMPObj)
EndIf
EndFunc
Func _Exit()
Exit
EndFunc
Func _ImgProcess(Const $bBinary);Merged code by Progandy and Zedna
Local $iLen = BinaryLen($bBinary)
If $iLen = 0 Then Return SetError(2, 0, 0)
Local $hMem = _MemGlobalAlloc($iLen, $GMEM_MOVEABLE)
If @error Or Not $hMem Then Return SetError(3, 0, 0)
DllStructSetData(DllStructCreate("byte[" & $iLen & "]", _MemGlobalLock($hMem)), 1, $bBinary)
If @error Then
_MemGlobalUnlock($hMem)
_MemGlobalFree($hMem)
Return SetError(4, 0, 0)
EndIf
_MemGlobalUnlock($hMem)
_GDIPlus_Startup()
Local $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $hMem, "bool", True, "ptr*", 0)
If @error Or $aResult[0] <> 0 Or $aResult[3] = 0 Then Return SetError(5, @error, 0)
Local $hImage = DllCall($ghGDIPDll, "uint", "GdipLoadImageFromStream", "ptr", $aResult[3], "int*", 0)
Local $error = @error
Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")
DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $aResult[3], "dword", 8 + 8 * @AutoItX64, "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT))
If @error Then Return SetError(6, $error, 0)
If $hImage[2] = 0 Then Return SetError(7, 0, $hImage[2])
Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage[2])
_GDIPlus_ImageDispose($hImage[2])
_GDIPlus_Shutdown()
Return SetError(0, 0, $hBitmap)
EndFunc ;==>_ImgProcess
我尝试过删除pic控件再重建,但这样可以看到明显的闪烁。所以不可行。是png图片本身的问题吗?
最简单的方法:用label控件写个x,然后改变字体颜色和控制位置,这样是没问题的。但我仍然想知道pic控件产生的这种问题如何解决。
此外,还发现有内存泄露。每次set image(鼠标移上去或移走)就泄露4K大小的内存。
网上查了下(http://goo.gl/7DtzU),说每次STM_SETIMAGE后要接收返回值(图像对象),并释放其句柄。
但我用IsHWnd判断,并不是一个句柄啊。奇了怪了。一并求教! |