kk_lee69 发表于 2018-4-1 23:28:01

关于listview虚表直接读取数据库的方法,求助修改范例成MSSQL的!!

本帖最后由 kk_lee69 于 2018-4-1 23:48 编辑

关于listview虚表直接读取数据库的方法,求助修改范例成SQL的!!

官网有个范例 是listview虚表 直接拿SQLlite 的数据库 当作 listview虚表的数据 直接使用,这样的好处是 即使你的数据再多 也是分次 读取 就不会卡了
无奈 小弟 对于 SQLLITE的 UDF 实在没辙,我研究了半天 总是搞不懂原理
无法改成 把SQL DB 当作数据库来源的方法 ,所以上来求助

listview虚表 我已经很熟了所以理论上不应该是我不会使用,只是以前的方法都是读进
数组然后 利用数组 当作listview虚表 的数据源

只是最近遇到了 数据太多 读进数组太慢想要改成 分次读取 分次秀出的方法

所以才把脑筋动到了 数据库上……

以下是 范例程序 与 数据库麻烦 高手帮我改个范例

資料庫檔案如下:



或者 也可以利用 下面的檔案 建立資料庫





範例程式如下:

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <SQLite.au3>

Opt( "MustDeclareVars", 1 )

Global Const $tagNMLVCACHEHINT = $tagNMHDR & ";int iFrom;int iTo"

Global $hLV

Example()


Func Example()
        _SQLite_Startup()

        ; Check databases
        Local $iRows1 = CheckDB( "Test1.db" )
        Local $iRows2 = CheckDB( "Test2.db" )
        Local $iRows3 = CheckDB( "Test3.db" )
        Local $iRows

        ; Create GUI
        GUICreate( "Virtual ListViews", 850, 400 )

        ; Create Tab
        Local $idTab = GUICtrlCreateTab( 10, 10, 850-20, 400-20 )
        GUICtrlCreateTabItem( "Test1.db: " & Format( $iRows1 ) & " rows" )
        GUICtrlCreateTabItem( "Test2.db: " & Format( $iRows2 ) & " rows" )
        GUICtrlCreateTabItem( "Test3.db: " & Format( $iRows3 ) & " rows" )
        GUICtrlCreateTabItem( "" )

        ; Create ListView
        Local $idLV = GUICtrlCreateListView( "", 20, 40, 850-40, 400-60, $LVS_OWNERDATA, BitOR( $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT ) )
        $hLV = GUICtrlGetHandle( $idLV ) ;                               Virtual listview                        Reduces flicker
        For $i = 0 To 9
                _GUICtrlListView_AddColumn( $hLV, "Col" & $i, 75 )
        Next

        GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
        GUISetState( @SW_SHOW )

        ; Data for first tab
        $iRows = $iRows1
        If $iRows Then _SQLite_Open( "Test1.db" )
        GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iRows, 0 )

        ; Message loop
        While 1
                Switch GUIGetMsg()
                        Case $idTab
                                If $iRows Then _SQLite_Close( -1 )
                                Switch GUICtrlRead( $idTab )
                                        Case 0
                                                $iRows = $iRows1
                                                If $iRows Then _SQLite_Open( "Test1.db" )
                                        Case 1
                                                $iRows = $iRows2
                                                If $iRows Then _SQLite_Open( "Test2.db" )
                                        Case 2
                                                $iRows = $iRows3
                                                If $iRows Then _SQLite_Open( "Test3.db" )
                                EndSwitch
                                GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iRows, 0 )

                        Case $GUI_EVENT_CLOSE
                                ExitLoop
                EndSwitch
        WEnd

        If $iRows Then _SQLite_Close( -1 )
        _SQLite_Shutdown()
        GUIDelete()
EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )
        Local Static $tText = DllStructCreate( "wchar" )
        Local Static $pText = DllStructGetPtr( $tText )
        Local Static $aResult, $iRows, $iFrom

        Local $tNMHDR, $hWndFrom, $iCode
        $tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
        $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
        $iCode = DllStructGetData( $tNMHDR, "Code" )

        Switch $hWndFrom

                Case $hLV

                        Switch $iCode

                                Case $LVN_GETDISPINFOW
                                        Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam )
                                        If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then
                                                Local $iIndex = DllStructGetData( $tNMLVDISPINFO, "Item" ) - $iFrom + 1
                                                If $iIndex > 0 And $iIndex < $iRows + 1 Then
                                                        Local $sItem = $aResult[$iIndex]
                                                        DllStructSetData( $tText, 1, $sItem )
                                                        DllStructSetData( $tNMLVDISPINFO, "Text", $pText )
                                                        DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) )
                                                EndIf
                                        EndIf

                                Case $LVN_ODCACHEHINT
                                        Local $tNMLVCACHEHINT = DllStructCreate( $tagNMLVCACHEHINT, $lParam ), $iColumns
                                        $iFrom = DllStructGetData( $tNMLVCACHEHINT, "iFrom" )
                                        Local $sSQL = "SELECT * FROM lvdata WHERE item_id >= " & $iFrom & _
                                                " AND item_id <= " & DllStructGetData( $tNMLVCACHEHINT, "iTo" ) & ";"
                                        _SQLite_GetTable2d( -1, $sSQL, $aResult, $iRows, $iColumns )

                        EndSwitch

        EndSwitch

        Return $GUI_RUNDEFMSG
EndFunc

Func CheckDB( $sDBname )
        Local $aRow, $iRows = 0
        If FileExists( $sDBname ) Then
                _SQLite_Open( $sDBname )
                _SQLite_QuerySingleRow( -1, "SELECT max(item_id) FROM lvdata;", $aRow )
                _SQLite_Close( -1 )
        EndIf
        If IsArray( $aRow ) Then _
                $iRows = $aRow + 1
        Return $iRows
EndFunc

Func Format( $iInt )
        Return StringRegExpReplace( $iInt, "(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))", "\1," )
EndFunc

chzj589 发表于 2018-4-3 13:05:46

回复 1# kk_lee69



aryce 发表于 2018-4-3 16:14:33

最近一直用MYsql ,感觉很方便 。mssql还不会

kk_lee69 发表于 2018-4-7 17:06:47

既然這題 沒辦法改成 MSSQL那有沒有人 可以 改變一下 不要一次取的一筆資料我希望一次可以讀取一 百筆資料當作緩衝呢???

kk_lee69 发表于 2018-4-7 17:32:32

回复 2# chzj589

就用SQL LISTE 好了 能否將範例中 每次讀取一筆到兩筆的緩衝   改成每次讀取100筆嗎??

chzj589 发表于 2018-4-7 17:41:23

回复 5# kk_lee69
你有看一下 CreateDB.au3吗?
範例程式,是读取三个数据库

Local $iRows1 = CheckDB( "Test1.db" )
Local $iRows2 = CheckDB( "Test2.db" )
Local $iRows3 = CheckDB( "Test3.db" )

数据库里有几笔,就读几笔,不是吗?

kk_lee69 发表于 2018-4-7 17:55:54

回复 6# chzj589

當然數據庫有幾筆 就讀取幾筆

但是這個虛擬表的概念是先決定資料庫有 幾筆假設有1萬筆 就先設定 有一萬筆資 料

然後第一次 讀取 0-15 資料往後 你往下滑一格它就往後讀取資料庫裡面的下一筆資料

一次只讀取一筆然後 你往上了 捲動了 就從資料庫裡 再往前 讀取 一筆 資料


我不要一次 只讀取一筆資料這樣對資料庫來說重複的讀取 負擔太重
我希望一次 可以讀取 100筆資料

chzj589 发表于 2018-4-7 18:27:07

回复 7# kk_lee69
哪个範例程式?

kk_lee69 发表于 2018-4-7 19:42:10

回复 8# chzj589

就是上面的範例程式

chzj589 发表于 2018-4-7 20:24:23

回复 9# kk_lee69
不理解。
上面的範例程式历,不就是读取三个数据库?
我没安装SQL LISTE数据库编辑器,不知道建立的"Test1.db"是什么结构。

kk_lee69 发表于 2018-4-7 20:43:02

回复 10# chzj589

你沒有實際跑資料庫....你下載 資料庫3 就好跟我的範例程式放在一起

執行後切換到 第三個 TAB你就會知道

chzj589 发表于 2018-4-7 21:27:32

回复 11# kk_lee69
还是不理解,有什么不同

kk_lee69 发表于 2018-4-7 21:44:59

本帖最后由 kk_lee69 于 2018-4-7 21:48 编辑

回复 12# chzj589

你有注意到
WM_NOTIFY 裡面的$LVN_ODCACHEHINT 這個變化嗎??

你在 $LVN_ODCACHEHINT 下面 加上

ConsoleWrite($iFrom&" "&DllStructGetData( $tNMLVCACHEHINT, "iTo" )&@CRLF)

你就會看到一開始是
015
15 16
16 17
17 18



你每按往下它就會從資料庫裡面抓一筆資料出來
所以上面的程式 才能做到資料庫裡面幾十萬筆資料但是都不會卡頓
因為它一次只抓一筆資料

chzj589 发表于 2018-4-8 09:34:24

回复 13# kk_lee69
主要控制是这里:
                                Case $LVN_ODCACHEHINT
                                        Local $tNMLVCACHEHINT = DllStructCreate($tagNMLVCACHEHINT, $lParam), $iColumns
                                        $iFrom = DllStructGetData($tNMLVCACHEHINT, "iFrom")
                                        Local $sSQL = "SELECT * FROM lvdata WHERE item_id >= " & $iFrom & _
                                                        " AND item_id <= " & DllStructGetData($tNMLVCACHEHINT, "iTo") & ";"
                                        GUICtrlSendMsg($hLV, $LVM_DELETEALLITEMS, 0, 0)
                                        _SQLite_GetTable2d(-1, $sSQL, $aResult, $iRows, $iColumns)
                                        Local $iFromg = ConsoleWrite($iFrom & " " & DllStructGetData($tNMLVCACHEHINT, "iTo") & @CRLF)
;------------------------------------------------
_SQLite_GetTable2d
传递包含执行查询的列名和数据的 2 维数组.

#include <SQLite.au3>
_SQLite_GetTable2d ( $hDB, $sSQL, ByRef $aResult, ByRef $iRows, ByRef $iColumns [, $iCharSize = -1 [, $bSwichDimensions = False]] )

参 数
$hDB 打开的数据库, 如为 -1, 则使用最后打开的数据库
$sSQL 要执行的 SQL 语句
$aResult 传递的结果
$iRows 传递的数据行数
$iColumns 传递的列数
$iCharSize [可选] 指定数据字段的最大尺寸
$bSwichDimensions [可选] 切换 $aResult 尺寸

chzj589 发表于 2018-4-8 10:03:36

回复 14# chzj589
我的理解是本来己经全部读取,只是控制显示条目而己。
不知对不?
页: [1] 2 3
查看完整版本: 关于listview虚表直接读取数据库的方法,求助修改范例成MSSQL的!!