2013-05-16 3 views
2

Я пишу программу win32, и у меня есть окно со строкой прокрутки, и теперь я добавил панель инструментов. Моя проблема в том, что панель инструментов - это свитки при прокрутке окна. Как настроить панель инструментов на свое место, например меню?Прокрутка панели инструментов при прокрутке окна

Это пример кода, который показывает, как панель инструментов прокручивается при прокрутке окна, код не является совершенным, но он показывает, как панель прокрутки, когда вы sroll окно линии вверх или линии вниз:

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

ответ

1

Большинство библиотек классов C++ делает это, создавая окно кадра . Внешнее окно - это главное окно приложения. И создает отдельные окна для отображения содержимого. Эти окна просмотра - это те, которые имеют полосу прокрутки. Даже кроткий Notepad использует эту технику:

enter image description here

Обратите внимание, как в строке состояния в нижней части является его собственный ребенок окно фрейма окна и не получает прокручивается при использовании полосы прокрутки в редактирования ребенка окно. Меню отличается, однако, это в неклиентской области окна кадра. Очень характерен для традиционных меню. Вы можете использовать утилиту Spy ++ для поиска в других приложениях, чтобы увидеть, как они организовали свои окна.

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

Ваши первые два решения не работают. Третье решение работает и полезно, но это выглядело немного неудобно, я считаю, что есть способ сделать панель инструментов не полностью включенной в клиентскую область родительского окна, так же, как меню, которое не включено в родительское окно клиентской области и не прокручивать с родительским окном. --- Может быть, мне нужно установить родительское окно панели инструментов в меню? – user1544067

+0

Меню находятся в неклиентской области. У вас будет такая же проблема, если вы добавите строку состояния, которая также будет размещена в клиентской области. – CoreyStup

+0

Я предполагаю, что есть способ создать панель инструментов вне клиентской области, так как она находится в Word Microsoft и т. Д. – user1544067

0

Добавить еще один уровень в иерархии окон, так что полосы прокрутки и области они прокрутки в дочернем окне, расположенной под панелью инструментов.

Смежные вопросы