2015-09-28 6 views
5

मैं डेल्फी 6 का उपयोग कर रहा हूं और एक सूची दृश्य को सॉर्ट करने की कार्यक्षमता जोड़ना चाहता हूं, जैसे कि यह विंडोज एक्सप्लोरर में किया जाता है।सॉर्टिंग सूची तीर के साथ कॉलम देखें

एक पहला परीक्षण में, मैं (त्वरित & गंदा) में कुछ स्रोतों से कुछ स्रोत कोड की नकल की है, और किया कुछ छोटे समायोजन:

यह वही है मैं अब के लिए अब तक (केवल त्वरित & गंदा है):

uses 
    CommCtrls; 

var 
    Descending: Boolean; 
    SortedColumn: Integer; 

const 
    { For Windows >= XP } 
    {$EXTERNALSYM HDF_SORTUP} 
    HDF_SORTUP    = $0400; 
    {$EXTERNALSYM HDF_SORTDOWN} 
    HDF_SORTDOWN   = $0200; 

procedure ShowArrowOfListViewColumn(ListView1: TListView; ColumnIdx: integer; Descending: boolean); 
var 
    Header: HWND; 
    Item: THDItem; 
begin 
    Header := ListView_GetHeader(ListView1.Handle); 
    ZeroMemory(@Item, SizeOf(Item)); 
    Item.Mask := HDI_FORMAT; 
    Header_GetItem(Header, ColumnIdx, Item); 
    Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags 
    if Descending then 
    Item.fmt := Item.fmt or HDF_SORTDOWN 
    else 
    Item.fmt := Item.fmt or HDF_SORTUP;//include the sort ascending flag 
    Header_SetItem(Header, ColumnIdx, Item); 
end; 

procedure TUD2MainForm.ListView3Compare(Sender: TObject; Item1, 
    Item2: TListItem; Data: Integer; var Compare: Integer); 
begin 
    if SortedColumn = 0 then 
    Compare := CompareText(Item1.Caption, Item2.Caption) 
    else 
    Compare := CompareText(Item1.SubItems[SortedColumn-1], Item2.SubItems[SortedColumn-1]); 
    if Descending then Compare := -Compare; 
end; 

procedure TUD2MainForm.ListView3ColumnClick(Sender: TObject; 
    Column: TListColumn); 
begin 
    TListView(Sender).SortType := stNone; 
    if Column.Index<>SortedColumn then 
    begin 
    SortedColumn := Column.Index; 
    Descending := False; 
    end 
    else 
    Descending := not Descending; 
    ShowArrowOfListViewColumn(TListView(Sender), column.Index, Descending); 
    TListView(Sender).SortType := stText; 
end; 

कॉलम को ऊपर और नीचे क्रमबद्ध किया जा सकता है, लेकिन मैं तीरों को नहीं देख सकता।

this question के अनुसार, मेरा फ़ंक्शन ShowArrowOfListViewColumn() समस्या को हल करना चाहिए था।

क्या यह संभव है कि डेल्फी 6 इस सुविधा का समर्थन नहीं करता है, या मेरे कोड में कोई समस्या है? दूसरी तरफ, लिस्ट व्यू आईआईआरसी Windows control है, और इसलिए मैं उम्मीद करता हूं कि WinAPI तीर ग्राफिक्स प्रस्तुत करता है, न कि (बहुत पुराना) वीसीएल।

मैंने German website पर पढ़ा है कि तीर ग्राफिक्स को मैन्युअल रूप से जोड़ा जाना है, लेकिन उस वेबसाइट के समाधान में डेल्फी के CommCtrl.pas को बदलने की आवश्यकता है (कॉलम का आकार बदलते समय गड़बड़ की वजह से)। लेकिन मैं वास्तव में वीसीएल स्रोत को संशोधित करना नापसंद करता हूं, खासकर जब से मैं ओपनसोर्स विकसित करता हूं, और मैं नहीं चाहता कि अन्य डेवलपर्स अपने डेल्फी स्रोतों को बदल दें/दोबारा बदलें।

नोट है कि मैं अपने द्विआधारी करने के लिए एक XP प्रकट जोड़ नहीं था, इसलिए एप्लिकेशन Win9x तरह दिखता है।

+0

क्या आप comctl v6, यानी XP विषयों का उपयोग कर रहे हैं? इसके लिए माइक लिस्के के थीम मैनेजर की आवश्यकता है। –

+0

मैंने अपनी बाइनरी में एक एक्सपी मैनिफेस्ट नहीं जोड़ा, इसलिए ऐप Win9x जैसा दिखता है। –

उत्तर

3

HDF_SORTDOWN और HDF_SORTUP comctl32 v6 की आवश्यकता है। यह HDITEM के लिए दस्तावेज में कहा गया है:

HDF_SORTDOWN संस्करण 6.00 और बाद में। इस मद पर एक तीर-तीर खींचता है। यह आमतौर पर इंगित करने के लिए प्रयोग किया जाता है कि वर्तमान विंडो में जानकारी को इस कॉलम पर अवरोही क्रम में क्रमबद्ध किया गया है। इस ध्वज को HDF_IMAGE या HDF_BITMAP के साथ जोड़ा नहीं जा सकता है।

HDF_SORTUP संस्करण 6.00 और बाद में संस्करण। इस आइटम पर एक ऊपर तीर खींचता है। यह आम तौर पर इंगित करने के लिए प्रयोग किया जाता है कि वर्तमान विंडो में जानकारी आरोही क्रम में इस कॉलम पर क्रमबद्ध है। इस ध्वज को HDF_IMAGE या HDF_BITMAP के साथ जोड़ा नहीं जा सकता है।

जैसा कि आपने अपनी टिप्पणियों में बताया है, आपने comctl32 v6 मेनिफेस्ट को शामिल नहीं किया है। यह बताता है कि आप क्या देखते हैं।

समाधान में शामिल हैं:

  • comctl32 v6 प्रकट जोड़ा जा रहा है, या
  • कस्टम ड्राइंग हैडर तीर।
+0

हैलो, इस संकेत के लिए आपको बहुत बहुत धन्यवाद। मैं वास्तव में "विंडोज एक्सपी की आवश्यकता है" पढ़ता हूं, लेकिन मैं भूल गया कि विंडोज़ कॉमसीटीएल 32 के फॉलबैक संस्करण का उपयोग करेगा, अगर कोई मैनिफेस्ट प्रदान नहीं किया गया है। - मैं अभी भी इसके बारे में थोड़ा आश्चर्यचकित हूं, क्योंकि तीर विंडोज 95 के बाद मौजूद हैं। क्या माइक्रोसॉफ्ट ने इस सुविधा को विंडोज एक्सपी तक खुलासा किया था, या विंडोज 95 एक्सप्लोरर ने सूची दृश्य से अलग नियंत्रण का उपयोग किया था? –

+0

पूर्णता के लिए, मैंने एक वीसीएल बनाया है - जो प्रत्येक कॉलम आकार बदलने पर तीरों के साथ समस्या को हल करता है: http://www.viathinksoft.de/~daniel-marschall/code/delphi/vcl/VTSListView.pas। लेकिन मुझे डर है कि मैंने पहिया का फिर से आविष्कार किया है। –

+0

जीत 95 में प्रो एक्सप्लोरर ने एक अलग नियंत्रण का उपयोग किया, या कस्टम तीर खींचा –

-1
आप VCL स्रोत बदलने के लिए जर्मन उदाहरण का अनुसरण करने की जरूरत नहीं है

, तो आप सिर्फ कोड क्रम पैच कर सकते हैं।

डिस्कर मैं डेल्फी 6 पर अपना कोड परीक्षण करना चाहता था, लेकिन मेरी डेल्फी 6 स्थापना आज सुबह शुरू नहीं होगी, इसलिए यह केवल डेल्फी एक्सई पर परीक्षण किया जाता है!

लेकिन मुझे लगता है कि यह डेल्फी 6 पर भी काम करेगा।

सबसे पहले आप एक विधि क्रम पैच करने के लिए एक वर्ग की जरूरत है:

unit PatchU; 

interface 

type 
    pPatchEvent = ^TPatchEvent; 

    // "Asm" opcode hack to patch an existing routine 
    TPatchEvent = packed record 
    Jump: Byte; 
    Offset: Integer; 
    end; 

    TPatchMethod = class 
    private 
    PatchedMethod, OriginalMethod: TPatchEvent; 
    PatchPositionMethod: pPatchEvent; 
    public 
    constructor Create(const aSource, aDestination: Pointer); 
    destructor Destroy; override; 
    procedure Restore; 
    procedure Hook; 
    end; 

implementation 

uses 
    Windows, Sysutils; 

{ TPatchMethod } 

constructor TPatchMethod.Create(const aSource, aDestination: Pointer); 
var 
    OldProtect: Cardinal; 
