seniors 发表于 2011-11-25 09:40:05

重设控件区域问题[已解决]

本帖最后由 seniors 于 2011-11-28 15:21 编辑



问题描述,我想自绘三角形按钮,用到了控件区域设置函数_WinAPI_SetWindowRgn
现在情况是,运行程序,第二图,第二个按钮把第一按钮覆盖,但点击任何按钮后,又不再覆盖,如第一图
不知道这个_WinAPI_SetWindowRgn应该放在什么地方才能解决此问题
窗口风格加上$WS_CLIPCHILDREN解决了
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <WinAPIEx.au3>

Dim $aPoint = [,,];向上三角形区域

Dim $bPoint = [,,];向下三角形区域

Global $hGUI, $nButton, $nButton2, $GUIMsg

GUIRegisterMsg($WM_DRAWITEM, "MY_WM_DRAWITEM")
Example()

Func Example()
        Local Const $BS_OWNERDRAW = 0x0000000B
       

        $hGUI = GUICreate("自绘按钮", 300, 200,-1,-1,BitOR($WS_MINIMIZEBOX,$WS_CAPTION,$WS_POPUP,$WS_SYSMENU,$WS_CLIPCHILDREN))

        $nButton = GUICtrlCreateButton("上", 5, 5, 50, 40)
        GUICtrlSetStyle($nButton, BitOR($WS_TABSTOP, $BS_NOTIFY, $BS_OWNERDRAW)) ; 设置自绘标志
        $hRgn = _WinAPI_CreatePolygonRgn($aPoint)
        _WinAPI_SetWindowRgn(GUICtrlGetHandle($nButton), $hRgn, 1);重设按钮区域

        $nButton2 = GUICtrlCreateButton("下", 40, 5, 50, 40)
        GUICtrlSetStyle($nButton2, BitOR($WS_TABSTOP, $BS_NOTIFY, $BS_OWNERDRAW)); 设置自绘标志
        $hRgn2 = _WinAPI_CreatePolygonRgn($bPoint)
        _WinAPI_SetWindowRgn(GUICtrlGetHandle($nButton2), $hRgn2, 1);重设按钮区域


        GUISetState()

        While 1
                $GUIMsg = GUIGetMsg()
               
                Switch $GUIMsg
                        Case $GUI_EVENT_CLOSE
                                ExitLoop
                               
                        Case $nButton
                                MsgBox(0, "点击消息", "按钮上点击了", -1, $hGUI)
                               
                        Case $nButton2
                                MsgBox(0, "点击消息", "按钮下点击了", -1, $hGUI)
                EndSwitch
        WEnd

EndFunc   ;==>Example


Func MY_WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
        Local $stDrawItem = DllStructCreate("uint;uint;uint;uint;uint;uint;uint;int;dword", $lParam)
        Local Const $ODT_BUTTON = 4
       
        $nCtlType = DllStructGetData($stDrawItem, 1);要求自绘的控件类型$ODT_BUTTON 是Owner-drawn button
        If $nCtlType = $ODT_BUTTON Then
                $nCtrlID = DllStructGetData($stDrawItem, 2);控件ID,菜单自绘无此参数,3为itemID菜单ITEM,4为itemAction

                $nItemState = DllStructGetData($stDrawItem, 5)
                $hCtrl = DllStructGetData($stDrawItem, 6);控件句柄 A handle to the control for combo boxes, list boxes, buttons, and static controls. For menus, this member is a handle to the menu that contains the item.

                $hDC = DllStructGetData($stDrawItem, 7);设备句柄 A handle to a device context; this device context must be used when performing drawing operations on the control
                $nLeft = DllStructGetData($stDrawItem, 8, 1)
                $nTop = DllStructGetData($stDrawItem, 8, 2)
                $nRight = DllStructGetData($stDrawItem, 8, 3)
                $nBottom = DllStructGetData($stDrawItem, 8, 4)
                $nTextColor = 0xFFFFFFFF
                $nBackColor = 0xFFEEDD
                DrawButton($hWnd, $nCtrlID, $hDC, $nLeft, $nTop, $nRight, $nBottom, $nItemState, $nTextColor, $nBackColor)
                $stDrawItem = 0
                Return 1
        EndIf

        $stDrawItem = 0
        Return $GUI_RUNDEFMSG ; Proceed the default Autoit3 internal message commands
