(已解决) 设置水平滚动条滑块位置导致后添加控件位置与预期不符
本帖最后由 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] = $hWnd Then
$iIndex = $x
$iCharX = $__g_aSB_WindowInfo[$iIndex]
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
没发现按钮位置移动了 , 还在原位.....
回复 2# 131738
有异常的是深色部分的子窗口。里面的竖线条X坐标不对,正常应该是每隔30像素画一条竖线。图片中可以看到60和61竖线之间隔了很远。 没说明白啊..... 本帖最后由 yhxhappy 于 2015-4-27 09:31 编辑
回复 4# 131738
可以看到两张图深色窗口中的竖线不一样。
左图是将滚动条始终靠右后的效果,右图是注释了第85行后的效果。
我画竖线的时候,是每隔30像素画一条,左图中30~31竖线之间明显隔了有几百像素。
图2中的竖线分布才是正常的,但是注释第86行后,它的滚动条是不动的。我想曲线往前延伸的时候,滚动条也始终拉到最右端
我修改了1楼的脚本,增加了延时,效果更明显 回复 5# yhxhappy
明白...帮不了你...等高手吧... 本帖最后由 yhxhappy 于 2015-4-27 10:23 编辑
回复 6# 131738
我怀疑问题就在 _GUIScrollBars_SetScrollInfoPos 里 _GUIScrollBars_ScrollWindow() 上面。
它将客户区向右移动了一部分(假设移动了100),那窗口最左侧X坐标应该是100,而对于子窗口来说,最左侧X坐标还是0。
所以导致新画的控件向右移动了一截。但曲线为什么不受影响就很奇怪。
我也想过每加大一次滚动条,X坐标减掉加大部分,但实际操作起来有点复杂。 本帖最后由 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] = $hWnd Then
$iIndex = $x
$iXAmount = $__g_aSB_WindowInfo[$iIndex]
$iYAmount = $__g_aSB_WindowInfo[$iIndex]
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] = $hWnd Then
$iIndex = $x
$iCharX = $__g_aSB_WindowInfo[$iIndex]
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 本帖最后由 131738 于 2015-4-27 12:25 编辑
回复 8# yhxhappy
奇怪你为何用汉化的繁体示例脚本... 回复 9# 131738
我一直用 v3.3.10.0 简体版本帮助文档,后来升级到 3.3.12后发现好多UDF名称变了。
就又下了 AutoIt 繁体 3.3.13.19 第 2 版.chm (Build 2014.12.17)
两个版本帮助文档都在使用,还是简体版本最顺手,排版、字体等各方面。
在此要感谢您老付出的辛苦劳动。 回复 10# yhxhappy
3.3.12.0个简体帮助在 Au.Cc 有免费下载的.... 类似示波器吗,有代码 回复 12# netegg
不是示波器,我写的是记录电池电量并生成曲线。 回复 13# yhxhappy
这个我知道
页:
[1]