EnderMo233 Ответов: 1

Win32 как создать элемент управления боковой вкладкой?


Я только что научился рисовать пользовательский интерфейс в течение нескольких месяцев. Теперь у меня есть проблема. Мы можем реализовать верхнюю вкладку с помощью owner draw TabControl, но с точки зрения пользовательского интерфейса это не то, что мне нужно
То, что я хочу, - это боковая вкладка типа, показанного на следующем рисунке [приложение настроек windows 10]. Нажмите кнопку и выполните соответствующую обработку сообщения
изображение↓
Видовое изображение
пожалуйста, сделайте это с WIN32 и без MFC
Does anyone can tell me how to create sidetab like the picture?

спасибо.

Что я уже пробовал:

Я устал использовать для этого кнопку ownerdraw,но она не может щелкнуть, чтобы переключить интерфейс,
Хотите, откройте редактор реестра, искать использовать этот стиль ownerdraw
<pre>HWND g_bt1;
HWND g_bt2;
WNDPROC BToldProc;

typedef struct tagBTN
{// 
    HWND hWnd;          // handle of owner window
    BOOL x1; //默认是185
    BOOL x2; //默认是170
    LPWSTR in;
    UINT style;
} BTN_PARAM;
//
//
LRESULT CALLBACK BTProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{// 
    PAINTSTRUCT ps;
    HDC hdc = NULL;
    RECT rc;
    GetClientRect(hWnd, &rc);
    LOGFONT lf;
    HFONT hFont = 0;
    HBRUSH br;
    TCHAR txt[40];
    switch (Msg)
    {//
    case WM_PAINT:
    {
        hdc = BeginPaint(hWnd, &ps);
        br = CreateSolidBrush(RGB(7, 130, 215));
        FillRect(hdc, &rc, br);
        GetWindowText(hWnd, txt, 40);
        SetBkMode(hdc, TRANSPARENT);
        if (hFont == 0)
        {
            memset(&lf, 0, sizeof(LOGFONT));
            lf.lfHeight = -16;
            wcscpy(lf.lfFaceName, L"黑体");
            hFont = CreateFontIndirect(&lf);  // create the font
        }
        HFONT old = (HFONT)SelectObject(hdc, hFont);
        TextOut(hdc, 18, 7, txt, wcslen(txt) /*&ps.rcPaint*//*DT_SINGLELINE | DT_CENTER | DT_VCENTER*/);
        //DrawText(hdc, txt, wcslen(txt), &ps.rcPaint, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        ReleaseDC(hWnd, hdc);
        UpdateWindow(hWnd);
        DeleteObject(br);
        EndPaint(hWnd, &ps);
        break;
    }
    case WM_MOUSEMOVE:
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(tme);
        tme.dwFlags = TME_HOVER | TME_LEAVE;
        tme.dwHoverTime = 1;
        tme.hwndTrack = hWnd;
        BOOL boRet = _TrackMouseEvent(&tme);
    }break;
    case WM_MOUSELEAVE:
    {
        
        PAINTSTRUCT ps1;
        HBRUSH hbr = NULL;
        hdc = GetDC(hWnd);
        hbr = CreateSolidBrush(RGB(0,255,191));
        SelectObject(hdc, hbr);
        FillRect(hdc, &rc, hbr);
        //SetWindowText(hWnd, L"关闭");
        ReleaseDC(hWnd, hdc);
        DeleteObject(hbr);
        OutputDebugStringA("Leave\n");
        break;
    }
    case WM_MOUSEHOVER:
    {
        HBRUSH hbr = NULL;
        hdc = GetDC(hWnd);
        hbr = CreateSolidBrush(RGB(99, 184, 255));
        SelectObject(hdc, hbr);
        FillRect(hdc, &rc, hbr);
        GetWindowText(hWnd, txt, 40);
        SetBkMode(hdc, TRANSPARENT);
        if (hFont == 0)
        {
            memset(&lf, 0, sizeof(LOGFONT));
            lf.lfHeight = -16;
            wcscpy(lf.lfFaceName, L"黑体");
            hFont = CreateFontIndirect(&lf);  // create the font
        }
        HFONT old = (HFONT)SelectObject(hdc, hFont);
        TextOut(hdc, 18, 7, txt, wcslen(txt) /*&ps.rcPaint*//*DT_SINGLELINE | DT_CENTER | DT_VCENTER*/);
        //SetWindowText(hWnd, L"关闭");
        ReleaseDC(hWnd, hdc);
        //SetWindowText(hWnd, L"[关闭]");
        DeleteObject(hbr);
        OutputDebugStringA("Over\n");
        break;
    }
    }
    //
    return CallWindowProc(BToldProc, hWnd, Msg, wParam, lParam);
}
//________________HWND 主窗口,__x1 x坐标,__x2 y坐标,L"按钮文字",从定义获取控件
//如果需要进行消息处理,case IDC_XX:
int Button(
    HWND hWnd,         // handle of owner window
    BOOL x1,
    BOOL x2,
    LPWSTR in,
    UINT style //从定义获取按钮控件依赖
)
{
    static HFONT hFont;
    BTN_PARAM btn;
    btn.hWnd = hWnd;
    btn.style = style;
    g_bt1 = CreateWindow(L"Button", in, WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,//默认按钮样式
        x1, x2, 180, 60, hWnd, (HMENU)style, b_hInstance, NULL);
    BToldProc = (WNDPROC)SetWindowLong(g_bt1, GWL_WNDPROC, (LONG)BTProc);
    return -1;
}


