2

我正在编写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);
    }
}
4

3 回答 3

1

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

在此处输入图像描述

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

于 2013-05-20T13:39:52.577 回答
0

有几个选择可以尝试。

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

您现有代码的另一个选项是从您请求滚动的区域中排除工具栏占用的区域。不要传递 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);
于 2013-05-17T21:51:53.267 回答
0

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

于 2013-05-20T13:04:52.660 回答