Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

How to scroll a client area?

SephirothSephiroth Fayetteville, NC, USAMember Posts: 1,035
Alright, as the topic suggests I need to know how to scroll the client area of a static window.I have created the window and setup scrollbars, but they don't seem to respond in any way. Below is the current code I am using to setup the scrollbars. The window in question is a child window but is open the entire time the parent window is open.
[code]
//Get the viewport client area
if(GetClientRect(this->whChild.Viewport, &(this->vdView.rArea)) == 0)
{
this->pLog->Write("Warning: Failed to get the viewport window client area during sizing");
return;
}

//Setup the viewport vertical scrolling range
this->vdView.ScrollRange.cbSize = sizeof(this->vdView.ScrollRange.cbSize);
this->vdView.ScrollRange.fMask = SIF_RANGE | SIF_PAGE;
this->vdView.ScrollRange.nMin = -524288;
this->vdView.ScrollRange.nMax = 524288;
this->vdView.ScrollRange.nPage = ((this->vdView.rArea.bottom - this->vdView.rArea.top) / 32);
SetScrollInfo(this->whChild.Viewport, SB_VERT, &(this->vdView.ScrollRange), true);

//Setup the viewport horizontal scrolling range
this->vdView.ScrollRange.cbSize = sizeof(this->vdView.ScrollRange.cbSize);
this->vdView.ScrollRange.fMask = SIF_RANGE | SIF_PAGE;
this->vdView.ScrollRange.nMin = -524288;
this->vdView.ScrollRange.nMax = 524288;
this->vdView.ScrollRange.nPage = ((this->vdView.rArea.right - this->vdView.rArea.left) / 32);
SetScrollInfo(this->whChild.Viewport, SB_HORZ, &(this->vdView.ScrollRange), true);
[/code]
After this I have tried catching the scroll messages but the scrollbars don't act like I am clicking on them. In fact, I have noticed that clicking on the scrollbars is like clicking in the client area of the window itself. The scrollbar arrows are not pressed when you click on them, like the bars are static images. I created the bars with the child window using WS_HSCROLL and WS_VSCROLL styles. So how would I deal with these bars?

-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

Comments

  • AsmGuru62AsmGuru62 Member Posts: 6,519
    : Alright, as the topic suggests I need to know how to scroll the
    : client area of a static window.I have created the window and setup
    : scrollbars, but they don't seem to respond in any way. Below is the
    : current code I am using to setup the scrollbars. The window in
    : question is a child window but is open the entire time the parent
    : window is open.
    : [code]:
    : //Get the viewport client area
    : if(GetClientRect(this->whChild.Viewport, &(this->vdView.rArea)) == 0)
    : {
    : this->pLog->Write("Warning: Failed to get the viewport window client area during sizing");
    : return;
    : }
    :
    : //Setup the viewport vertical scrolling range
    : this->vdView.ScrollRange.cbSize = sizeof(this->vdView.ScrollRange.cbSize);
    : this->vdView.ScrollRange.fMask = SIF_RANGE | SIF_PAGE;
    : this->vdView.ScrollRange.nMin = -524288;
    : this->vdView.ScrollRange.nMax = 524288;
    : this->vdView.ScrollRange.nPage = ((this->vdView.rArea.bottom - this->vdView.rArea.top) / 32);
    : SetScrollInfo(this->whChild.Viewport, SB_VERT, &(this->vdView.ScrollRange), true);
    :
    : //Setup the viewport horizontal scrolling range
    : this->vdView.ScrollRange.cbSize = sizeof(this->vdView.ScrollRange.cbSize);
    : this->vdView.ScrollRange.fMask = SIF_RANGE | SIF_PAGE;
    : this->vdView.ScrollRange.nMin = -524288;
    : this->vdView.ScrollRange.nMax = 524288;
    : this->vdView.ScrollRange.nPage = ((this->vdView.rArea.right - this->vdView.rArea.left) / 32);
    : SetScrollInfo(this->whChild.Viewport, SB_HORZ, &(this->vdView.ScrollRange), true);
    : [/code]:
    : After this I have tried catching the scroll messages but the
    : scrollbars don't act like I am clicking on them. In fact, I have
    : noticed that clicking on the scrollbars is like clicking in the
    : client area of the window itself. The scrollbar arrows are not
    : pressed when you click on them, like the bars are static images. I
    : created the bars with the child window using WS_HSCROLL and
    : WS_VSCROLL styles. So how would I deal with these bars?
    :
    : -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/gre
    : en][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h
    : [/red][/b][/italic]

    [color=Blue]
    So, which procedure catches the scroll messages? I think the whole problem is that you trying to use static control where you need the whole functioning window. The scroll messages will go to a static control's window procedure - not to the parent of that static control. So, here you need to subclass that control and catch messages there (in subclassed procedure).
    [/color]
  • SephirothSephiroth Fayetteville, NC, USAMember Posts: 1,035
    : [color=Blue]
    : So, which procedure catches the scroll messages? I think the whole
    : problem is that you trying to use static control where you need the
    : whole functioning window. The scroll messages will go to a static
    : control's window procedure - not to the parent of that static
    : control. So, here you need to subclass that control and catch
    : messages there (in subclassed procedure).
    : [/color]
    You're right, and I figured that out last night after a few hours on the MSDN. I am attempting to do so using the following procedure. The problem is, this procedure is a method in my primary class and it is giving me problems. If I declare the method static I lose access to members of the class, such as the original procedure pointer. If I Don't declare it as static, I cannot use it in "SetWindowLong()". Got any ideas?
    [code]
    LRESULT CALLBACK ETWindow::ViewportCalls(HWND hwndWindow, UINT uiMessage, WPARAM wpCode, LPARAM lpCode)
    {
    switch(uiMessage)
    {
    case WM_HSCROLL:
    MessageBox(hwndWindow, "HScroll", "Debug", MB_OK);
    break;

    case WM_VSCROLL:
    MessageBox(hwndWindow, "VScroll", "Debug", MB_OK);
    break;
    }

    return CallWindowProc((WNDPROC)this->vdView.lCallAddress, hwndWindow, uiMessage, wpCode, lpCode);
    }
    [/code]
    This procedure will handle scrolling and then pass any other messages to the original procedure for processing. The thing is, static breaks calling the original procedure here, and non-static breaks "SetWindowLong()". Ideas?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
  • AsmGuru62AsmGuru62 Member Posts: 6,519
    [color=Blue]
    I do it simply by declaring the callback as it was done in C - no need for any statics. Here is my class, (you can derive classes from it and use it):

    Header file:
    [/color]

    [code]
    // -------------------------------------------------------------------------
    // FILE: TWindow.h
    // DATE: Thursday, November 17, 2005
    // -------------------------------------------------------------------------
    // Generated by CppWriter 1.2 -- Copyright (C) CodeXXI Inc.
    // -------------------------------------------------------------------------

    #ifndef TWINDOW_H
    #define TWINDOW_H

    // Dependencies:

    // -------------------------------------------------------------------------
    class TWindow {
    public:
    TWindow ();
    virtual ~TWindow ();

    // Methods:
    VOID ForceFocus ();
    VOID RepaintRect (RECT* pArea);
    VOID Show (int iCmd);
    BOOL IsVisible ();
    VOID Move (RECT& area);
    VOID Create (HWND hOwner, UINT uiStyle, UINT uiChildID);

    // Override:
    virtual VOID WmDestroy ();
    virtual VOID WmSize (LPARAM lp);
    virtual VOID WmCreate (HWND hWnd);
    virtual VOID FillRegistration (WNDCLASS& wc);
    virtual PCHAR ClassName ();
    virtual LRESULT MsgMap (UINT uiMsg, WPARAM wp, LPARAM lp);

    // Data:
    HWND m_Handle;
    RECT m_ClientArea;
    };

    #endif // TWINDOW_H
    [/code]

    [color=Blue]
    Implementation file:
    (For some reason forum adds an empty line in code blocks, but not always)
    [/color]

    [code]
    // -------------------------------------------------------------------------
    // FILE: TWindow.cpp
    // DATE: Thursday, November 17, 2005
    // -------------------------------------------------------------------------
    // Generated by CppWriter 1.2 -- Copyright (C) CodeXXI Inc.
    // -------------------------------------------------------------------------

    #include "All.h"
    #include "TWindow.h"

    // -------------------------------------------------------------------------
    LRESULT CALLBACK callback_GenericWindow (HWND hWnd, UINT uiMsg, WPARAM wp, LPARAM lp) {
    TWindow* pWnd;

    if (uiMsg == WM_CREATE) {
    pWnd = (TWindow*) (((CREATESTRUCT*) lp)->lpCreateParams);
    SetWindowLong (hWnd, 0, (LONG) pWnd);
    pWnd->WmCreate (hWnd);
    return 0;
    }

    if ((pWnd = (TWindow*) GetWindowLong (hWnd, 0)) != NULL) {
    if (uiMsg == WM_DESTROY) {
    pWnd->WmDestroy ();
    SetWindowLong (hWnd, 0, 0);
    return 0;
    }
    return pWnd->MsgMap (uiMsg, wp, lp);
    }

    return DefWindowProc (hWnd, uiMsg, wp, lp);
    }

    // -------------------------------------------------------------------------
    TWindow::TWindow () {
    m_Handle = NULL;
    SetRectEmpty (&m_ClientArea);
    }

    // -------------------------------------------------------------------------
    TWindow::~TWindow () {
    }

    // -------------------------------------------------------------------------
    LRESULT TWindow::MsgMap (UINT uiMsg, WPARAM wp, LPARAM lp) {
    if (uiMsg == WM_SIZE) {
    if ((wp != SIZE_MINIMIZED) && lp) {
    WmSize (lp);
    }
    return 0;
    }

    if (uiMsg == WM_ERASEBKGND) {
    return 1;
    }

    return DefWindowProc (m_Handle, uiMsg, wp, lp);
    }

    // -------------------------------------------------------------------------
    PCHAR TWindow::ClassName () {
    return "TWindow";
    }

    // -------------------------------------------------------------------------
    VOID TWindow::FillRegistration (WNDCLASS& wc) {
    memset (&wc, 0, sizeof (wc));
    wc.cbWndExtra = sizeof (this);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.hInstance = GetModuleHandle (NULL);
    wc.lpfnWndProc = callback_GenericWindow;
    wc.lpszClassName = ClassName ();
    }

    // -------------------------------------------------------------------------
    VOID TWindow::Create (HWND hOwner, UINT uiStyle, UINT uiChildID) {
    WNDCLASS wc;
    HINSTANCE hModule = GetModuleHandle (NULL);

    if (! GetClassInfo (hModule, ClassName (), &wc)) {
    FillRegistration (wc);
    RegisterClass (&wc);
    }

    CreateWindow (ClassName (), NULL, uiStyle, 0, 0, 0, 0, hOwner, (HMENU) uiChildID, hModule, this);
    }

    // -------------------------------------------------------------------------
    VOID TWindow::WmCreate (HWND hWnd) {
    m_Handle = hWnd;
    }

    // -------------------------------------------------------------------------
    VOID TWindow::WmSize (LPARAM lp) {
    m_ClientArea.right = LP2X (lp);
    m_ClientArea.bottom = LP2Y (lp);
    }

    // -------------------------------------------------------------------------
    VOID TWindow::Move (RECT& area) {
    MoveWindow (m_Handle, area.left, area.top, WRECT (area), HRECT (area), TRUE);
    }

    // -------------------------------------------------------------------------
    BOOL TWindow::IsVisible () {
    return IsWindowVisible (m_Handle);
    }

    // -------------------------------------------------------------------------
    VOID TWindow::Show (int iCmd) {
    ShowWindow (m_Handle, iCmd);
    }

    // -------------------------------------------------------------------------
    VOID TWindow::RepaintRect (RECT* pArea) {
    InvalidateRect (m_Handle, pArea, TRUE);
    UpdateWindow (m_Handle);
    }

    // -------------------------------------------------------------------------
    VOID TWindow::ForceFocus () {
    SetFocus (m_Handle);
    }

    // -------------------------------------------------------------------------
    VOID TWindow::WmDestroy () {
    }
    [/code]
  • SephirothSephiroth Fayetteville, NC, USAMember Posts: 1,035
    Wow, that's almost identical to mine, only mine holds the instance handle (HINSTANCE) as well. The method you use is also similar to mine. When I call the method to create the window within my class I pass "this" in the LPARAM and catch it in NC_CREATE. After that I can retrieve this data from any number of windows derived from my class and dispatch messages to the real procedure, which is virtual and set to zero so you are required to overried it in a subclass. Then you simply subclass it and you're set.

    *EDIT*

    Check your private messages. I just sent you the source to what I am using and want you to look it over. It is compiling without error, but won't dispatch messages properly to my child window.

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
Sign In or Register to comment.