использовать
#определение теста 0xcc1
Кнопка(hwnd,x,y,"текст",тест);
кейс-тест:
{}
чтобы использовать кнопку

But this is not the normal way


Кто-нибудь может сказать мне, как создать sidetab, как на картинке?

1 Ответов

Рейтинг:
11

Richard MacCutchan

Вам нужно создать два дочерних окна в клиентском пространстве. Тот, что слева, - это ваша вкладка, а тот, что справа, - ваше основное пространство обработки. Обработайте сообщение WM_SIZE в вашем WndProc и измените размер двух дочерних окон на основе клиентского пространства и относительных размеров, которые вы хотите.

[редактировать]
Пример обработчика WM_SIZE:

void OnSize(
    HWND	hWnd,
    UINT	nAction,
    int	nWidth,
    int	nHeight
)
{
    POINT  ptTopLeft = { 0, 0 };
    int    nTabWidth = nWidth / 3; // tab is 1/3 of main window width
    
    // resize the views
    MoveWindow(hTabWindow,
        ptTopLeft.x,	// starting x-coordinate
        ptTopLeft.y,	// starting y-coordinate
        nTabWidth,	// width of left client area 
        nHeight,	// height of client area 
        TRUE		// repaint window 
    );
    ptTopLeft.x += nTabWidth;	// becomes left edge of right view
    nWidth -= ptTopLeft.x;	// width of right-hand view
    
    MoveWindow(hEditWindow,
        ptTopLeft.x,
        ptTopLeft.y,
        nWidth,
        nHeight,
        TRUE
    );
}

[/редактировать]


EnderMo233

Теперь мой пользовательский интерфейс выглядит следующим образом

http://db.endermo.xyz/lnk/UI.png

Каждый элемент управления является дочерним окном hwnd

LargeTitlebtn(hwnd, 1, 1, 160, 50, L"Title", NULL);
FrameClose(hwnd, rect.right - 20, 16, CLOSE);
FrameMinimize(hwnd, rect.right - 60, 16,IDC_MINIMIZE);
FrameMenuBox(hwnd, rect.right - 100, 16, IDC_MENUBOX);
ConsoleUI(hwnd, rect.слева + 161, 51, 669,459, ноль);

Я хочу, чтобы добавить откройте редактор реестра, искать в левой(уголок DarkGrey )
Должен ли я сделать вкладку в дочернем окне?Как переключить интерфейс при переключении вкладки?

Richard MacCutchan

Вы не должны использовать фиксированные размеры для ваших окон. Если пользователь изменит размер главного окна, то дочерние окна будут выглядеть неправильно. Вам нужно установить размеры и положения дочерних окон в обработчике WM_SIZE. Используйте значение width для расчета ширины и положения дочерних окон, а также высоты, чтобы убедиться, что они правильно вписываются в рамку. Это обеспечит правильный размер и положение при каждом изменении размера главного окна. Смотрите мое решение обновления для простого примера двух дочерних окон, где левая сторона должна быть одной третью ширины:

EnderMo233

Мое окно - это саморисовывающееся окно без полей и отключенное изменение размера.
Я использовал приведенный выше код, чтобы сделать подокно, но как переключить интерфейс, когда пользователь нажимает разные кнопки вкладок
Например, по умолчанию "console UI" - это самый интерфейс, а вкладка "console UI" - это "консоль". Если я хочу создать кнопку новый "столбец testtab", мне нужно, чтобы скрыть "интерфейс консоли" окно и отобразить новое окно, когда я щелкните по нему

Richard MacCutchan

Вы можете создать другие дочерние окна той же формы и размера в вашем framewindow. Затем вы можете использовать Функцию setwindowpos (winuser.ч) - Win32-приложений, Майкрософт документы[^] чтобы вывести их на вершину (то есть сделать их видимыми).

EnderMo233

Я, кажется, не использовал setwindowpos
Поскольку я добавил вкладку "В", каждая кнопка представляет собой подокно. Если я хочу скрыть подокно "console UI", когда я нажимаю кнопку "testtab", то невозможно скрыть подокно "console UI", когда я нажимаю кнопку "testtab", потому что у них был другой hwnd. Как я могу скрыть дочернее окно "console UI" и отобразить другое, когда я нажимаю кнопку "testtab"?
спасибо.

Richard MacCutchan

вы можете спрятался и шоу любого окна с помощью функции showwindow, setwindowpos и т. д. Взгляните на это EFNet #Winprog[^] что очень подробно объясняет Программирование Win32.

EnderMo233

как я могу задать вопрос в EFNet?

Richard MacCutchan

Без понятия, вам придется заглянуть на сайт.