找回密码
 加入
搜索
查看: 6584|回复: 13

[GUI管理] (已解决) 设置水平滚动条滑块位置导致后添加控件位置与预期不符

  [复制链接]
发表于 2015-4-26 13:48:33 | 显示全部楼层 |阅读模式
本帖最后由 yhxhappy 于 2015-4-27 17:32 编辑

小弟我在一个子窗口画折线图,如果曲线长度超过窗口宽度则需要加大客户区并添加水平滚动条

现在的问题是:
我需要曲线向前延伸时,水平滚动条始终滚动到最右端。
使用_GUIScrollBars_SetScrollInfoPos 后可以达到效果。但窗口上的个别控件位置竟然不对了,折线不受影响。
而注释掉这条(86行)后所有控件X坐标就正常。

一直找不到原因,就差这一步了。




以下代码是我做的一个演示的例子
#include <GUIConstantsEx.au3>
#include <GuiScrollBars.au3>
#include <StructureConstants.au3>
#include <WindowsConstants.au3>

$GUI = GUICreate("滾動條 UDF 示例", 660, 450, -1, -1)

$Button = GUICtrlCreateButton("开始画线", 100, 20, 100, 30)


Global $sGUI_W = 600, $sGUI_H = 300, $sGUI_W2 = $sGUI_W
Global $sGUI_X = 24, $sGUI_Y = 100
Global $Line_X = 0        ;        曲线起始X坐标,每画一截加 $1Unit_W
Global $1Unit_W = 30        ;每一截的宽度
Global $isWinMove_H = False                ;False表示子窗口未加高过,否则加高18,用于显示水平滚动条

Local $aY = $sGUI_Y
For $i = 100 To 0 Step -10                                                                                        ;画刻度线
   GUICtrlCreateLabel("", $sGUI_X+1, $aY, 9999999, 1)
          GUICtrlSetBkColor(-1, 0xfff100)
   GUICtrlCreateLabel($i & "-", 0, $aY-5, 24, 15, 0x0002)
          GUICtrlSetFont(-1, 8)
          GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
   $aY += $sGUI_H/100*10
Next


;===曲线子窗口===============================================================================
Global $sGUI = GUICreate("", $sGUI_W, $sGUI_H, $sGUI_X, $sGUI_Y, $WS_CHILD+$WS_BORDER, "", $GUI)
   GUISetBkColor(0x88AABB)

Global $LineGraphic = GUICtrlCreateGraphic(0, 0, 1, 1)
          GUICtrlSetState(-1, $GUI_DISABLE)
Global $LineNum = 0
GUICtrlSetGraphic($LineGraphic, $GUI_GR_MOVE, $Line_X, $sGUI_H)                        ;将曲线起始点定于左下角。

_GUIScrollBars_Init($sGUI, 9999999999999999999)                                                        ;先将窗口滚动条初始化到一个很大的值
_GUIScrollBars_ShowScrollBar($sGUI, $SB_VERT, False)                                                ;设置水平滚动条隐藏
_GUIScrollBars_ShowScrollBar($sGUI, $SB_HORZ, False)                                                ;设置水平滚动条隐藏

GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")
;======================================================

GUISetState(@SW_SHOW, $GUI)
GUISetState(@SW_SHOW, $sGUI)


While 1
   $hGUIMsg = GUIGetMsg()
   Switch $hGUIMsg
   Case $GUI_EVENT_CLOSE
          Exit
   Case $Button
          GUICtrlSetState($Button, $GUI_DISABLE)
          For $i = 1 To 100
                 _DrawLine(Random(0, $sGUI_H, 1), $i)
                Sleep(100)
          Next
   EndSwitch
WEnd


