找回密码
 加入
搜索
查看: 3768|回复: 4

[GUI管理] 给pic控件设置不同的图片有残影,求教~

[复制链接]
发表于 2012-9-21 09:34:41 | 显示全部楼层 |阅读模式
本帖最后由 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判断,并不是一个句柄啊。奇了怪了。一并求教!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2012-9-21 11:25:13 | 显示全部楼层
IsHWnd改成IsObj
 楼主| 发表于 2012-9-21 15:05:18 | 显示全部楼层
本帖最后由 xiehuahere 于 2012-9-21 15:48 编辑

回复 2# seniors

不行啊,IsObj返回的也是0。
$hBMPObj = GUICtrlSendMsg($pic, $STM_SETIMAGE, 0, $hCloseBMP)
MsgBox(0, 0, IsObj($hBmObj))
STM_SETIMAGE究竟返回啥?
PS:我看到了官网上的用法:
_WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap))
竟然是不作判断直接删除。。。很是蛋疼!

我看了你的“仿360界面”,按钮不是用pic控件,而是用自绘矩形区域的方法来做的。
但我觉得那样比较复杂,Hover和Press的时候得自行处理。所以想尝试下用pic控件来做的方法。

当然,最简单的就是用label控件写个x,然后变字体颜色。我不想这样。
发表于 2012-9-21 16:05:31 | 显示全部楼层
本帖最后由 seniors 于 2012-9-21 16:12 编辑

STM_SETIMAGE返回的是旧的图片对象,本来就应该直接删除,不删除的话会增加对象的
 楼主| 发表于 2012-10-8 15:05:54 | 显示全部楼层
这个残影问题还是不知道如何解决、、、
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-26 22:06 , Processed in 0.081687 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表