Bei einem Splitter handelt es sich um kein Control in dem Sinn, wie Sie dies von einem Fenster, Button o.ä. kennen. Der Splitter wird einfach nur "simuliert", indem Sie zwischen den Controls Platz frei lassen. Im Bild erkennen Sie diesen freien Bereich an der Schraffur zwischen Tree-View (links) und List-View (rechts)

Wie Sie auch im Beispielprogramm sehen können, werden die drei Controls (Tree-View, List-View und Edit-Control) jeweils an der gleichen Position im Fenster erzeugt, und das Edit-Control hat zu diesem Zeitpunkt nicht einmal Breite und Höhe:
hTreeView := CreateWindowEx(WS_EX_CLIENTEDGE,WC_TREEVIEW,nil, WS_VISIBLE or WS_CHILD or TVS_HASLINES or TVS_LINESATROOT or TVS_HASBUTTONS or TVS_EDITLABELS,0,0,10,10,wnd, IDC_TREEVIEW,hInstance,nil);
hLV := CreateWindowEx(WS_EX_CLIENTEDGE,WC_LISTVIEW,nil, WS_VISIBLE or WS_CHILD or LVS_ICON or LVS_AUTOARRANGE or LVS_SHAREIMAGELISTS,0,0,10,10,wnd,IDC_LV,hInstance,nil);
hMemo := CreateWindowEx(WS_EX_CLIENTEDGE,'Edit',nil, WS_CHILD or WS_VISIBLE or WS_VSCROLL or ES_MULTILINE or ES_NOHIDESEL,0,0,0,0,wnd,IDC_MEMO,hInstance,nil);
Aber das spielt keine Rolle, denn die Neupositionierung und die Änderung der Größe findet in "WM_SIZE" statt.
Zunächst sind aber ein paar Konstanten und Variablen erforderlich, mit denen wir uns die Arbeit ein wenig erleichtern wollen. Der Einfachheit halber habe ich die minimale Breite und Höhe sowie die Breite des Splitters an sich als Konstanten deklariert.
Die integer-Variablen dienen später zur Ermittlung der Position, und die beiden bool-Variablen werden als Flags benutzt, damit das Programm "weiß", wann ein Splitter gezogen wird und wann nicht
const MINVSPLIT = 190; MINHSPLIT = 100; SPLITWIDTH = 3; var vSplitPos : integer = MINVSPLIT + 30; hSplitPos : integer = wHeight - (MINHSPLIT + 50); fVTrackSplit : boolean = false; fHTrackSplit : boolean = false;
Wie gesagt wird nun in "WM_SIZE" dafür gesorgt, dass a) die Controls entsprechend neu positioniert werden, und dass sie b) auch die neuen Größen erhalten, damit die beiden Splitter quasi sichtbar werden.
Sollten allerdings die Maße des Fensters so gering sein, dass die Splitter nicht mehr zu sein sein würden, wird ihre Position ggf. zurückgesetzt. Beachten Sie bitte, dass die beiden Variablen "i" und "rc" im Beispielprogramm vorher ermittelt werden und die Höhe der Statuszeile und die Maße des Clientbereichs des Fensters enthalten
if(vSplitPos >= rc.Right - MINVSPLIT) then vSplitPos := rc.Right - MINVSPLIT; if(hSplitPos >= rc.Bottom - i - MINHSPLIT) then hSplitPos := rc.Bottom - i - MINHSPLIT;
Nun können wir uns an die Controls heranwagen:
Zuerst verschieben wir den Tree-View auf seine neue Position. Da er links sein soll, sind zumindest die X- und Y-Werte kein Problem und richten sich nach den Angaben im Rechteck "rc". Für die Breite verwenden wir die Variable "vSplitPos", und für die Höhe "hSplitPos"
MoveWindow(hTreeView,rc.Left,rc.Top,vSplitPos,hSplitPos,true);
Die List-View hat mit dem Tree-View zumindest die Y-Koordinate und die Höhe gemeinsam: nämlich den oberen Rand des Clientbereichs des Fensters sowie die Variable "hSplitPos". Der X-Wert allerdings richtet sich ebenfalls nach der Variablen "vSplitPos", wobei hier aber noch die Breite des Splitters berücksichtigt werden muss. Schließlich wollen Sie ja den gewünschten Platz zwischen den beiden Controls lassen. Und die Breite des Controls errechnet sich aus der Angabe in der schon erwähnten TRect-Variablen, wobei hier natürlich die Splitterposition und -breite abgezogen werden müssen
MoveWindow(hLV,vSplitPos + SPLITWIDTH,rc.Top,rc.Right - (vSplitPos + SPLITWIDTH),hSplitPos,true);
Damit bleibt noch das mehrzeilige Editfeld (quasi ein Memo), das im unteren Teil des Fensters sitzt und durch einen horizontalen Splitter von Tree-View und List-View getrennt ist.
Hier sind die Angaben für den linken und rechten Rand recht einfach, weil der Splitter ja über die gesamte Fensterbreite gehen soll. Als Höhe wird dagegen die Variable "hSplitPos" (mit der Angabe zur Splitterposition) herangezogen, wobei auch hier die Konstante mit dem Breiten- bzw. (in dem Fall) Höhenwert addiert werden muss, damit Sie den Splitter auch sehen. Und die Höhe des Editfeldes selbst richtet sich nach dem unteren Rand des Fensters, von dem natürlich die Höhe der Statuszeile und die Splitterposition und -breite abgezogen werden müssen
MoveWindow(hMemo,rc.Left,hSplitPos + SPLITWIDTH,rc.Right, rc.Bottom - i - (hSplitPos + SPLITWIDTH),true);
Damit wäre der erste Schritt vollbracht. Die "Splitter" reagieren zwar bisher auf überhaupt nichts, aber es hat zumindest schon einmal den Anschein, als wäre da was ... :o)