Func _DrawLine($Line_Y, $Value)
   GUICtrlCreateLabel("", $Line_X, 0, 1, $sGUI_H)                                ;垂直刻度
          GUICtrlSetBkColor(-1, 0x898989)
   GUICtrlCreateLabel("<" & $Value, $Line_X+1, $sGUI_H-16, 20, 16)                                ;垂直刻度
          GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
          GUICtrlSetColor(-1, 0xffffff)

   $Line_Y = $sGUI_H-$Line_Y                ;Y坐标上下翻转
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_PENSIZE, 1)                        ;画笔粗细
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_COLOR, 0xff0000)
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_LINE, $Line_X, $Line_Y)
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_REFRESH)

   $Line_X += $1Unit_W                ;下一线段X坐标向右移指定像素宽度

   If $Line_X >= $sGUI_W Then                ;如果 下一线段的 X坐标超过窗口宽度,则调整水平滚动条
          $sGUI_W += $sGUI_W2/2
          If Not $isWinMove_H Then
                 WinMove($sGUI, "", Default, Default, Default, $sGUI_H+18);, 200+50)                ;改变图表窗口高度,给滚动条增加空间
                 _GUIScrollBars_ShowScrollBar($sGUI, $SB_HORZ, True)                                                ;设置水平滚动条显示
                 $isWinMove_H = True
          EndIf
          _GUIScrollBars_SetScrollRange($sGUI, $SB_HORZ, 0, $sGUI_W*0.145)                                ;设置水平滚动条参数
          _GUIScrollBars_SetScrollInfoPos($sGUI, $SB_HORZ, _GUIScrollBars_GetScrollInfoMax($sGUI, $SB_HORZ))                ;滚动条移动到最右端
   EndIf
EndFunc

Func WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $lParam
    Local $iScrollCode = BitAND($wParam, 0x0000FFFF)

    Local $iIndex = -1, $iCharX, $iPosX
    Local $iMin, $iMax, $iPage, $iPos, $iTrackPos

    For $x = 0 To UBound($__g_aSB_WindowInfo) - 1
        If $__g_aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $iCharX = $__g_aSB_WindowInfo[$iIndex][2]
            ExitLoop
        EndIf
    Next
    If $iIndex = -1 Then Return 0

    ; ; 獲取所有的水平滾動條信息
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $iMin = DllStructGetData($tSCROLLINFO, "nMin")
    $iMax = DllStructGetData($tSCROLLINFO, "nMax")
    $iPage = DllStructGetData($tSCROLLINFO, "nPage")
    ; 保存位置以后進行比較
    $iPosX = DllStructGetData($tSCROLLINFO, "nPos")
    $iPos = $iPosX
    $iTrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    #forceref $iMin, $iMax
    Switch $iScrollCode

        Case $SB_LINELEFT ; 用戶點擊向左箭頭
            DllStructSetData($tSCROLLINFO, "nPos", $iPos - 1)

        Case $SB_LINERIGHT ; 用戶點擊向右箭頭
            DllStructSetData($tSCROLLINFO, "nPos", $iPos + 1)

        Case $SB_PAGELEFT ; 用戶單擊滾動條軸左側
            DllStructSetData($tSCROLLINFO, "nPos", $iPos - $iPage)

        Case $SB_PAGERIGHT ; 用戶單擊滾動條軸右側
            DllStructSetData($tSCROLLINFO, "nPos", $iPos + $iPage)

        Case $SB_THUMBTRACK ; 用戶拖動滾動條
            DllStructSetData($tSCROLLINFO, "nPos", $iTrackPos)
    EndSwitch

    ; // 設置的位置,然后檢索它,
    ; //   因 Windows 的原因,設定值可能不相同.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    ;// 如果位置發生了變化, 則滾動窗口并更新
    $iPos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($iPos <> $iPosX) Then _GUIScrollBars_ScrollWindow($hWnd, $iCharX * ($iPosX - $iPos), 0)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HSCROLL

本帖子中包含更多资源

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

×
发表于 2015-4-26 15:33:28 | 显示全部楼层
没发现按钮位置移动了 , 还在原位.....

本帖子中包含更多资源

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

×
 楼主| 发表于 2015-4-26 16:04:48 | 显示全部楼层
回复 2# 131738


    有异常的是深色部分的子窗口。里面的竖线条X坐标不对,正常应该是每隔30像素画一条竖线。图片中可以看到60和61竖线之间隔了很远。
