滚动窗口时,工具栏会滚动

时间:2013-05-16 08:22:57

标签: winapi scrollbar toolbar

我正在编写win32程序,我有一个带滚动条的窗口,现在我添加了一个工具栏。 我的问题是,当我滚动窗口时,工具栏会滚动。 如何将工具栏设置为站在他的位置,例如菜单?

这是一个代码示例,显示滚动窗口时工具栏的滚动方式,代码并不完美,但它显示了当您将窗口向上滚动或向下滚动时滚动工具栏的方式:

#include <windows.h> 
#include <stdlib.h>
#include <CommCtrl.h>
#pragma comment(lib, "comctl32.lib")

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE instance;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    instance = hInstance;

    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style           = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc    = WndProc; 
    wcex.cbClsExtra     = 0; 
    wcex.cbWndExtra     = 0;  
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));  
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1); 
    wcex.lpszMenuName   = NULL; 
    wcex.lpszClassName  = L"Example";  
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

    RegisterClassEx(&wcex);

    HWND hWnd = CreateWindow(L"Example", L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        500, 500, NULL, NULL, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);  
        DispatchMessage(&msg); 
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE: 
        {
            // create toolbar
            HWND hWndToolbar = CreateWindowEx(0 , TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_TOOLTIPS,
                0, 0, 0, 0, hWnd, (HMENU)0, instance, NULL);

            HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, 3, 0);

            SendMessage(hWndToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList);
            SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);

            TBBUTTON tbb[4] = 
            {
                {0,0,TBSTATE_ENABLED,TBSTYLE_BUTTON,},
                {1,1,TBSTATE_ENABLED,TBSTYLE_BUTTON,},
                {2,2,TBSTATE_ENABLED,TBSTYLE_BUTTON,},
                {0,0,TBSTATE_ENABLED,BTNS_SEP} 
            };

            SendMessage(hWndToolbar, (UINT) TB_ADDBUTTONS, 4, (LPARAM)&tbb);

            SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
            ShowWindow(hWndToolbar , SW_SHOW);

            // scrollbar
            SCROLLINFO si;
            si.cbSize = sizeof(SCROLLINFO);
            si.fMask = SIF_ALL;
            si.nMax = 1000;
            si.nMin = 0;
            si.nPos = 0;
            si.nPage = 500; 
            SetScrollInfo(hWnd, SBS_VERT, &si, TRUE);
        }
    break;

 case WM_VSCROLL:
        switch(LOWORD(wParam))
        {
        case SB_LINEDOWN:
                ScrollWindow(hWnd, 0, -20, NULL, NULL);
            break;

        case SB_LINEUP:
                ScrollWindow(hWnd, 0, 20, NULL, NULL);
            break;
        }
    return 0;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
}

3 个答案:

答案 0 :(得分:1)

大多数C ++类库都是通过创建框架窗口来实现的。外部窗口是应用程序的主窗口。并创建单独的视图窗口以显示内容。那些视图窗口是具有滚动条的窗口。即便是低记事本也使用这种技术:

enter image description here

请注意底部的状态栏是框架窗口的子窗口,当您在编辑子窗口中使用滚动条时,它不会滚动。然而,菜单是不同的,它位于框架窗口的非客户区域中。非常特定于传统菜单。您可以使用Spy ++实用程序在其他应用程序中查看它们如何组织窗口。

答案 1 :(得分:0)

有几种选择可供尝试。

如果使用WS_CLIPCHILDREN创建主机窗口,ScrollWindow()可能会忽略子窗口(包括工具栏)占用的区域。虽然我已经在与SW_SCROLLCHILDREN的各种组合中使用ScrollWindowEx()来解决子窗口滚动问题,但我并非100%确定是这种情况。

现有代码的另一个选项是从您要请求滚动的区域中排除工具栏占用的区域。而不是传递NULL,传递客户端矩形,扣除工具栏的大小。

这样的事情:

RECT toolRect;
GetClientRect(hWndToolbar, &toolRect);
RECT clientRect;
GetClientRect(hWnd, &clientRect);
// Adjust clientrect by the height of the toolbar
clientRect.top += toolRect.bottom;
// Scroll the region of our client area minus the toolbar at the top
ScrollWindow(hWnd, 0, 20, &clientRect, NULL);

答案 2 :(得分:0)

向窗口层次结构中添加另一个级别,以便滚动条和它们滚动的区域位于工具栏下方的子窗口中。