線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2197
推到 Plurk!
推到 Facebook!

請問如何讓兩個ListView的Scrollbar作同步化

尚未結案
u8702656
一般會員


發表:2
回覆:5
積分:1
註冊:2003-07-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-06-21 14:40:47 IP:211.23.xxx.xxx 未訂閱
請教各位前輩 小弟目前在作資料夾中所有檔案的synchronization功能,因此必須使用兩個ListView用vsReport的ViewStyle作比對的列表,讓user方便對照 因為ListView中的ScrollBar為動態產生的所以沒有OnScroll這個Event,所以我是把Scroll的動作寫在OnCustomDrawItem中,並且在程式中判斷滑鼠所在的位置決定由哪一個ListView的OnCustomDrawItem事件來更新Scrollbar的位置, 但是這會造成當我再拖拉時滑鼠不在原本按下的那個ListView時,無法執行更新動作,以下是我的程式碼.. //--------------------------------------------------------------------------- void __fastcall TForm4::ListView2CustomDrawItem(TCustomListView *Sender,TListItem *Item, TCustomDrawState State, bool &DefaultDraw) {      RECT r;     ::GetWindowRect(ListView2->Handle,&r);     //取得滑鼠位置     POINT pd;     GetCursorPos(&pd);     if(::PtInRect(&r,pd))     {     SCROLLINFO scroll;  //宣告(ScrollBar)結構     memset(&scroll,0,sizeof(SCROLLINFO));//結構初始化     scroll.fMask = SIF_ALL; //取得ScrollBar全部資料的旗標     scroll.cbSize = sizeof(SCROLLINFO); //配置足夠記憶體     if(GetScrollInfo(ListView3->Handle,SB_VERT,&scroll))//取得垂直                                                       //ScrollBar的資訊     //返回值如果是真的將得到以下各種資訊,否則代表ScrollBar沒有出現     {         if(ListView2->TopItem->Index > ListView3->TopItem->Index)         {             //令垂直ScrollBar向下翻頁     //SB_LINEUP             for(int i = ListView3->TopItem->Index;iTopItem->Index;i ) SendMessage(ListView3->Handle,WM_VSCROLL,SB_LINEDOWN,0); } else if(ListView2->TopItem->Index < ListView3->TopItem->Index) { int LV4 = ListView3->TopItem->Index; for(int i = ListView2->TopItem->Index;iHandle,WM_VSCROLL,SB_LINEUP,0); } } } } //--------------------------------------------------------------------------- void __fastcall TForm4::ListView3CustomDrawItem(TCustomListView *Sender, TListItem *Item, TCustomDrawState State, bool &DefaultDraw) { RECT r; ::GetWindowRect(ListView3->Handle,&r); //取得滑鼠位置 POINT pd; GetCursorPos(&pd); //pd = ScreenToClient(pd); //轉換 為Client視窗上的座標 //由滑鼠位置而取得Form1上物件handle //HWND h = ChildWindowFromPoint(Handle, pd); //if(::PtInRect(&r,pd)) if(ISListView3) { //ListView4->TopItem = ViewOrigin; SCROLLINFO scroll; //宣告(ScrollBar)結構 memset(&scroll,0,sizeof(SCROLLINFO));//結構初始化 scroll.fMask = SIF_ALL; //取得ScrollBar全部資料的旗標 scroll.cbSize = sizeof(SCROLLINFO); //配置足夠記憶體 if(GetScrollInfo(ListView2->Handle,SB_VERT,&scroll))//取得垂直ScrollBar的資訊 //返回值如果是真的將得到以下各種資訊,否則代表ScrollBar沒有出現 { if(ListView3->TopItem->Index > ListView2->TopItem->Index) { //令垂直ScrollBar向下翻頁 //SB_LINEUP for(int i = ListView2->TopItem->Index;iTopItem->Index;i ) SendMessage(ListView2->Handle,WM_VSCROLL,SB_LINEDOWN,0); } else if(ListView3->TopItem->Index < ListView2->TopItem->Index) { int LV2 = ListView2->TopItem->Index; for(int i = ListView3->TopItem->Index;iHandle,WM_VSCROLL,SB_LINEUP,0); } } } } //------------------------------------------------------------------- 另外我也參考了之前一篇ScrollBar和Memo同步化的方法(http://delphi.ktop.com.tw/topic.php?topic_id=27548), 但是發現ListView對scPosition的message在拖拉時無法正確反應,點選上,下箭頭才會正確執行< > 是否可麻煩各位前輩位小弟解惑,不勝感激 < >
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-06-22 06:08:43 IP:211.76.xxx.xxx 未訂閱
u8702656你好:     以下的Code是我用的方式,在bcb6可以運作正常,不知道能否解決你的問題?     
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView2CustomDrawItem(TCustomListView *Sender,
      TListItem *Item, TCustomDrawState State, bool &DefaultDraw)
{
if(ListView2->VisibleRowCount > ListView2->Items->Count)
        return;
while(ListView2->TopItem->Index != ListView3->TopItem->Index)
        SendMessage(ListView3->Handle,
                    WM_VSCROLL,
                    (ListView2->TopItem->Index > ListView3->TopItem->Index)? SB_LINEDOWN:SB_LINEUP,
                    0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView3CustomDrawItem(TCustomListView *Sender,
      TListItem *Item, TCustomDrawState State, bool &DefaultDraw)
{
if(ListView3->VisibleRowCount > ListView3->Items->Count)
        return;
while(ListView2->TopItem->Index != ListView3->TopItem->Index)
        SendMessage(ListView2->Handle,
                    WM_VSCROLL,
                    (ListView3->TopItem->Index > ListView2->TopItem->Index)? SB_LINEDOWN:SB_LINEUP,
                    0);
}
//---------------------------------------------------------------------------
 
u8702656
一般會員


發表:2
回覆:5
積分:1
註冊:2003-07-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-06-23 10:05:12 IP:211.23.xxx.xxx 未訂閱
謝謝pwipwi前輩的幫忙 真的很抱歉先前沒有講清楚,誤導了大家 因為我要避開兩個ListView在OnCustomDrawItem時,互相SendMessage會造成畫面混亂的問題,必須再拖拉時只能由一方發訊息,所以我才用抓滑鼠位置的方式來作分辨,因此造成滑鼠未在ListView中會不work 所以我的問題應該是:如何再拖拉時正確分辨現在到底拖拉的是哪一個ListView 麻煩各位前輩再一次的指導
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-08-18 10:12:37 IP:61.63.xxx.xxx 未訂閱
引言: 謝謝pwipwi前輩的幫忙 真的很抱歉先前沒有講清楚,誤導了大家 因為我要避開兩個ListView在OnCustomDrawItem時,互相SendMessage會造成畫面混亂的問題,必須再拖拉時只能由一方發訊息,所以我才用抓滑鼠位置的方式來作分辨,因此造成滑鼠未在ListView中會不work 所以我的問題應該是:如何再拖拉時正確分辨現在到底拖拉的是哪一個ListView 麻煩各位前輩再一次的指導 < face="Verdana, Arial, Helvetica">
引言: 謝謝pwipwi前輩的幫忙 真的很抱歉先前沒有講清楚,誤導了大家 因為我要避開兩個ListView在OnCustomDrawItem時,互相SendMessage會造成畫面混亂的問題,必須再拖拉時只能由一方發訊息,所以我才用抓滑鼠位置的方式來作分辨,因此造成滑鼠未在ListView中會不work 所以我的問題應該是:如何再拖拉時正確分辨現在到底拖拉的是哪一個ListView 麻煩各位前輩再一次的指導 < face="Verdana, Arial, Helvetica"> u8702656你好< >: 你的問題讓我有點困惑< >!因為依照你這樣程式的設計方式是可以達成同步ok,但你的問題: 但是這會造成當我再拖拉時滑鼠不在原本按下的那個ListView時,無法執行更新動作 卻是你自已程式碼中劃地自限造成的不是嗎? 也就是你的這段程式碼: < class="code"> RECT r; ::GetWindowRect(ListView2->Handle,&r); //取得滑鼠位置 POINT pd; GetCursorPos(&pd); if(::PtInRect(&r,pd)) { ~~~ 並沒有意義,因為今天不管滑鼠在那裏,只有我確定ListView2(依你程式中變數名)是onfocus狀態時,我就可以確定在做滑鼠滾輪scroll動作時就是ListView2會接收到,也就是說滑鼠所控制的一定是目前正在onfocus中的那一個元件! 所以那一段程式碼那掉應該就可以滿足你的需求了! 簡單 class="code"> void __fastcall TForm1::ListView1CustomDrawItem(TCustomListView *Sender, TListItem *Item, TCustomDrawState State, bool &DefaultDraw) { if (!ListView1->Focused()) { <--因為ListView1不在onfocus狀態時也有可能會執行 return; 這個drawitem的事件,所以加此段判斷,如果不是 } onfocus的話,後面就不用再做下去了 SCROLLINFO scroll; memset(&scroll,0,sizeof(SCROLLINFO)); scroll.fMask = SIF_ALL; scroll.cbSize = sizeof(SCROLLINFO); if (GetScrollInfo(ListView2->Handle,SB_VERT,&scroll)) { if (ListView1->TopItem->Index>ListView2->TopItem->Index) { for(int i=ListView2->TopItem->Index;iTopItem->Index;i ) SendMessage(ListView2->Handle,WM_VSCROLL,SB_LINEDOWN,0); } else if (ListView1->TopItem->Index< ListView2->TopItem->Index) { int LV4=ListView2->TopItem->Index; for (int i=ListView1->TopItem->Index;iHandle,WM_VSCROLL,SB_LINEUP,0); } } } 簡單範例,是延用你的sample去修,只寫了一半! <>> >! >!
u8702656
一般會員


發表:2
回覆:5
積分:1
註冊:2003-07-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-08-23 10:48:50 IP:211.23.xxx.xxx 未訂閱
謝謝m8815010前輩提供的方法 可是小弟我去試了一下,發現滑鼠去點選 >
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-08-24 12:11:31 IP:210.244.xxx.xxx 未訂閱
引言: 謝謝m8815010前輩提供的方法 可是小弟我去試了一下,發現滑鼠去點選 > < face="Verdana, Arial, Helvetica"> u8702656颱風天好< >: 還是不太瞭解你的意思< >!愈看愈霧,呵呵! 首先你說:滑鼠點scroll bar,並不會讓ListView被set focus,只有點選ListView(非scroll bar)處,才可以讓它被focus,這是沒錯的,嗯 另外用滑鼠控制scroll bar有3種方式: 1.用左鍵點選scroll bar的長條,並一直壓者左鍵,同時拖拽長條,達成捲動 2.用滑鼠scroll bar的上、下箭頭 3.直接滾動滑鼠的滾輪 不知道你是怎麼操作,怎麼樣的問題,愈看愈不解,!
u8702656
一般會員


發表:2
回覆:5
積分:1
註冊:2003-07-10

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-09-01 10:59:34 IP:211.23.xxx.xxx 未訂閱
拍謝拍謝拖了這麼久才又上來. 對於這3種操作狀況 1.用左鍵點選scroll bar的長條,並一直壓者左鍵,同時拖拽長條,達成捲動 2.用滑鼠scroll bar的上、下箭頭 3.直接滾動滑鼠的滾輪    以一個例子來說明,比如說我有兩個ListView,分別為ListView1和ListView2,想做到ScrollBar同步; 則在原本的程式中,有這個問題,當我在操作狀況1時,拖拉ListView1的ScrollBar,在拖拉時只要我滑鼠的游標一超出ListView1元件的範圍,就會造成不同步; 而在操作狀況2時,因為滑鼠游標都會在LisView1中,所以不會有問題; 但在操作狀況3中,當Focus在ListView1時,滑鼠游標在ListView1時滾動滑鼠滾輪,一切正常,當滑鼠游標不在ListView1時,就無法做到同步了 以上這些其實也是因為程式中會去判斷滑鼠所在位置,如果不在其範圍內就不發送捲動訊息給另一個ListView的關係    而我會這樣寫的原因有三個 1.主要原因:ListView沒有提供OnScroll的Event,所以我將發送要求同步捲動的Message寫在CustomDrawItem的Event中 2.而CustomDrawItem這個Event是只要你有重繪ListView的動作都會觸發,因此必須加入判斷到底是捲動哪一個ListView的判斷,來避免重複發送Scroll訊息的狀況 3.要判斷現在的focus在哪一個ListView,本來以為只要用 ListView->Focused()來判斷,但是發現 "滑鼠點scroll bar,並不會讓ListView被set focus,只有點選ListView(非scroll bar)處,才可以讓它被focus"的這個問題 所以只好判斷滑鼠游標了;因此我只要找出: 如何在拖拉時正確分辨現在到底拖拉的是哪一個ListView就可以解決我的問題
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-09-03 14:32:12 IP:61.63.xxx.xxx 未訂閱
引言: 拍謝拍謝拖了這麼久才又上來. 對於這3種操作狀況 1.用左鍵點選scroll bar的長條,並一直壓者左鍵,同時拖拽長條,達成捲動 2.用滑鼠scroll bar的上、下箭頭 3.直接滾動滑鼠的滾輪 以一個例子來說明,比如說我有兩個ListView,分別為ListView1和ListView2,想做到ScrollBar同步; 則在原本的程式中,有這個問題,當我在操作狀況1時,拖拉ListView1的ScrollBar,在拖拉時只要我滑鼠的游標一超出ListView1元件的範圍,就會造成不同步; 而在操作狀況2時,因為滑鼠游標都會在LisView1中,所以不會有問題; 但在操作狀況3中,當Focus在ListView1時,滑鼠游標在ListView1時滾動滑鼠滾輪,一切正常,當滑鼠游標不在ListView1時,就無法做到同步了 以上這些其實也是因為程式中會去判斷滑鼠所在位置,如果不在其範圍內就不發送捲動訊息給另一個ListView的關係 而我會這樣寫的原因有三個 1.主要原因:ListView沒有提供OnScroll的Event,所以我將發送要求同步捲動的Message寫在CustomDrawItem的Event中 2.而CustomDrawItem這個Event是只要你有重繪ListView的動作都會觸發,因此必須加入判斷到底是捲動哪一個ListView的判斷,來避免重複發送Scroll訊息的狀況 3.要判斷現在的focus在哪一個ListView,本來以為只要用 ListView->Focused()來判斷,但是發現 "滑鼠點scroll bar,並不會讓ListView被set focus,只有點選ListView(非scroll bar)處,才可以讓它被focus"的這個問題 所以只好判斷滑鼠游標了;因此我只要找出: 如何在拖拉時正確分辨現在到底拖拉的是哪一個ListView就可以解決我的問題
u8702656你好: 你的例子中: < class="code"> 1.按滑鼠左鍵點選scroll bar的長條柱,拖拽使scroll bar捲動,你說只要滑鼠一離開Listview 的範圍,就會造成不同步: 這應該不是程式的問題,因為滑鼠離開Listview範圍的時候(左鍵還是一直按著哦),拖拽scroll bar的 長條柱是可以的,只是不太順,會感覺似有似無(這裡要細心感覺一下),這是os(或說builder)design 本身呈現,我們don't care。但是不管滑鼠在不在Listview的範圍上,只要你可以成功捲動Listvew1的 話,listview2就可以跟著動了(用我小修過的版本)! 2.ok 3.你說當滑鼠游標不在Listview1時,就無法同步 因為:1. 你原本的程式限制了,而在我的小修改掉這問題(如前述回應) 2. Listview1跟本沒被setfocus,所以它的scroll bar不會接收到滑鼠的動作,就不會 跟著動,所以Listview1就不會動,所以Listview2也不會跟動! conclusion:1.我還是覺得我前述小修過的程式碼應該可以滿足了 2.以寫在ondraw事件的同步方式,流程一定是死的: Listview1被focus-->才可以接受捲動指令(不管指令怎麼送來)-->被捲動 -->重繪item事件觸發-->送message給Listview2 3.即然問題還不能糎清,還是跳回你一開始想要的做法吧,就是抓scroll事件: 之前post的,精神上應該是一致的,就不劃蛇黏足再寫範例了: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=54792 愈來愈霧,希望有所幫助!
u8702656
一般會員


發表:2
回覆:5
積分:1
註冊:2003-07-10

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-09-20 09:47:11 IP:211.23.xxx.xxx 未訂閱
雖然還是沒有解決問題 不過還是要感謝版主的熱心指導 我想我在想辦法解決好了
系統時間:2024-03-29 9:48:44
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!