如何使win32文本框像iPhone一样滚动

时间:2010-03-01 08:16:13

标签: windows-mobile winapi textbox scroll

我正在win32中为Windows Mobile平台制作一个程序(在WM6.1上测试)。大多数主窗口都包含一个文本框,我想用手指滚动它而不是选择文本。我该怎么做呢?

2 个答案:

答案 0 :(得分:1)

如果不进入技术细节,您应该考虑将“鼠标”点击事件分为“鼠标”和“鼠标”事件。

如果指针位置自down事件以来没有改变,则对up事件执行选择。因此,您需要将指针位置存储在向下事件中。

然后你可以处理指针移动事件来执行滚动。

答案 1 :(得分:1)

我得到了它的工作。这并不像我希望的那样微不足道。顺便说一下,这应该适用于普通的窗户,而不仅仅是windows mobile。它是这样的:

创建窗口时(作为主窗口的子窗口)


HWND createCustomDrawArea(const LPCTSTR className, const HWND hWndParent) {
    WNDCLASS wndClass = {
        CS_HREDRAW | CS_VREDRAW,
        (WNDPROC)wndProc,
        0,
        0,
        hInstMain,
        NULL,
        0,
        (HBRUSH)GetStockObject(HOLLOW_BRUSH),
        0,
        className
    };

    RegisterClass(&wndClass);

    return CreateWindow(
        className,
        className,
        WS_CHILD | WS_TABSTOP,
        0, 0, 0, 0,
        hWndParent,
        NULL,
        hInstMain,
        NULL
    );
}

然后在main函数(主消息循环)中:

    while(GetMessage(&msg, NULL, 0, 0)) {
        if(!handleScrollingMessages(msg.hwnd, msg.message, msg.wParam, msg.lParam) && !TranslateAccelerator(msg.hwnd, NULL, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

我这样做是为了一旦手指(鼠标)向下,你可以将手指移动到其他位置(它仍然在同一个程序中,但可以在滚动窗口之外),它会继续滚动直到你放手(鼠标向上)。消息处理程序如下所示:


inline BOOL handleScrollingMessages(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static BOOL mouseIsDown = FALSE;
    static BOOL isScrolling;
    static POINT firstMousePos;
    static POINT lastMousePos;
    POINT currentMousePos;

    switch(message) {
        case WM_MOUSEMOVE:
            if(!mouseIsDown) {
                return FALSE;
            }
            GetCursorPos(¤tMousePos);

            scrollText(currentMousePos.y - lastMousePos.y);
            if(!isScrolling && (
                firstMousePos.x  currentMousePos.x + FINGER_SCROLL_SENSITIVITY ||
                firstMousePos.y  currentMousePos.y + FINGER_SCROLL_SENSITIVITY
            )) {
                isScrolling = TRUE;
            }
            lastMousePos = currentMousePos;
            return TRUE;

        case WM_LBUTTONDOWN:
            if(hWnd == whichPrimaryIsVisible) {
                if(!mouseIsDown) {
                    GetCursorPos(&firstMousePos);
                    lastMousePos = firstMousePos;
                    mouseIsDown = TRUE;
                    isScrolling = FALSE;
                }
                return TRUE;
            }
            return FALSE;

        case WM_LBUTTONUP:
            if(mouseIsDown) {
                mouseIsDown = FALSE;
                if(isScrolling) {
                    isScrolling = FALSE;
                } else {
                    if(hWnd == whichPrimaryIsVisible) {
                        jumpToSong(HIWORD(lParam));
                    }
                }
                return TRUE;
            }
            return FALSE;
    }

    return FALSE;
}

在普通的消息处理程序中,您必须捕获WM_ERASEBKGND和WM_PAINT消息:


        case WM_ERASEBKGND:
            if(hWnd == whichPrimaryIsVisible) {
                drawBackground(hWnd, (HDC)wParam);
                return 1;
            }
            return DefWindowProc(hWnd, message, wParam, lParam);

        case WM_PAINT:
            if(hWnd != hWndMain && drawWindowSection(hWnd)) {
                return 0;
            }
            return DefWindowProc(hWnd, message, wParam, lParam);

然后,您必须分别绘制背景和文本(前景)。滚动功能如下所示:


inline void scrollText(const int mouseChange) {
    RECT wholeAreaRect;
    RECT invalidatedRect;

    scrollPos += mouseChange;

    GetClientRect(whichPrimaryIsVisible, &wholeAreaRect);
    ScrollWindowEx(whichPrimaryIsVisible, 0, mouseChange, NULL, &wholeAreaRect, NULL, &invalidatedRect, SW_ERASE | SW_INVALIDATE);
    UpdateWindow(whichPrimaryIsVisible);
}

请记住whichPrimaryIsVisible是滚动窗口(全局变量),而scrollPos是一个全局int。

唯一剩下的就是drawBackground()和drawWindowSection()。它们在我的程序中很长很复杂,因为我让它们做其他事情(这与绘制窗口BTW有关)。如果你真的想要那些代码,那么给我发消息或者其他什么。如果我以正确的方式发布内容,请告诉我,因为我刚刚在论坛上发帖等。