发表于 2015-4-26 16:25:18 | 显示全部楼层
没说明白啊.....
 楼主| 发表于 2015-4-26 17:09:08 | 显示全部楼层
本帖最后由 yhxhappy 于 2015-4-27 09:31 编辑


回复 4# 131738


可以看到两张图深色窗口中的竖线不一样。

左图是将滚动条始终靠右后的效果,右图是注释了第85行后的效果。
我画竖线的时候,是每隔30像素画一条,左图中30~31竖线之间明显隔了有几百像素。
图2中的竖线分布才是正常的,但是注释第86行后,它的滚动条是不动的。我想曲线往前延伸的时候,滚动条也始终拉到最右端

我修改了1楼的脚本,增加了延时,效果更明显

本帖子中包含更多资源

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

×
发表于 2015-4-26 20:04:23 | 显示全部楼层
回复 5# yhxhappy

明白...帮不了你...等高手吧...
 楼主| 发表于 2015-4-27 10:06:50 | 显示全部楼层
本帖最后由 yhxhappy 于 2015-4-27 10:23 编辑

回复 6# 131738

我怀疑问题就在 _GUIScrollBars_SetScrollInfoPos 里 _GUIScrollBars_ScrollWindow() 上面。

它将客户区向右移动了一部分(假设移动了100),那窗口最左侧X坐标应该是100,而对于子窗口来说,最左侧X坐标还是0。
所以导致新画的控件向右移动了一截。但曲线为什么不受影响就很奇怪。

我也想过每加大一次滚动条,X坐标减掉加大部分,但实际操作起来有点复杂。
 楼主| 发表于 2015-4-27 10:39:10 | 显示全部楼层
本帖最后由 yhxhappy 于 2015-4-27 17:23 编辑

打开 GuiScrollBars.au3 查看了 _GUIScrollBars_SetScrollInfoPos

尝试修改了下竟然成功了,见115行。
#include <GUIConstantsEx.au3>
#include <GuiScrollBars.au3>
#include <StructureConstants.au3>
#include <WindowsConstants.au3>

$GUI = GUICreate("滾動條 UDF 示例", 660, 450, -1, -1)

$Button = GUICtrlCreateButton("开始画线", 100, 20, 100, 30)


Global $sGUI_W = 600, $sGUI_H = 300, $sGUI_W2 = $sGUI_W
Global $sGUI_X = 24, $sGUI_Y = 100
Global $Line_X = 0        ;        曲线起始X坐标,每画一截加 $1Unit_W
Global $oLine_X = 0                        ;竖线的X坐标
Global $1Unit_W = 30        ;每一截的宽度
Global $isWinMove_H = False                ;False表示子窗口未加高过,否则加高18,用于显示水平滚动条

Local $aY = $sGUI_Y
For $i = 100 To 0 Step -10                                                                                        ;画刻度线
   GUICtrlCreateLabel("", $sGUI_X+1, $aY, 9999999, 1)
          GUICtrlSetBkColor(-1, 0xfff100)
   GUICtrlCreateLabel($i & "-", 0, $aY-5, 24, 15, 0x0002)
          GUICtrlSetFont(-1, 8)
          GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
   $aY += $sGUI_H/100*10
Next


;===曲线子窗口===============================================================================
Global $sGUI = GUICreate("", $sGUI_W, $sGUI_H, $sGUI_X, $sGUI_Y, $WS_CHILD+$WS_BORDER, "", $GUI)
   GUISetBkColor(0x88AABB)

Global $LineGraphic = GUICtrlCreateGraphic(0, 0, 1, 1)
          GUICtrlSetState(-1, $GUI_DISABLE)
Global $LineNum = 0
GUICtrlSetGraphic($LineGraphic, $GUI_GR_MOVE, $Line_X, $sGUI_H)                        ;将曲线起始点定于左下角。

_GUIScrollBars_Init($sGUI, 999999999999999999999999)                                                        ;先将窗口滚动条初始化到一个很大的值
_GUIScrollBars_ShowScrollBar($sGUI, $SB_VERT, False)                                                ;设置垂直滚动条隐藏
_GUIScrollBars_ShowScrollBar($sGUI, $SB_HORZ, False)                                                ;设置水平滚动条隐藏
GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")
;======================================================

