weixin_52765502 2023-02-07 20:28 采纳率: 100%
浏览 31
已结题

关于修改GUI控件的问题

关于Autohotkey 修改GUI控件Background 颜色窗口崩溃
win10 x64、Autohotkey1.1.36
使用gdi32.dll\SetBkColor修改控件Background 颜色,在修改同一个控件9910次后窗口崩溃,或都修改多个控件,累计达到9910次后窗口崩溃,只是窗口崩溃了,脚本仍然正常运行(如fileappend仍然正常往文件写内容),增加延时无变化,dllcall返回没有错误。
希望可以无限次修改控件Background 颜色,感谢!
#Persistent
#Singleinstance force
#Include ControlCol.ahk

Gui Destroy
Gui, Add, Text,         hwndh_1, Text1
Gui, Add, Edit,         hwndh_2, Edit
Gui, Add, Edit,         hwndh_3, Edit
Gui, Add, UpDown,       hwndh_4, UpDown
Gui, Add, Picture,      hwndh_5, Picture
Gui, Add, Button,       hwndh_6, Button
Gui, Add, CheckBox,     hwndh_7, CheckBox
Gui, Add, Radio,        hwndh_8, Radio
Gui, Add, ListBox,      hwndh_9, ListBox
Gui, Add, Link,         hwndh_10, Link


Gui, Add, Edit, w320 h50 HwndMyTextHwnd,  Here is some text that is given`na custom background color.
Gui, Add, Edit, w320 h50 HwndMyTextHwnd2, Here is some text that is given`na custom background color.
Gui, Add, Edit, w320 h50 HwndMyTextHwnd3, Here is some text that is given`na custom background color.
Gui +LastFound
GuiHwnd := WinExist()
;MsgBox, % GuiHwnd
Gui Show
loop
{
    Sleep, 50
    Random, t, 0, 0xffffff
    Random, b, 0, 0xffffff
    ;MsgBox, %t%, %b%
    t := "0x" SubStr(Format("{:p}", t), 3)
    b := "0x" SubStr(Format("{:p}", b), 3)
    
    loop, 10 {    
        ControlCol(H_%A_Index%, GuiHwnd, b, t)    
    }    
    
    GuiControl, text, Edit5, %A_Index%
}

ControlCol(h_1, hMainWnd, 0x9FCFFF, 0xffffff)
ControlCol(MyTextHwnd2, hMainWnd, 0x00ff00, 0x0000ff)
ControlCol(MyTextHwnd3, hMainWnd, 0x0000ff, 0xff0000)
count := 0
;SetTimer, c, 500
return

c:
Random, b, 0, 0xffffff
Random, t, 0, 0xffffff
ControlCol(MyTextHwnd,GuiHwnd, b, t)
ControlCol(MyTextHwnd2,GuiHwnd, b, t)
abc := ControlCol(MyTextHwnd3,GuiHwnd, b, t)
count ++
GuiControl, text, Edit5, %Count% %abc%
return

f4::
ExitApp
return


GuiClose:
ExitApp

ControlCol.ahk

; ------------------------
; http://www.autohotkey.com/board/topic/104539-controlcol-set-background-and-text-color-gui-controls/
; v1.0.2
; ------------------------
ControlCol(Control, Window, bc="", tc="", redraw=1) {
        ; msgbox
    a := []
    a["c"]  := Control
    a["g"]  := Window
    a["bc"] := (bc="")?"":(((bc&255)<<16)+(((bc>>8)&255)<<8)+(bc>>16))
    a["tc"] := (tc="")?"":((tc&255)<<16)+(((tc>>8)&255)<<8)+(tc>>16)
    
    WindowProc("Set", a, "", "")
    If redraw
    {
        SizeOfWINDOWINFO := 10
        VarSetCapacity(WINDOWINFO, SizeOfWINDOWINFO, 0)       
        NumPut(SizeOfWINDOWINFO, WINDOWINFO, "UInt")
        DllCall("GetWindowInfo",  "Ptr", Control, "Ptr", &WINDOWINFO)
        ;FileAppend, GetWindowInfo %ErrorLevel%`n, %A_ScriptDir%\ControlCol.log
        DllCall("ScreenToClient", "Ptr", Window,  "Ptr", &WINDOWINFO+20) ; x1,y1 of Client area
        ;FileAppend, ScreenToClient %ErrorLevel%`n, %A_ScriptDir%\ControlCol.log
        DllCall("ScreenToClient", "Ptr", Window,  "Ptr", &WINDOWINFO+28) ; x2,y2 of Client area
        ;FileAppend, ScreenToClient %ErrorLevel%`n, %A_ScriptDir%\ControlCol.log
        DllCall("RedrawWindow"
        , "Ptr",  Window             ; A handle to the window to be redrawn. If this parameter is NULL, the desktop window is updated.
        , "UInt", &WINDOWINFO+20    ; A pointer to a RECT structure containing the coordinates, in device units, of the update rectangle. This parameter is ignored if the hrgnUpdate parameter identifies a region.
        , "UInt", 0                    ; A handle to the update region. If both the hrgnUpdate and lprcUpdate parameters are NULL, the entire client area is added to the update region.
        , "UInt", 0x101)            ; One or more redraw flags. This parameter can be used to invalidate or validate a window, control repainting, and control which windows are affected by RedrawWindow.
        ;FileAppend, RedrawWindow %ErrorLevel%`n, %A_ScriptDir%\ControlCol.log
        VarSetCapacity(WINDOWINFO, 0)
    }
    
    return    
}


WindowProc(hwnd, uMsg, wParam, lParam)
{
    Static Win := {}    
    ;Critical
    If uMsg between 0x132 and 0x138    
    If Win[hwnd].HasKey(lparam)
    {
      FileAppend, %A_Now% %A_MSec% %ErrorLevel%`n, %A_ScriptDir%\ControlCol.log
        If tc := Win[hwnd, lparam, "tc"]
        DllCall("SetTextColor", "UInt", wParam, "UInt", tc)
        If bc := Win[hwnd, lparam, "bc"]
        DllCall("SetBkColor", "UInt", wParam, "UInt", bc)
        
        return Win[hwnd, lparam, "Brush"]  ; Return the HBRUSH to notify the OS that we altered the HDC.
    }
    
    ;}
    If (hwnd = "Set")
    {
      ;MsgBox, fsefs
        a := uMsg
        Win[a.g, a.c] := a
        If (Win[a.g, a.c, "tc"] = "") and (Win[a.g, a.c, "bc"] = "")
            Win[a.g].Remove(a.c, "")
        If not Win[a.g, "WindowProcOld"]
            Win[a.g,"WindowProcOld"] := DllCall("SetWindowLong", "Ptr", a.g, "Int", -4, "Int", RegisterCallback("WindowProc", "", 4), "UInt")
        If Win[a.g, a.c, "Brush"]
            DllCall("DeleteObject", "Ptr", Brush)
        If (Win[a.g, a.c, "bc"] != "")
            Win[a.g, a.c, "Brush"] := DllCall("CreateSolidBrush", "UInt", a.bc)
        ; array_list(a)
        return
    } 
    
    q1234 := DllCall("CallWindowProcA", "UInt", Win[hwnd, "WindowProcOld"], "UInt", hwnd, "UInt", uMsg, "UInt", wParam, "UInt", lParam)
    
    return q1234
}

