WinAPI Mehrere Buttons scrollen

üäpöol

Erfahrenes Mitglied
Hallo,
Ich sehe bei einigen Programmen (z.B. Skype) immer Buttons (?!) untereinander, die man scrollen kann. Ich hoffe ihr könnt verstehen, was ich meine. :) Leider habe ich keinen Anhaltspunkt gefunden, wie man so etwas macht. Ich hoffe ihr könnt mir helfen.
Vielen Dank für alle Antworten!
 
Zuletzt bearbeitet:
OK, ich beschreib das ganze mal etwas anders :) :
Ich habe ein paar Buttons untereinander und merke, dass es so viele Buttons sind, dass sie nicht auf das Fenster passen. Jetzt möchte ich einen Bereich (Childwindow?!) festlegen, in dem die Buttons sein können; die Buttons darunter müssen "erscrollt" werden, also scrollt mal wie bei einem Editfenster runter, um den restlichen Text zu sehen, allerdings möchte ich das ganze mit Buttons machen.
Ich hoffe es ist jetzt klarer. :)

Schönes Wochende
 
Du kannst bei CreateWindow() oder CreateWindowEx() festlegen, wo die Buttons sein sollen. Per Variable und 2 weiteren Buttons kannst du dann die Variable vergrössern/verkleinern. So kannst du die Buttons scrollen.
Auch möglich mit MoveWindow(). Alternativ könntest du naturlich auch eine Dropbox mit den Befehlen und einen "go"-Button einfügen. Du könntest die Buttons kleiner machen, usw.

Was willst du mit den Buttons tun? Vielleicht gibt es ja eine einfachere Lösung?

Gruss
cwriter
 
Zuletzt bearbeitet:
Du kannst jedem beliebigen Fenster dem MainWindow und auch allen Childs im CreateWindow() ein WS_VSCROLL mitgeben.
Du kannst sogar ein völlig unabhängiges Child erstellen, was nur eine Scrollbar enthält und damit den Inhalt von jedem beliebigen anderen Fenster scrollen.
Anders als bei edit controls, musst du dann aber in der WndProc das Scrollverhalten selber machen.
Wie das geht, dazu findet Google 1000 Treffer inkl. Tutorials, Suchbegriffe SCROLLINFO oder GetScrollInfo() oder SetScrollInfo()
 
OK. Ich bin mir nicht ganz sicher ob ich das richtig verstanden habe: Ich mache ein einfaches Childwindow mit Scrollbar mit eigener WndProc. Dann erstelle ich in diesem Childwindow einen Button. Ich probier das morgen mal aus. Danke schonmal. :)
 
Hm... Funktioniert leider nicht. Ich fürchte ich hab das falsch verstanden. Über einer genauere Erklärung würde ich mich sehr freuen. :)
 
Wenn ich ins Blaue raten soll, dann hast du Folgendes falsch verstanden:
"in der WndProc das Scrollverhalten selber machen"

Das bedeutet du musst in der WndProc einiges anstellen

1) case WM_CREATE:
Grösse vom Fenster im Verhältnis zu Scrollweite berechnen und damit
SetScrollInfo()
aufrufen
2) case WM_SIZE:
Neuberechnung der Werte aus WM_CREATE und damit
SetScrollInfo()
aufrufen
3) case WM_VSCROLL:
Scrollposition abfragen mit GetScrollInfo()
Werte an die neue Position anpassen und damit
SetScrollInfo()
aufrufen
InvalidateRect() aufrufen zum neu zeichnen des Inhalts.
4) case WM_PAINT:
Das ganze Fenster in einen memDC zeichnen,
Scrollposition abfragen mit GetScrollInfo()
Anhand der Werte den sichtbaren Auschnitt berechnen und mit BitBlt() aus dem memDC übertragen.

Ich kann dir ein Beispiel geben, vielleicht hilft das.
Für xx musst du jeweils die passenden Werte eingeben.

Code:
LRESULT CALLBACK ScrollWindow(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{

switch(msg)
{

case WM_CREATE:
{

RECT rect;
GetClientRect(hWnd,&rect);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.nMin = 0;
si.nMax = xx - 1; // Anzahl Buttons minus 1
si.nPage = rect.bottom / xx; // ButtonHöhe inkl Abstand zum Nächsten
si.fMask = SIF_PAGE|SIF_RANGE;
SetScrollInfo(hWnd,SB_VERT,&si,1);

return 0;

}
break;

case WM_SIZE:
{

RECT rect;
GetClientRect(hWnd,&rect);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.nMin = 0;
si.nMax = xx - 1; // Anzahl Buttons minus 1
si.nPage = rect.bottom / xx; // ButtonHöhe inkl Abstand zum Nächsten
si.fMask = SIF_PAGE | SIF_RANGE;
SetScrollInfo(hWnd, SB_VERT, &si, 1);
InvalidateRect(hWnd,0,0);

return 0;

}
break;

case WM_VSCROLL:
{

SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hWnd,SB_VERT,&si);
si.fMask = SIF_POS;
switch(LOWORD(wParam))
      {
          case SB_LINEUP:
          {
              si.nPos -= 1;
          }
          break;
          case SB_LINEDOWN:
          {
              si.nPos +=1;
          }
          break;
          case SB_PAGEUP:
          {
              si.nPos -= si.nPage;
          }
          break;
          case SB_PAGEDOWN:
          {
              si.nPos += si.nPage;
          }
          break;
          case SB_THUMBTRACK:
          {
              si.nPos = si.nTrackPos;
          }
          break;
      }

SetScrollInfo(hWnd, SB_VERT, &si, 1);
InvalidateRect(hWnd,0,0);

return 0;

}
break;

case WM_PAINT:
{

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP BMP_current = CreateCompatibleBitmap(hdc,FensterBreite,Fensterhöhe); // volle Grösse mit allen Buttons
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem,BMP_current);

// hier das GANZE Fenster zeichnen, mit BitBlt(hdcMem ...)

SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hWnd,SB_VERT,&si);

BitBlt(hdc,0,0,rect.right,rect.bottom,hdcMem,0,si.nPos * xx,SRCCOPY); // ButtonHöhe inkl Abstand zum Nächsten
SelectObject(hdcMem,hbmOld);
DeleteDC(hdcMem);
DeleteObject(BMP_current);
EndPaint(hWnd,&ps);

return 0;

}
break;

Eleganter wäre statt das gesamte Fenster zu zeichnen schon vorher zu berechnen, was sichtbar ist, aber das musst du dann selber ausrechnen.
 
Zuletzt bearbeitet:
Zurück