GUISetState(@SW_SHOW, $GUI)
GUISetState(@SW_SHOW, $sGUI)


While 1
   $hGUIMsg = GUIGetMsg()
   Switch $hGUIMsg
   Case $GUI_EVENT_CLOSE
          Exit
   Case $Button
          GUICtrlSetState($Button, $GUI_DISABLE)
          For $i = 1 To 100
                 _DrawLine(Random(0, $sGUI_H, 1), $i)
                Sleep(100)
          Next
   EndSwitch
WEnd


Func _DrawLine($Line_Y, $Value)
   GUICtrlCreateLabel("", $oLine_X, 0, 1, $sGUI_H)                                ;垂直刻度
          GUICtrlSetBkColor(-1, 0x898989)
   GUICtrlCreateLabel("<" & $Value, $oLine_X+1, $sGUI_H-16, 20, 16)                                ;垂直刻度
          GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
          GUICtrlSetColor(-1, 0xffffff)

   $Line_Y = $sGUI_H-$Line_Y                ;Y坐标上下翻转
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_PENSIZE, 1)                        ;画笔粗细
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_COLOR, 0xff0000)
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_LINE, $Line_X, $Line_Y)
   GUICtrlSetGraphic($LineGraphic, $GUI_GR_REFRESH)

   $Line_X += $1Unit_W                ;下一线段X坐标向右移指定像素宽度
   $oLine_X += $1Unit_W
   If $Line_X >= $sGUI_W Then                ;如果 下一线段的 X坐标超过窗口宽度,则调整水平滚动条
          $sGUI_W += $sGUI_W2/2
          If Not $isWinMove_H Then
                        WinMove($sGUI, "", Default, Default, Default, $sGUI_H+18);, 200+50)                ;改变图表窗口高度,给滚动条增加空间
                 _GUIScrollBars_ShowScrollBar($sGUI, $SB_HORZ, True)                                                ;设置水平滚动条显示
                        $isWinMove_H = True
                 EndIf
                 _GUIScrollBars_SetScrollRange($sGUI, $SB_HORZ, 0, $sGUI_W*0.145)                                ;设置水平滚动条参数
                 _MyGUIScrollBars_SetScrollInfoPos($sGUI, $SB_HORZ, _GUIScrollBars_GetScrollInfoMax($sGUI, $SB_HORZ))                ;滚动条移动到最右端
   EndIf
EndFunc

Func _MyGUIScrollBars_SetScrollInfoPos($hWnd, $iBar, $iPos)                        ;取自 GuiScrollBars.au3,只增加一行
        Local $iIndex = -1, $iYAmount, $iXAmount

        For $x = 0 To UBound($__g_aSB_WindowInfo) - 1
                If $__g_aSB_WindowInfo[$x][0] = $hWnd Then
                        $iIndex = $x
                        $iXAmount = $__g_aSB_WindowInfo[$iIndex][2]
                        $iYAmount = $__g_aSB_WindowInfo[$iIndex][3]
                        ExitLoop
                EndIf
        Next
        If $iIndex = -1 Then Return 0

        ; Save the position for comparison later on
        Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $iBar)
        Local $iPosXY = DllStructGetData($tSCROLLINFO, "nPos")

        DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
        DllStructSetData($tSCROLLINFO, "nPos", $iPos)
        _GUIScrollBars_SetScrollInfo($hWnd, $iBar, $tSCROLLINFO)
        _GUIScrollBars_GetScrollInfo($hWnd, $iBar, $tSCROLLINFO)
        ;// If the position has changed, scroll the window and update it
        $iPos = DllStructGetData($tSCROLLINFO, "nPos")
        If $iBar = $SB_HORZ Then
                If ($iPos <> $iPosXY) Then _GUIScrollBars_ScrollWindow($hWnd, $iXAmount * ($iPosXY - $iPos), 0)
                 $oLine_X += $iXAmount * ($iPosXY - $iPos)                                                                                                                                        ;每移动一次窗口客户区,X坐标减去加的部分
        Else
                If ($iPos <> $iPosXY) Then _GUIScrollBars_ScrollWindow($hWnd, 0, $iYAmount * ($iPosXY - $iPos))

   EndIf