begin 
    PatchPositionMethod := pPatchEvent(aSource); 
    OriginalMethod := PatchPositionMethod^; 
    PatchedMethod.Jump := $E9; 
    PatchedMethod.Offset := PByte(aDestination) - PByte(PatchPositionMethod) - SizeOf(TPatchEvent); 

    if not VirtualProtect(PatchPositionMethod, SizeOf(TPatchEvent), PAGE_EXECUTE_READWRITE, OldProtect) then 
    RaiseLastOSError; 

    Hook; 
end; 

destructor TPatchMethod.Destroy; 
begin 
    Restore; 
    inherited; 
end; 

procedure TPatchMethod.Hook; 
begin 
    PatchPositionMethod^ := PatchedMethod; 
end; 

procedure TPatchMethod.Restore; 
begin 
    PatchPositionMethod^ := OriginalMethod; 
end; 

end. 

तो हम इसका इस्तेमाल करने की जरूरत है। पऊ एक रूप पर सूचीदृश्य एक तो यह कोड:

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, ComCtrls, PatchU; 

type 
    TListView = class(ComCtrls.TListView) 
    protected 
    procedure ColClick(Column: TListColumn); override; 
    end; 

    TForm1 = class(TForm) 
    ListView1: TListView; 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

uses 
    CommCtrl; 

var 
    ListView_UpdateColumn_Patch: TPatchMethod; 

type 
    THooked_ListView = class(TListView) 
    procedure HookedUpdateColumn(AnIndex: Integer); 
    end; 

    { TListView } 

procedure TListView.ColClick(Column: TListColumn); 
var 
    Header: HWND; 
    Item: THDItem; 
    NewFlag: DWORD; 
begin 
    Header := ListView_GetHeader(Handle); 
    ZeroMemory(@Item, SizeOf(Item)); 
    Item.Mask := HDI_FORMAT; 
    Header_GetItem(Header, Column.Index, Item); 

    if Item.fmt and HDF_SORTDOWN <> 0 then 
    NewFlag := HDF_SORTUP 
    else 
    NewFlag := HDF_SORTDOWN; 

    Item.fmt := Item.fmt and not(HDF_SORTUP or HDF_SORTDOWN); // remove both flags 
    Item.fmt := Item.fmt or NewFlag; 
    Header_SetItem(Header, Column.Index, Item); 

    inherited; 
end; 

{ THooked_ListView } 

procedure THooked_ListView.HookedUpdateColumn(AnIndex: Integer); 
begin 
    ListView_UpdateColumn_Patch.Restore; 
    try 
    UpdateColumn(AnIndex); 
    finally 
    ListView_UpdateColumn_Patch.Hook; 
    end; 
end; 

initialization 

ListView_UpdateColumn_Patch := TPatchMethod.Create(@TListView.UpdateColumn, @THooked_ListView.HookedUpdateColumn); 

finalization 

ListView_UpdateColumn_Patch.Free; 

end. 

जैसा कि आप देख फिर मेरे डेमो मैं heavly कोड आप प्रकाशित से प्रेरित है। मैंने सिर्फ वैश्विक युद्ध हटा दिए हैं। मेरे उदाहरण में मैं मूल प्रक्रिया बुला लेकिन कुछ भी नहीं है, लेकिन आप ofcause Geraman उदाहरण से कोड फोन करना होगा।

तो मूल रूप से मैं आपको यह दिखाना चाहता था कि आप मूल स्रोत कोड को संपादित करने के साथ वीसीएल कैसे बदल सकते हैं। यह आपको जाना चाहिए।

+2

आपको इस तरह हैक करने की आवश्यकता नहीं है। आप यहां अपने उत्तर में किसी भी ग़लत हैक के बिना मेरे उत्तर से कोड का उपयोग कर सकते हैं। –

+0

यह यह TListView = वर्ग (ComCtrls.TListView) भाग या पैच भाग है जिसे आप एक बुरा हैक कहते हैं? –

+1

चक्कर लगाने की जरूरत नहीं है। किसी भी प्रकार में, आप बिंदु चूक गए हैं। प्रश्न ने आपको पहले ही बताया है कि मेरे दूसरे उत्तर में कोड का कोई प्रभाव नहीं पड़ रहा है। आपको यह बताने की जरूरत है कि ऐसा क्यों होगा। एक्सपी विषयों की कमी असली कारण है। –

संबंधित मुद्दे