[C++/WinAPI] Obsługa Scrollbar'a jako kontrolki

0

Tworzę sobię pionowego Scrollbar'a:

HWND hVscroll;
...
hVscroll=CreateWindow("SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_VERT, rect.right-15, 0, 15, rect.bottom, hoglg, (HMENU)204, hInst, NULL);

deklaruję zmienną z max pozycją scrollbar'a:

int Iheight=1480;

oraz określam od razu jego maksymalną i minimalną wartość:

SetScrollRange(hVscroll, SB_CTL, 0, Iheight,true);

no i pozostało mi już tylko obsłużyć komunikat dla tego scrollbar'a:

case WM_VSCROLL :
int newpos;
switch (LOWORD (wParam))
{
	case SB_LINEUP :
	if (newpos>0) newpos++;
	break;

	case SB_LINEDOWN :
	if (newpos<Iheight) newpos--;
	break;

	case SB_PAGEUP :
	break;

	case SB_PAGEDOWN :
	break;

	case SB_THUMBTRACK :
	break;
	
	case SB_THUMBPOSITION :
	newpos=HIWORD (wParam);
	break;

	default :
	break;
	SetScrollPos(hVscroll, SB_CTL, newpos, true);
}
	return 0;
break;	

tylko że przy zmianie pozycji scroll'a nie zostaje na miejscu puszczenia thumba... to jest jeden z dwóch scrollbarów które w ogóle wykorzystuję w programie... ale jeden jest V (pionowy), drugi jest H (poziomy) ;)
Tyle że nie zostaje na miejscu ani jeden... coś jakby ten ten cały komunikat WM_VSCROLL nie był odbierany... co zrobić :>

0

Nie wiem, może ślepy jestem, ale nie widzę żeby gdzieś była inicjowana zmienna newpos ;)

//EDIT: OK, widzę ;P Spróbuj może tak:

...
case SB_THUMBPOSITION :
  SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam), true);
  break;
...

Tak ogólnie to usuń SetScrollPos spod default'a, a dodaj tam gdzie użycie tej funkcji jest konieczne - SB_LINEUP, SB_LINEDOWN.

0

teraz wygląda tak:

case WM_VSCROLL :
switch (LOWORD (wParam))
{
	case SB_LINEUP :
	if (yPos>0) yPos++;
	SetScrollPos(hVscroll, SB_CTL,yPos, true);
	break;

	case SB_LINEDOWN :
	if (yPos<Iheight) yPos--;
	SetScrollPos(hVscroll, SB_CTL,yPos, true);
	break;

	case SB_PAGEUP :
	
	break;

	case SB_PAGEDOWN :
	
	break;

	case SB_THUMBTRACK :
	break;
	
	case SB_THUMBPOSITION :
	SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam), true);
	break;

	default :
	break;
}
break;	

ale dalej przy obsłudze tego zdarzenia nie wyłapuje :(

0

[...] ale dalej przy obsłudze tego zdarzenia nie wyłapuje

Ale co, wysyła w ogóle komunikat WM_VSCROLL??? Dawałeś jakiegoś breakpoint'a na ten komunikat???

Dalej....

case SB_LINEUP :
  if (yPos>0) yPos++;  //<--- tu chyba coś jest nie tak
  SetScrollPos(hVscroll, SB_CTL,yPos, true);
  break;

case SB_LINEDOWN :
  if (yPos<Iheight) yPos--;    //<--- i tu :)
  SetScrollPos(hVscroll, SB_CTL,yPos, true);
  break;

yPos przed pomniejszeniem/powiększeniem powinna mieć przypisaną aktualną wartość scrolla.

0

no to proszę, spróbuj sobię skompilować przykład który przed chwilą zrobiłem, ciekawe czy tak dobrze działa scroll :]

#include <windows.h>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
HWND hVscroll, hstat;
int Iheight=1480;
int yPos;

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASS wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) BLACK_BRUSH;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClass (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindow (
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
            hstat=CreateWindow("static", NULL, WS_CHILD | WS_VISIBLE , 2, 2, 60, 320, hwnd, (HMENU)204, NULL, NULL);
            hVscroll=CreateWindow("SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_VERT, 10, 10, 15, 300, hstat, (HMENU)204, NULL, NULL);
            SetScrollRange(hVscroll, SB_CTL, 0, Iheight,true);
            break;
        case WM_VSCROLL :
if (lParam==(int)hVscroll)
    {
switch (LOWORD (wParam))
{
        case SB_LINEUP :
        SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam)-1, true);
        break;

        case SB_LINEDOWN :
        if (yPos<Iheight) yPos--;
        SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam)+1, true);
        break;

        case SB_THUMBTRACK :
            SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam), true);
        break;
       
        case SB_THUMBPOSITION :
        SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam), true);
        break;

        default :
        break;
return 0;
}
}
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

Jednocześnie proszę Cię o poprawienie tego co jest źle, jeśli potrafisz ;)

0

Jednocześnie proszę Cię o poprawienie tego co jest źle, jeśli potrafisz

Ja nie potrafie??? ;P Podstawowym błędem było to, że dałeś nie ten co trzeba uchwyt okna-rodzica.

// scroll.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
HWND hVscroll, hstat;
int Iheight=1480;
int yPos;

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    HWND hwnd;               /* this is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASS wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* this function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* catch double-clicks */

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) BLACK_BRUSH;

    /* register the window class, and if it fails quit the program */
    if (!RegisterClass (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindow (
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}

//////////////////////////////////
/*  this function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int nPos;

    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
            hstat=CreateWindow("static", NULL, WS_CHILD | WS_VISIBLE , 2, 2, 60, 320, hwnd, (HMENU)204, NULL, NULL);
            hVscroll=CreateWindow("SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_VERT, 10, 10, 15, 300, hwnd/*hstat*/, (HMENU)204, NULL, NULL);
            SetScrollRange(hVscroll, SB_CTL, 0, Iheight,true);
            break;
        case WM_VSCROLL:
          if((HWND)lParam==hVscroll)
		  {
			switch (LOWORD (wParam))
			{
			 case SB_LINEUP :
			   nPos=GetScrollPos((HWND)lParam,SB_CTL);
			   if(nPos>0)nPos--;
               SetScrollPos((HWND)lParam,SB_CTL,nPos,true);
               break;

             case SB_LINEDOWN :
			   nPos=GetScrollPos((HWND)lParam,SB_CTL);
			   if(nPos<Iheight)nPos++;
               SetScrollPos((HWND)lParam,SB_CTL,nPos,true);
               break;

             //case SB_THUMBTRACK :
             //  break;
       
             case SB_THUMBPOSITION :
               SetScrollPos(hVscroll, SB_CTL,HIWORD(wParam), true);
               break;

             default:
               break;
			}
		  }
		  break;

        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}



0

Trzeba było subclassować statica i z tego obsługiwać ;)

0
Talib napisał(a)

Trzeba było subclassować statica i z tego obsługiwać ;)

No nie tylko ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1