http://www.autohotkey.com/board/topic/104539-controlcol-set-background-and-text-color-gui-controls/

  • 写回答

3条回答 默认 最新

  • 火星的猫FM 2023-02-09 22:19
    关注

    这种情况是由于你的脚本运行次数太多导致的。在修改同一个控件或多个控件多次后窗口崩溃是因为 GDI 对象泄露。GDI 对象是 Windows 使用的图形对象,当你创建太多的 GDI 对象而不释放它们,就会导致 GDI 对象泄露。

    解决方法是使用 gdi32.dll 的 DeleteObject 函数来释放创建的 GDI 对象。可以在 ControlCol.ahk 中添加一个函数来删除之前创建的 GDI 对象:

    ControlCol.ahk:

    ; ------------------------
    ; http://www.autohotkey.com/board/topic/104539-controlcol-set-background-and-text-color-gui-controls/
    ; v1.0.2
    ; ------------------------
    ControlCol(Control, Window, bc="", tc="", redraw=1) {
    static hBrush
    ; ...
    if (hBrush)
    DllCall("gdi32.dll\DeleteObject", "ptr", hBrush)
    ; ...
    }

    这样,在每次调用 ControlCol 函数时都会释放上一次创建的 GDI 对象,避免 GDI 对象泄露。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月23日
  • 已采纳回答 2月15日
  • 赞助了问题酬金20元 2月9日
  • 创建了问题 2月7日

悬赏问题

  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan