开发者

How to make a win32 text box scroll like an iPhone

I'm making a program in win32 for the Windows Mobile platform (testing on WM6.1). Most of the main window consists of开发者_JAVA百科 a single text box, and I would like to use my finger to scroll it instead of selecting the text. How would I go about doing that?


Without going into the technicalities you should be looking at separating the "mouse" click event into "mouse" down and "mouse" up events.

Perform the selection on the up event if the pointer location hasn't changed since the down event. So you will need to store the pointer location on the down event.

Then you can handle the pointer move event to perform the scrolling.


I got it to work. It wasn't as trivial as I had hoped. By the way, this should work on normal windows, not just windows mobile. It went something like this:

When you create the window (as a child window of the main window)


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
    );
}

Then in the main function (the main message loop):

    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);
        }
    }

I did this so that once the finger (mouse) is down, you can move your finger elsewhere (that's still in the same program, but can be outside the scrolling window), and it will continue to scroll until you let go (mouse up). The message handler looks like this:


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;
}

In the normal message handler, you have to catch the WM_ERASEBKGND and WM_PAINT messages:


        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);

You then have to draw both the background and the text (foreground) separately. The scrolling function looks like this:


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);
}

Keep in mind that whichPrimaryIsVisible is the scrolling window (global variable), and that scrollPos is a global int.

The only other thing that remains is drawBackground() and drawWindowSection(). They are long and convoluted in my program as I get them to do other things too (that are related to drawing the window BTW). If you really want that code, then send me a message or something. Also let me know if I've posted things the right way, as I'm new to posting on forums etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