EndFunc   ;==>MY_WM_DRAWITEM


Func DrawButton($hWnd, $nCtrlID, $hDC, $nLeft, $nTop, $nRight, $nBottom, $nItemState, $nTextColor, $nBackColor)
        ;Local $bDefault        = FALSE
        Local Const $GWL_STYLE = -16
        Local Const $ODS_SELECTED = 0x0001
        Local Const $ODS_GRAYED = 0x0002
        Local Const $ODS_DISABLED = 0x0004
        Local Const $ODS_CHECKED = 0x0008
        Local Const $ODS_FOCUS = 0x0010
        Local Const $ODS_HOTLIGHT = 0x0040
        Local Const $ODS_INACTIVE = 0x0080
        Local Const $ODS_NOACCEL = 0x0100
        Local Const $ODS_NOFOCUSRECT = 0x0200
        Local Const $DFC_BUTTON = 4
        Local Const $DFCS_BUTTONPUSH = 0x0010
        Local $bChecked = BitAND($nItemState, $ODS_CHECKED)
        Local $bFocused = BitAND($nItemState, $ODS_FOCUS)
        Local $bGrayed = BitAND($nItemState, BitOR($ODS_GRAYED, $ODS_DISABLED))
        Local $bSelected = BitAND($nItemState, $ODS_SELECTED)

        $tRect = DllStructCreate("int;int;int;int")
        DllStructSetData($tRect, 1, $nLeft)
        DllStructSetData($tRect, 2, $nTop)
        DllStructSetData($tRect, 3, $nRight)
        DllStructSetData($tRect, 4, $nBottom)
        $hBrush = _WinAPI_GetSysColorBrush($COLOR_BTNFACE)
       
        Switch $nCtrlID
                Case $nButton
                        _DrawTria($hDC, _MyTriangle($tRect, 2, 6, 8), $hBrush);绘制三角形边线,2,6,8分别是上中,左下,右下
                       
                Case $nButton2
                        _DrawTria($hDC, _MyTriangle($tRect, 7, 1, 3), $hBrush);绘制三角形边线,7,1,3,分别是下中,左上,右上
        EndSwitch
       
        _WinAPI_DrawText($hDC, @LF & GUICtrlRead($nCtrlID), $tRect, BitOR($DT_VCENTER, $DT_CENTER));绘制按钮文字
        _WinAPI_DeleteObject($hBrush)
        Return 1
EndFunc   ;==>DrawButton


Func _MyTriangle($tRect, $T1, $T2, $T3);返回三角形三顶点坐标
        Local $tTriA
        Switch $T1
                Case 1
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 2)
                Case 2
                        $tTriA = DllStructGetData($tRect, 3) / 2
                        $tTriA = DllStructGetData($tRect, 2)
                Case 3
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 2)
                Case 4
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 4) / 2
                Case 5
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 4) / 2
                Case 6
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 4) - 1
                Case 7
                        $tTriA = DllStructGetData($tRect, 3) / 2
                        $tTriA = DllStructGetData($tRect, 4) - 1
                Case 8
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 4) - 1
        EndSwitch
        Switch $T2
                Case 1
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 2)
                Case 2
                        $tTriA = DllStructGetData($tRect, 3) / 2
                        $tTriA = DllStructGetData($tRect, 2)
                Case 3
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 2)
                Case 4
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 4) / 2
                Case 5
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 4) / 2
                Case 6
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 4) - 1
                Case 7
                        $tTriA = DllStructGetData($tRect, 3) / 2
                        $tTriA = DllStructGetData($tRect, 4) - 1
                Case 8
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 4) - 1
        EndSwitch
        Switch $T3
                Case 1
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 2)
                Case 2
                        $tTriA = DllStructGetData($tRect, 3) / 2
                        $tTriA = DllStructGetData($tRect, 2)
                Case 3
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 2)
                Case 4
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 4) / 2
                Case 5
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 4) / 2
                Case 6
                        $tTriA = DllStructGetData($tRect, 1)
                        $tTriA = DllStructGetData($tRect, 4) - 1
                Case 7
                        $tTriA = DllStructGetData($tRect, 3) / 2
                        $tTriA = DllStructGetData($tRect, 4) - 1
                Case 8
                        $tTriA = DllStructGetData($tRect, 3) - 1
                        $tTriA = DllStructGetData($tRect, 4) - 1
        EndSwitch

        Return $tTriA
