Winapi 当我滚动窗口时,工具栏会滚动

Winapi 当我滚动窗口时,工具栏会滚动,winapi,scrollbar,toolbar,Winapi,Scrollbar,Toolbar,我正在编写win32程序,我有一个带有滚动条的窗口,现在我添加了一个工具栏。 我的问题是,当我滚动窗口时,工具栏是滚动的。 如何将工具栏设置为位于其位置,例如菜单 这是一个显示滚动窗口时工具栏如何滚动的代码示例,该代码并不完美,但它显示了向上或向下滚动窗口时工具栏如何滚动: #include <windows.h> #include <stdlib.h> #include <CommCtrl.h> #pragma comment(lib, "comctl32

我正在编写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);
    }
}
#包括
#包括
#包括
#pragma注释(lib,“comctl32.lib”)
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
举个例子;
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、LPSTR lpCmdLine、int nCmdShow)
{
实例=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_应用程序));
wcex.hCursor=LoadCursor(空,IDC_箭头);
wcex.hbrBackground=(HBRUSH)(彩色窗口+1);
wcex.lpszMenuName=NULL;
wcex.lpszClassName=L“示例”;
wcex.hIconSm=LoadIcon(wcex.hInstance,MAKEINTRESOURCE(IDI_应用程序));
注册类别(&wcex);
HWND HWND=CreateWindow(L“示例”,L“”,WS_重叠窗口,CW_使用默认值,CW_使用默认值,
500,500,NULL,NULL,hInstance,NULL);
显示窗口(hWnd、nCmdShow);
味精;
while(GetMessage(&msg,NULL,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回(int)msg.wParam;
}
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
开关(信息)
{
案例WM_创建:
{
//创建工具栏
HWND hWndToolbar=CreateWindowEx(0,TOOLBARCLASSNAME,NULL,WS|u CHILD | TBSTYLE|u工具提示,
0,0,0,0,hWnd,(HMENU)0,实例,NULL);
HIMAGELIST HIMAGELIST=ImageList_Create(16,16,ILC_COLOR16 | ILC_MASK,3,0);
SendMessage(hWndToolbar,TB_SETIMAGELIST,(WPARAM)0,(LPARAM)hImageList);
SendMessage(hWndToolbar,TB_按钮结构大小,(WPARAM)sizeof(TBBUTTON),0);
tbb按钮tbb[4]=
{
{0,0,TBSTATE_已启用,TBSTYLE_按钮,},
{1,1,TBSTATE_已启用,TBSTYLE_按钮,},
{2,2,TBSTATE_已启用,TBSTYLE_按钮,},
{0,0,TBSTATE_已启用,BTN_SEP}
};
发送消息(hWndToolbar,(UINT)TB_添加按钮,4,(LPRAM)和tbb);
SendMessage(hWndToolbar,TB_AUTOSIZE,0,0);
显示窗口(hWndToolbar,SW_SHOW);
//滚动条
滚动信息si;
si.cbSize=sizeof(SCROLLINFO);
si.fMask=SIF_ALL;
si.nMax=1000;
si.nMin=0;
si.nPos=0;
si.nPage=500;
SetScrolInfo(hWnd、SBS_VERT和si、TRUE);
}
打破
案例WM_VSCROLL:
开关(LOWORD(wParam))
{
案例SB_系列:
滚动窗口(hWnd,0,-20,NULL,NULL);
打破
案例SB_阵容:
滚动窗口(hWnd,0,20,NULL,NULL);
打破
}
返回0;
违约:
返回DefWindowProc(hWnd、message、wParam、lParam);
}
}

有几个选项可以尝试

如果使用WS_CLIPCHILDREN创建主机窗口,ScrollWindow()可能会忽略子窗口(包括工具栏)占据的区域。我不是100%确定是这种情况,尽管我已经在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);

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

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


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

前两个解决方案不起作用。第三种解决方案是可行的,而且很有帮助,但看起来有点尴尬,我相信有某种方法可以使工具栏不完全包含在父窗口的客户端区域中,就像菜单不包含在父窗口的客户端区域中,并且不随父窗口滚动一样。--也许我应该设置工具栏的父窗口是菜单?菜单在非客户端区域。如果您添加了一个状态栏,它也会被放置在客户端区域,那么您也会遇到同样的问题。我想有一种方法可以在客户端区域之外创建工具栏,就像在Word Microsoft中一样。