EndFunc   ;==>_GUIScrollBars_SetScrollInfoPos


Func WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $lParam
    Local $iScrollCode = BitAND($wParam, 0x0000FFFF)

    Local $iIndex = -1, $iCharX, $iPosX
    Local $iMin, $iMax, $iPage, $iPos, $iTrackPos

    For $x = 0 To UBound($__g_aSB_WindowInfo) - 1
        If $__g_aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $iCharX = $__g_aSB_WindowInfo[$iIndex][2]
            ExitLoop
        EndIf
    Next
    If $iIndex = -1 Then Return 0

    ; ; 獲取所有的水平滾動條信息
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $iMin = DllStructGetData($tSCROLLINFO, "nMin")
    $iMax = DllStructGetData($tSCROLLINFO, "nMax")
    $iPage = DllStructGetData($tSCROLLINFO, "nPage")
    ; 保存位置以后進行比較
    $iPosX = DllStructGetData($tSCROLLINFO, "nPos")
    $iPos = $iPosX
    $iTrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    #forceref $iMin, $iMax
    Switch $iScrollCode

        Case $SB_LINELEFT ; 用戶點擊向左箭頭
            DllStructSetData($tSCROLLINFO, "nPos", $iPos - 1)

        Case $SB_LINERIGHT ; 用戶點擊向右箭頭
            DllStructSetData($tSCROLLINFO, "nPos", $iPos + 1)

        Case $SB_PAGELEFT ; 用戶單擊滾動條軸左側
            DllStructSetData($tSCROLLINFO, "nPos", $iPos - $iPage)

        Case $SB_PAGERIGHT ; 用戶單擊滾動條軸右側
            DllStructSetData($tSCROLLINFO, "nPos", $iPos + $iPage)

        Case $SB_THUMBTRACK ; 用戶拖動滾動條
            DllStructSetData($tSCROLLINFO, "nPos", $iTrackPos)
    EndSwitch

    ; // 設置的位置,然后檢索它,
    ; //   因 Windows 的原因,設定值可能不相同.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    ;// 如果位置發生了變化, 則滾動窗口并更新
    $iPos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($iPos <> $iPosX) Then _GUIScrollBars_ScrollWindow($hWnd, $iCharX * ($iPosX - $iPos), 0)
   ;MsgBox(0,$sGUI_W2/2,$iCharX * ($iPosX - $iPos))
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HSCROLL
发表于 2015-4-27 12:14:16 | 显示全部楼层
本帖最后由 131738 于 2015-4-27 12:25 编辑

回复 8# yhxhappy

奇怪你为何用汉化的繁体示例脚本...
 楼主| 发表于 2015-4-27 17:22:26 | 显示全部楼层
回复 9# 131738


我一直用 v3.3.10.0 简体版本帮助文档,后来升级到 3.3.12后发现好多UDF名称变了。
就又下了 AutoIt 繁体 3.3.13.19 第 2 版.chm (Build 2014.12.17)

两个版本帮助文档都在使用,还是简体版本最顺手,排版、字体等各方面。

在此要感谢您老付出的辛苦劳动。
发表于 2015-4-27 19:38:26 | 显示全部楼层
回复 10# yhxhappy

3.3.12.0个简体帮助在 Au.Cc 有免费下载的....
发表于 2015-4-27 22:44:39 | 显示全部楼层
类似示波器吗,有代码
 楼主| 发表于 2015-4-28 09:44:59 | 显示全部楼层
回复 12# netegg


    不是示波器,我写的是记录电池电量并生成曲线。
发表于 2015-4-28 09:59:11 | 显示全部楼层
回复 13# yhxhappy
这个我知道
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-5-2 18:24 , Processed in 0.086387 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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