⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 popupmenuwin.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        return;    m_focusedIndex = client()->selectedIndex();    ::InvalidateRect(m_popup, 0, TRUE);    if (!scrollToRevealSelection())        ::UpdateWindow(m_popup);}bool PopupMenu::itemWritingDirectionIsNatural() {     return true; }const int separatorPadding = 4;const int separatorHeight = 1;void PopupMenu::paint(const IntRect& damageRect, HDC hdc){    if (!m_popup)        return;    if (!m_DC) {        m_DC = ::CreateCompatibleDC(::GetDC(m_popup));        if (!m_DC)            return;    }    if (m_bmp) {        bool keepBitmap = false;        BITMAP bitmap;        if (GetObject(m_bmp, sizeof(bitmap), &bitmap))            keepBitmap = bitmap.bmWidth == clientRect().width()                && bitmap.bmHeight == clientRect().height();        if (!keepBitmap) {            DeleteObject(m_bmp);            m_bmp = 0;        }    }    if (!m_bmp) {        BITMAPINFO bitmapInfo;        bitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);        bitmapInfo.bmiHeader.biWidth         = clientRect().width();         bitmapInfo.bmiHeader.biHeight        = -clientRect().height();        bitmapInfo.bmiHeader.biPlanes        = 1;        bitmapInfo.bmiHeader.biBitCount      = 32;        bitmapInfo.bmiHeader.biCompression   = BI_RGB;        bitmapInfo.bmiHeader.biSizeImage     = 0;        bitmapInfo.bmiHeader.biXPelsPerMeter = 0;        bitmapInfo.bmiHeader.biYPelsPerMeter = 0;        bitmapInfo.bmiHeader.biClrUsed       = 0;        bitmapInfo.bmiHeader.biClrImportant  = 0;        void* pixels = 0;        m_bmp = ::CreateDIBSection(m_DC, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);        if (!m_bmp)            return;        ::SelectObject(m_DC, m_bmp);    }    GraphicsContext context(m_DC);    int itemCount = client()->listSize();    // listRect is the damageRect translated into the coordinates of the entire menu list (which is itemCount * m_itemHeight pixels tall)    IntRect listRect = damageRect;    listRect.move(IntSize(0, m_scrollOffset * m_itemHeight));    for (int y = listRect.y(); y < listRect.bottom(); y += m_itemHeight) {        int index = y / m_itemHeight;        Color optionBackgroundColor, optionTextColor;        PopupMenuStyle itemStyle = client()->itemStyle(index);        if (index == focusedIndex()) {            optionBackgroundColor = theme()->activeListBoxSelectionBackgroundColor();            optionTextColor = theme()->activeListBoxSelectionForegroundColor();        } else {            optionBackgroundColor = itemStyle.backgroundColor();            optionTextColor = itemStyle.foregroundColor();        }        // itemRect is in client coordinates        IntRect itemRect(0, (index - m_scrollOffset) * m_itemHeight, damageRect.width(), m_itemHeight);        // Draw the background for this menu item        if (itemStyle.isVisible())            context.fillRect(itemRect, optionBackgroundColor);        if (client()->itemIsSeparator(index)) {            IntRect separatorRect(itemRect.x() + separatorPadding, itemRect.y() + (itemRect.height() - separatorHeight) / 2, itemRect.width() - 2 * separatorPadding, separatorHeight);            context.fillRect(separatorRect, optionTextColor);            continue;        }        String itemText = client()->itemText(index);                    unsigned length = itemText.length();        const UChar* string = itemText.characters();        TextRun textRun(string, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);        context.setFillColor(optionTextColor);                Font itemFont = client()->menuStyle().font();        if (client()->itemIsLabel(index)) {            FontDescription d = itemFont.fontDescription();            d.setWeight(d.bolderWeight());            itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());            itemFont.update(m_popupClient->fontSelector());        }                // Draw the item text        if (itemStyle.isVisible()) {            int textX = max(0, client()->clientPaddingLeft() - client()->clientInsetLeft());            int textY = itemRect.y() + itemFont.ascent() + (itemRect.height() - itemFont.height()) / 2;            context.drawBidiText(itemFont, textRun, IntPoint(textX, textY));        }    }    if (m_scrollbar)        m_scrollbar->paint(&context, damageRect);    if (!hdc)        hdc = ::GetDC(m_popup);    ::BitBlt(hdc, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY);}void PopupMenu::valueChanged(Scrollbar* scrollBar){    ASSERT(m_scrollbar);    if (!m_popup)        return;    int offset = scrollBar->value();    if (m_scrollOffset == offset)        return;    int scrolledLines = m_scrollOffset - offset;    m_scrollOffset = offset;    UINT flags = SW_INVALIDATE;#ifdef CAN_SET_SMOOTH_SCROLLING_DURATION    BOOL shouldSmoothScroll = FALSE;    ::SystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &shouldSmoothScroll, 0);    if (shouldSmoothScroll)        flags |= MAKEWORD(SW_SMOOTHSCROLL, smoothScrollAnimationDuration);#endif    IntRect listRect = clientRect();    if (m_scrollbar)        listRect.setWidth(listRect.width() - m_scrollbar->frameRect().width());    RECT r = listRect;    ::ScrollWindowEx(m_popup, 0, scrolledLines * m_itemHeight, &r, 0, 0, 0, flags);    if (m_scrollbar) {        r = m_scrollbar->frameRect();        ::InvalidateRect(m_popup, &r, TRUE);    }    ::UpdateWindow(m_popup);}void PopupMenu::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect){    IntRect scrollRect = rect;    scrollRect.move(scrollbar->x(), scrollbar->y());    RECT r = scrollRect;    ::InvalidateRect(m_popup, &r, false);}static ATOM registerPopup(){    static bool haveRegisteredWindowClass = false;    if (haveRegisteredWindowClass)        return true;    WNDCLASSEX wcex;    wcex.cbSize = sizeof(WNDCLASSEX);    wcex.style          = 0;    wcex.lpfnWndProc    = PopupWndProc;    wcex.cbClsExtra     = 0;    wcex.cbWndExtra     = sizeof(PopupMenu*); // For the PopupMenu pointer    wcex.hInstance      = Page::instanceHandle();    wcex.hIcon          = 0;    wcex.hCursor        = LoadCursor(0, IDC_ARROW);    wcex.hbrBackground  = 0;    wcex.lpszMenuName   = 0;    wcex.lpszClassName  = kPopupWindowClassName;    wcex.hIconSm        = 0;    haveRegisteredWindowClass = true;    return ::RegisterClassEx(&wcex);}const int smoothScrollAnimationDuration = 5000;static LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    LRESULT lResult = 0;    LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);    PopupMenu* popup = reinterpret_cast<PopupMenu*>(longPtr);    switch (message) {        case WM_SIZE:            if (popup && popup->scrollbar()) {                IntSize size(LOWORD(lParam), HIWORD(lParam));                popup->scrollbar()->setFrameRect(IntRect(size.width() - popup->scrollbar()->width(), 0, popup->scrollbar()->width(), size.height()));                int visibleItems = popup->visibleItems();                popup->scrollbar()->setEnabled(visibleItems < popup->client()->listSize());                popup->scrollbar()->setSteps(1, max(1, visibleItems - 1));                popup->scrollbar()->setProportion(visibleItems, popup->client()->listSize());            }            break;        case WM_ACTIVATE:            if (popup && popup->client() && wParam == WA_INACTIVE)                popup->client()->hidePopup();            break;        case WM_KILLFOCUS:            if (popup && popup->client() && (HWND)wParam != popup->popupHandle())                // Focus is going elsewhere, so hide                popup->client()->hidePopup();            break;        case WM_KEYDOWN:            if (popup && popup->client()) {                lResult = 0;                switch (LOWORD(wParam)) {                    case VK_DOWN:                    case VK_RIGHT:                        popup->down();                        break;                    case VK_UP:                    case VK_LEFT:                        popup->up();                        break;                    case VK_HOME:                        popup->focusFirst();                        break;                    case VK_END:                        popup->focusLast();                        break;                    case VK_PRIOR:                        if (popup->focusedIndex() != popup->scrollOffset()) {                            // Set the selection to the first visible item                            int firstVisibleItem = popup->scrollOffset();                            popup->up(popup->focusedIndex() - firstVisibleItem);                        } else                            // The first visible item is selected, so move the selection back one page                            popup->up(popup->visibleItems());                        break;                    case VK_NEXT:                        if (popup) {                            int lastVisibleItem = popup->scrollOffset() + popup->visibleItems() - 1;                            if (popup->focusedIndex() != lastVisibleItem) {                                // Set the selection to the last visible item                                popup->down(lastVisibleItem - popup->focusedIndex());                            } else                                // The last visible item is selected, so move the selection forward one page                                popup->down(popup->visibleItems());                        }                        break;                    case VK_TAB:                        ::SendMessage(popup->client()->hostWindow()->platformWindow(), message, wParam, lParam);                        popup->client()->hidePopup();                        break;                    default:                        if (isASCIIPrintable(wParam))                            // Send the keydown to the WebView so it can be used for type-to-select.                            ::PostMessage(popup->client()->hostWindow()->platformWindow(), message, wParam, lParam);                        else                            lResult = 1;                        break;                }            }            break;        case WM_CHAR:            if (popup && popup->client()) {                lResult = 0;                int index;                switch (wParam) {                    case 0x0D:   // Enter/Return                        popup->client()->hidePopup();                        index = popup->focusedIndex();                        ASSERT(index >= 0);                        popup->client()->valueChanged(index);                        break;                    case 0x1B:   // Escape                        popup->client()->hidePopup();                        break;                    case 0x09:   // TAB                    case 0x08:   // Backspace                    case 0x0A:   // Linefeed                    default:     // Character                        lResult = 1;                        break;                }            }            break;        case WM_MOUSEMOVE:            if (popup) {                IntPoint mousePoint(MAKEPOINTS(lParam));                if (popup->scrollbar()) {                    IntRect scrollBarRect = popup->scrollbar()->frameRect();                    if (popup->scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) {                        // Put the point into coordinates relative to the scroll bar                        mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());                        PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));                        popup->scrollbar()->mouseMoved(event);                        break;                    }                }                BOOL shouldHotTrack = FALSE;                ::SystemParametersInfo(SPI_GETHOTTRACKING, 0, &shouldHotTrack, 0);                RECT bounds;                GetClientRect(popup->popupHandle(), &bounds);                if ((shouldHotTrack || wParam & MK_LBUTTON) && ::PtInRect(&bounds, mousePoint))                    popup->setFocusedIndex(popup->listIndexAtPoint(mousePoint), true);                // Release capture if the left button isn't down, and the mousePoint is outside the popup window.                // This way, the WebView will get future mouse events in the rest of the window.                if (!(wParam & MK_LBUTTON) && !::PtInRect(&bounds, mousePoint)) {                    ::ReleaseCapture();                    break;                }            }            break;        case WM_LBUTTONDOWN:            if (popup) {                ::SetCapture(popup->popupHandle());                IntPoint mousePoint(MAKEPOINTS(lParam));                if (popup->scrollbar()) {                    IntRect scrollBarRect = popup->scrollbar()->frameRect();                    if (scrollBarRect.contains(mousePoint)) {                        // Put the point into coordinates relative to the scroll bar                        mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());                        PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));                        popup->scrollbar()->mouseDown(event);                        popup->setScrollbarCapturingMouse(true);                        break;                    }                }                popup->setFocusedIndex(popup->listIndexAtPoint(mousePoint), true);            }            break;        case WM_LBUTTONUP:            if (popup) {                IntPoint mousePoint(MAKEPOINTS(lParam));                if (popup->scrollbar()) {                    ::ReleaseCapture();                    IntRect scrollBarRect = popup->scrollbar()->frameRect();                    if (popup->scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) {                        popup->setScrollbarCapturingMouse(false);                        // Put the point into coordinates relative to the scroll bar                        mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());                        PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));                        popup->scrollbar()->mouseUp();                        // FIXME: This is a hack to work around Scrollbar not invalidating correctly when it doesn't have a parent widget                        RECT r = scrollBarRect;                        ::InvalidateRect(popup->popupHandle(), &r, TRUE);                        break;                    }                }                // Only release capture and hide the popup if the mouse is inside the popup window.                RECT bounds;                GetClientRect(popup->popupHandle(), &bounds);                if (popup->client() && ::PtInRect(&bounds, mousePoint)) {                    ::ReleaseCapture();                    popup->client()->hidePopup();                    int index = popup->focusedIndex();                    if (index >= 0)                        popup->client()->valueChanged(index);                }            }            break;        case WM_MOUSEWHEEL:            if (popup && popup->scrollbar()) {                int i = 0;                for (popup->incrementWheelDelta(GET_WHEEL_DELTA_WPARAM(wParam)); abs(popup->wheelDelta()) >= WHEEL_DELTA; popup->reduceWheelDelta(WHEEL_DELTA))                    if (popup->wheelDelta() > 0)                        ++i;                    else                        --i;                popup->scrollbar()->scroll(i > 0 ? ScrollUp : ScrollDown, ScrollByLine, abs(i));            }            break;        case WM_PAINT:            if (popup) {                PAINTSTRUCT paintInfo;                ::BeginPaint(popup->popupHandle(), &paintInfo);                popup->paint(paintInfo.rcPaint, paintInfo.hdc);                ::EndPaint(popup->popupHandle(), &paintInfo);                lResult = 0;            }            break;        case WM_PRINTCLIENT:            if (popup)                popup->paint(popup->clientRect(), (HDC)wParam);            break;        default:            lResult = DefWindowProc(hWnd, message, wParam, lParam);    }    return lResult;}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -