【问题标题】:How to make a win32 text box scroll like an iPhone如何让win32文本框像iPhone一样滚动
【发布时间】:2011-01-22 05:01:41
【问题描述】:

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

【问题讨论】:

    标签: windows-mobile winapi textbox scroll


    【解决方案1】:

    在不涉及技术细节的情况下,您应该考虑将“鼠标”点击事件分为“鼠标”向下和“鼠标”向上事件。

    如果指针位置自向下事件以来未更改,则在向上事件上执行选择。因此,您需要将指针位置存储在向下事件中。

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

    【讨论】:

    • 嘿,我怎么没想到。非常感谢,我试试看。
    【解决方案2】:

    我让它工作了。这并不像我希望的那样微不足道。顺便说一句,这应该适用于普通 Windows,而不仅仅是 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
        );
    }
    

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

        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(&currentMousePos);
    
                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()。它们在我的程序中很长而且很复杂,因为我让它们也做其他事情(与绘制窗口有关)。如果您真的想要该代码,请给我发消息或其他内容。如果我以正确的方式发布内容,也请告诉我,因为我是在论坛等上发帖的新手。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-24
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 2019-06-26
      • 2015-05-12
      相关资源
      最近更新 更多