Windows Programmierung: Splitbar |
Der Splitbar ist der verschiebbare Balken, der im Windows-Explorer seit Windows 95 die Baumdarstellung der Verzeichnisse von der Liste der Dateien auf der rechten Seite trennt. Leider ist dieser kein Kontrollelement der Win32-API, sondern muss vollständig selbst programmiert werden, was aber gar nicht so schwer ist. Als Nebeneffekt kann man ihn auch leicht für Programme unter Windows 3.x verwenden, da er nicht auf Spezialitäten der Win32 aufsetzt.
Bewegt sich die Maus über diesen Spalt, wird die Mauszeiger auf einen Doppelpfeil umgeschaltet. Wird die Maus niedergedrückt und verschoben, wird damit die VBarPos geändert. Beim Loslassen der Maus werden die Kontrollelemente neu positioniert.
Zur optischen Rückmeldung wird ein invertierter Streifen beim Verschieben
durch das Bild geschoben. Die Technik ist die gleiche wie beim
Aufspannen eines Markierungsrechtecks,
des sogenannten Gummibandes.
Ereignisse in der Fensterfunktion
Zunächst sind die Nachrichten der Fensterfunktion abzufangen.
Dabei interessieren die Mausereignisse Bewegung, Tastendruck und Loslassen.
Aber auch das Ereignis zur Grössenänderung WM_SIZE muss
angepasst werden.
static HWND hEdit; static HWND hToolbar; static HWND hListe; static int VBarPos = 0; POINTS pos; // for mouse operations static bool TrackSplit = false; ... case WM_SIZE: reSize(hWnd, hToolbar, hEdit, hListe, VBarPos); break; case WM_MOUSEMOVE: pos = MAKEPOINTS(lParam); if (TrackSplit) { drawCapture(hWnd, VBarPos); VBarPos = pos.x; drawCapture(hWnd, VBarPos); } if (pos.x<=VBarPos+2 && pos.x>=VBarPos-2) { SetCursor(LoadCursor(0, IDC_SIZEWE)); } break; case WM_LBUTTONDOWN: pos = MAKEPOINTS(lParam); if (pos.x<=VBarPos+2 && pos.x>=VBarPos-2) { TrackSplit = true; SetCapture(hWnd); VBarPos = pos.x; drawCapture(hWnd, VBarPos); SetCursor(LoadCursor(0, IDC_SIZEWE)); } break; case WM_LBUTTONUP: pos = MAKEPOINTS(lParam); if (TrackSplit) { TrackSplit = false; drawCapture(hWnd, pos.x); VBarPos = pos.x; ReleaseCapture(); reSize(hWnd, hToolbar, hEdit, hListe, VBarPos); } break; |
Ein Sonderfall kann eintreten, wenn das Fenster über den Schiebebalken hinweg verkleinert wird. Der Schiebebalken muss in jedem Fall in das Fenster hinein, damit er weiter zugreifbar bleibt.
#define BARWIDTH 4 void reSize(HWND hWnd, HWND hToolbar, HWND hEdit, HWND hListe, int &VBarPos) { RECT rcl, win; GetClientRect(hWnd, &win); // get (new) window size // Get the size of the toolbar SendMessage(hToolbar, TB_AUTOSIZE, 0L, 0L); GetWindowRect(hToolbar, &rcl); int xSize = win.right; int ySize = win.bottom; if (VBarPos==0) VBarPos = xSize/4; if (VBarPos < BARWIDTH) VBarPos=5; if (VBarPos > xSize-BARWIDTH) VBarPos = xSize; if (VBarPos<0) VBarPos=0; // Size the rich edit control to the right MoveWindow(hEdit, VBarPos+BARWIDTH/2, rcl.bottom - rcl.top, xSize - VBarPos - BARWIDTH/2, ySize, TRUE ); // Size the tree control to the left MoveWindow(hListe, 0, rcl.bottom - rcl.top, VBarPos-BARWIDTH/2, ySize, TRUE ); } |
void drawCapture(HWND hWnd, int x) { RECT r; GetClientRect(hWnd, &r); int y = r.bottom; HDC hDC = GetDC(hWnd); SetROP2(hDC, R2_NOT); MoveToEx(hDC, x-BARWIDTH/2, 0, 0); LineTo(hDC, x-BARWIDTH/2, y); LineTo(hDC, x+BARWIDTH/2, y); LineTo(hDC, x+BARWIDTH/2, 0); LineTo(hDC, x-BARWIDTH/2, 0); ReleaseDC(hWnd, hDC); } |
Hier wird die Grösse des Fensters für die Höhe des Balkens berechnet. Mit SetROP2 und R2_NOT wird invertierendes Zeichnen eingestellt und anschliessend das Rechteck um den Balken gezeichnet. Will man das Verhalten des Explorers komplett kopieren, müsste man an dieser Stelle die x-Position der linken oberen Ecke auf 0 setzen. Dass auch Microsoft dieses Verfahren im Visual Studio ändert, zeigt, dass das Umrahmen des Balkens die optisch naheliegendere Lösung ist.
Etwas unschön ist noch, dass der Balken durch die Toolbar geht. Dies ist mit den ersten Zeilen aus reSize leicht zu ändern und ist hier der Übersichtlichkeit halber weggelassen.
WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); ... wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);//(COLOR_WINDOW+1); ... RegisterClassEx(&wcex); |
Homepage - Windows-API-Programmierung | (C) Copyright 1999 Arnold Willemer |