EndFunc   ;==>_MyTriangle

Func _InflateTriA($tTriA, $Dx, $Dy);三角形缩放,未完成
        Local $min, $max
        $min = $tTriA
        $max = $tTriA
        If $tTriA > $min Then
                $max = $tTriA
        Else
                $min = $tTriA
        EndIf
        If $tTriA > $max Then $max = $tTriA
        If $tTriA < $min Then $min = $tTriA
        For $ii = 0 To 2
                If $tTriA[$ii] == $min Then $tTriA[$ii] -= $Dx
                If $tTriA[$ii] == $max Then $tTriA[$ii] += $Dx
        Next
        $min = $tTriA
        $max = $tTriA
        If $tTriA > $min Then
                $max = $tTriA
        Else
                $min = $tTriA
        EndIf
        If $tTriA > $max Then $max = $tTriA
        If $tTriA < $min Then $min = $tTriA
        For $ii = 0 To 2
                If $tTriA[$ii] == $min Then $tTriA[$ii] -= $Dy
                If $tTriA[$ii] == $max Then $tTriA[$ii] += $Dy
        Next
        Return $tTriA
EndFunc   ;==>_InflateTriA

Func _DrawTria($hDC, $tTriA, $hBrush);绘制三角形
        Local $hOldBrush = _WinAPI_SelectObject($hDC, $hBrush)
        _WinAPI_SetBkMode($hDC, $TRANSPARENT)
        _WinAPI_MoveTo($hDC, $tTriA, $tTriA)
        _WinAPI_LineTo($hDC, $tTriA, $tTriA)
        _WinAPI_LineTo($hDC, $tTriA, $tTriA)
        _WinAPI_LineTo($hDC, $tTriA, $tTriA)
        _WinAPI_SelectObject($hDC, $hOldBrush)
        _WinAPI_DeleteObject($hBrush)
       
EndFunc   ;==>_DrawTria

dodolovely 发表于 2011-11-25 09:50:18

作为一个新手,看到这些代码,表示鸭梨很大

seniors 发表于 2011-11-25 10:02:49

大家多是从新手过来的

seniors 发表于 2011-11-25 22:29:03

第二页了,顶一下

seniors 发表于 2011-11-28 15:20:00

问题解决,只要加上$WS_CLIPCHILDREN窗口风格就可以了

afan 发表于 2011-11-28 15:35:47

加上$WS_CLIPCHILDREN样式后,如果按钮被其它窗体覆盖或移出该窗口至屏幕外,貌似按钮将不会更新

seniors 发表于 2011-11-28 16:33:00

回复 6# afan
其它窗体覆盖,可以更新
移出该窗口至屏幕外好像没更新,再找找办法看

tiger_47 发表于 2013-8-28 17:17:08

請問大大:小弟有個問題想請教
line-54: Local Const $ODT_BUTTON = 4 ...
line-57: If $nCtlType = $ODT_BUTTON Then ...
為何設定 $ODT_BUTTON = 4 ?
難不成 按鈕 傳回 為 4 ?
其他控件傳回值為何?
請問何處有詳述?小弟爬了一些文,都找不到?
謝謝!
页: [1]
查看完整版本: 重设控件区域问题[已解决]