硬汉嵌入式论坛

 找回密码
 立即注册
查看: 327|回复: 8
收起左侧

[emWin] 左右滑动 button动态切换显示

[复制链接]

3

主题

7

回帖

16

积分

新手上路

积分
16
发表于 2025-3-17 16:18:32 | 显示全部楼层 |阅读模式
1.我想创建多个button。然后屏幕显示3个button,然后左滑或者右滑会切换一个button,然后5个button按顺序循环显示。

2.目前是对话框创建了一个窗口合集,内含5个button。是一起显示出来。



static const GUI_WIDGET_CREATE_INFO _aDialogCreate_Home[] = {
    { WINDOW_CreateIndirect, "Framewin", ID_WINDOW_MODE_HOME, 0,  0, 560,170, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_BT", ID_BUTTON_BT, BUTTON_BT_INIT_X, BUTTON_BT_INIT_Y, 56,56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_Charging", ID_BUTTON_CHARGING, BUTTON_CHARGING_INIT_X, BUTTON_CHARGING_INIT_Y, 56,56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_VolDe", ID_BUTTON_VOL_DE, BUTTON_VOL_DE_INIT_X, BUTTON_VOL_DE_INIT_Y, 56,56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_VolIn", ID_BUTTON_VOL_IN, BUTTON_VOL_IN_INIT_X, BUTTON_VOL_IN_INIT_Y, 56,56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_VolLED", ID_BUTTON_LED, BUTTON_LED_INIT_X, BUTTON_LED_INIT_Y, 56,56, 0, 0x0, 0 },
};



3.有没有什么办法能动态创建button     或者一起创建5个,根据窗口左右滑动然后动态显示3个
回复

使用道具 举报

8

主题

51

回帖

75

积分

初级会员

积分
75
发表于 2025-3-17 19:23:01 | 显示全部楼层
1. 看看我发过的帖子: emwin 动态软键盘,你可以借鉴一下。

2.还有很多方法的。



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2025-3-18 09:05:52 | 显示全部楼层
可以创建一个大窗口,可以覆盖3-4个显示屏范围。然后通过WM MoveTo函数移动创建即可。
回复

使用道具 举报

3

主题

7

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-3-18 16:04:33 | 显示全部楼层
eric2013 发表于 2025-3-18 09:05
可以创建一个大窗口,可以覆盖3-4个显示屏范围。然后通过WM MoveTo函数移动创建即可。

你的意思是说,
1.创建一个非常大的窗口,20x100(容纳5个按钮)
2.在窗口创建所有按钮,但是是在显示的区域(屏幕显示区域20x50)只显示对应数量(比如3个)的按钮
3.通过窗口移动,来显示对应的窗口区域,进而显示对应区域的按钮。超过物理屏幕显示的区域,就不显示
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2025-3-19 06:14:34 | 显示全部楼层
hsw1234 发表于 2025-3-18 16:04
你的意思是说,
1.创建一个非常大的窗口,20x100(容纳5个按钮)
2.在窗口创建所有按钮,但是是在显示 ...

对,是这样。
回复

使用道具 举报

3

主题

7

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-3-20 14:43:07 | 显示全部楼层

我试了试了方法,初步已经实现了切换,唯一的难点,或者说比较烦的地方就是要自己做一个位置换算表,然后去切换窗口位置。

我在考虑另一种方法,利用dialog创建一个带有两个左右按键的窗口,然后中间的5个按钮,利用BUTTON_CreateEx(),去动态创建,利用L和R按键去切换中间5个button
也是要写一个ID的table,这个目前已经实现了,但是有个问题,我点击按BUTTON_CreateEx()创建的按钮,发现无法触发WM_NOTIFICATION_CLICKED和WM_NOTIFICATION_RELEASED消息。点击后没啥反应,但是dialog一起创建的按钮,就可以触发一些反馈。



/* 资源表 */
static const GUI_WIDGET_CREATE_INFO _aDialogCreate_Home[] = {
    { WINDOW_CreateIndirect, "Framewin", ID_WINDOW_MODE_HOME, 0,  0, 560, 170, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "L", ID_BUTTON_LEFT, 0, 57, 20, 56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "R", ID_BUTTON_RIGHT, 540, 57,20, 56, 0, 0x0, 0 },
};


void hsw_update_button_mode(void)
{
    U16 button_ID_set_arr[5] = {0};
    int new_index = 0;
    U8 i = 0;

    new_index = current_button_mode;

    for (i = 0; i < 5; i++)
    {
        button_ID_set_arr = new_index;
        new_index++;
        if (new_index >= BUTTON_MAX_MODE)
            new_index = 0;
    }

    WM_DeleteWindow(hButton0_0);
    WM_DeleteWindow(hButton0_1);
    WM_DeleteWindow(hButton0_2);
    WM_DeleteWindow(hButton0_3);
    WM_DeleteWindow(hButton0_4);


    hButton0_0 = BUTTON_CreateEx(BUTTON_BT_INIT_X, BUTTON_BT_INIT_Y, 56, 56, 0, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[0]]);
    hButton0_1 = BUTTON_CreateEx(BUTTON_CHARGING_INIT_X, BUTTON_CHARGING_INIT_Y, 56, 56, 0, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[1]]);
    hButton0_2 = BUTTON_CreateEx(BUTTON_VOL_DE_INIT_X, BUTTON_VOL_DE_INIT_Y, 56, 56, 0, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[2]]);
    hButton0_3 = BUTTON_CreateEx(BUTTON_VOL_IN_INIT_X, BUTTON_VOL_IN_INIT_Y, 56, 56, 0, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[3]]);
    hButton0_4 = BUTTON_CreateEx(BUTTON_LED_INIT_X, BUTTON_LED_INIT_Y, 56, 56, 0, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[4]]);


    BUTTON_SetText(hButton0_0, button_name_table[button_ID_set_arr[0]]);
    BUTTON_SetText(hButton0_1, button_name_table[button_ID_set_arr[1]]);
    BUTTON_SetText(hButton0_2, button_name_table[button_ID_set_arr[2]]);
    BUTTON_SetText(hButton0_3, button_name_table[button_ID_set_arr[3]]);
    BUTTON_SetText(hButton0_4, button_name_table[button_ID_set_arr[4]]);
}


是对话框创建的窗口和后续动态添加的按钮控件,一些消息机制不能同步吗?


回复

使用道具 举报

3

主题

7

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-3-20 14:48:30 | 显示全部楼层

这个是模拟的效果,本来想穿个短视频,不过好像不支持MP4格式
控件.png
回复

使用道具 举报

3

主题

7

回帖

16

积分

新手上路

积分
16
 楼主| 发表于 2025-3-20 17:04:01 | 显示全部楼层

前面提到的BUTTON_CreateEx创建的button控件无法和dialog窗口一起绑定,button点击的消息无法通知到_cbDialog_Home的情况已经解决了。还是创建的时候没有将button控件绑定父窗口的原因。不过很奇怪,我用WM_HWIN 的全局变量保存了CreateFramewin()返回的句柄。
然后在while中利用hsw_switch_button_mode()更新按钮的时候直接通过这个全局变量去创建,还是无法绑定,但是我把hsw_switch_button_mode放在 _cbDialog_Home()中去操作。给hsw_switch_button_mode()加了传递参数的能力,然后成功了。

不知道为什么,其中的机制还是不太清晰

另附上源码。仅供参考。
功能,这是实现了动态创建按钮。通过左右两个小按钮来切换,并点击音量+-按钮会切换到新的界面,无返回按钮。
唯一遗憾的是对motion还不太懂,如果能去掉左右两个button,通过检测motion来切换那就更好了。不过到时候滑起来不知道会不会一卡一卡的。

另外,这是vs2019模拟测试方案可行性的例程,中间有大量的无用变量。很多函数放置也很随意,请见谅



#include "GUI.h"
#include "DIALOG_Type.h"
#include "FRAMEWIN.h"
#include "BUTTON.h"
#include "DIALOG.h"
#include "WM.h"
#include <stdio.h>
#include <stdlib.h>

//#include "../FatFS/source/ff.h"

/****************************************************************
*
* 通过创建两组0~5的按钮,放置在170*560 窗口区域
* 同时左右创建两个小按钮,然后通过点击左右两个小按钮,动态创建button
*
*
*
*****************************************************************
*/


/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
//
// Recommended memory to run the sample with adequate performance
//
#define RECOMMENDED_MEMORY (1024L * 5)

int Click_button_flag = 0;
U8 current_button_mode = 0;
int i_count = 0;

int volume_num = 10;

WM_HWIN hsw_home_win;

/* 控件ID */
/*
BT---bluetooth
VOL_DE---volume dcrease
VOL_IN---volume increase
*/
#define ID_WINDOW_MODE_HOME (GUI_ID_USER + 0x00)

#define ID_BUTTON_LEFT (GUI_ID_USER+ 0x01)
#define ID_BUTTON_RIGHT (GUI_ID_USER+ 0x02)

#define ID_BUTTON_BT (GUI_ID_USER+ 0x03)
#define ID_BUTTON_CHARGING  (GUI_ID_USER+ 0x04)
#define ID_BUTTON_VOL_DE   (GUI_ID_USER+ 0x05)
#define ID_BUTTON_VOL_IN    (GUI_ID_USER+ 0x06)
#define ID_BUTTON_LED (GUI_ID_USER + 0x07)
#define ID_BUTTON_SETTING (GUI_ID_USER + 0x08)


#define ID_WINDOW_MODE_VOLUME (GUI_ID_USER + 0x10)
#define ID_WINDOW_MODE_VOLUME_DE (GUI_ID_USER + 0x11)
#define ID_WINDOW_MODE_VOLUME_IN (GUI_ID_USER + 0x12)

typedef enum {
    BUTTON_BT_MODE = 0,
    BUTTON_CHARGING_MODE,
    BUTTON_VOL_DE_MODE,
    BUTTON_VOL_IN_MODE,
    BUTTON_LED_MODE,
    BUTTON_SETTING_MODE,

    BUTTON_MAX_MODE,
}hsw_work_mode;

const U16 ID_Button_Table[BUTTON_MAX_MODE] = {
    ID_BUTTON_BT,
    ID_BUTTON_CHARGING,
    ID_BUTTON_VOL_DE,
    ID_BUTTON_VOL_IN,
    ID_BUTTON_LED,
    ID_BUTTON_SETTING,
};


const char *button_name_table[BUTTON_MAX_MODE] = {
    "B_BT",
    "B_CHARG",
    "B_VOL_DE",
    "B_VOL_IN",
    "B_LED",
    "B_SET",
};

U16 button_ID_set_arr[5] = { 0 };

// 按钮初始化的xy坐标
#define BUTTON_BT_INIT_X   46
#define BUTTON_BT_INIT_Y   57
#define BUTTON_CHARGING_INIT_X   (BUTTON_BT_INIT_X + 56+46)
#define BUTTON_CHARGING_INIT_Y   (BUTTON_BT_INIT_Y )
#define BUTTON_VOL_DE_INIT_X   (BUTTON_CHARGING_INIT_X + 56+46)
#define BUTTON_VOL_DE_INIT_Y   (BUTTON_CHARGING_INIT_Y)
#define BUTTON_VOL_IN_INIT_X   (BUTTON_VOL_DE_INIT_X + 56+46)
#define BUTTON_VOL_IN_INIT_Y   (BUTTON_VOL_DE_INIT_Y)
#define BUTTON_LED_INIT_X   (BUTTON_VOL_IN_INIT_X + 56+46)
#define BUTTON_LED_INIT_Y   (BUTTON_VOL_IN_INIT_Y)


/*********************************************************************
*
*       Function Declaration
*
**********************************************************************
*/
static void _cbDialog_volume(WM_MESSAGE* pMsg);

void hsw_switch_button_mode(WM_HWIN button_pWin);

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/* 资源表 */
static  GUI_WIDGET_CREATE_INFO _aDialogCreate_Home[] = {
    { WINDOW_CreateIndirect, "Framewin", ID_WINDOW_MODE_HOME, 0,  0, 560, 170, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "L", ID_BUTTON_LEFT, 0, 57, 20, 56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "R", ID_BUTTON_RIGHT, 540, 57,20, 56, 0, 0x0, 0 },
};

static const GUI_WIDGET_CREATE_INFO _aDialogCreate_Volume[] = {
    { WINDOW_CreateIndirect, "Framewin", ID_WINDOW_MODE_VOLUME, 0,  0, 560, 170, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_DE", ID_WINDOW_MODE_VOLUME_DE, 47, 57, 56, 56, 0, 0x0, 0 },
    { BUTTON_CreateIndirect, "B_IN", ID_WINDOW_MODE_VOLUME_IN, 457, 57,56, 56, 0, 0x0, 0 },
};



static const GUI_COLOR _aColor[] = {
  GUI_BLUE,
  GUI_YELLOW,
  GUI_RED,
  GUI_GREEN
};


/**************************************************************************/

int BUTTON_DrawSkin(const WIDGET_ITEM_DRAW_INFO* pButtonSkinItem)
{
    int Id;
    Id = WM_GetId(pButtonSkinItem->hWin);

    switch (Id) {
    case ID_BUTTON_BT:
      
        break;

    default:
        return BUTTON_DrawSkinFlex(pButtonSkinItem);
        break;
    }
    return 0;
}


/**
* @brief 对话框回调函数
* @note 无
* @param pMsg:消息指针:消息指针
* @retval 无
*/
static void _cbDialog_Home(WM_MESSAGE* pMsg)
{

    WM_HWIN hItem;
    int NCode;
    int Id;

    hItem = pMsg->hWin;


    switch (pMsg->MsgId) {
        case WM_INIT_DIALOG:
            ///* 初始化Framewin控件 */
            //hItem = pMsg->hWin;
            //WINDOW_SetBkColor(hItem, 0x0000FFFF)
            break;

        case WM_NOTIFY_PARENT:
            Id = WM_GetId(pMsg->hWinSrc);
            NCode = pMsg->Data.v;
            switch (Id)
            {
                case ID_BUTTON_LEFT:
                     if (NCode == WM_NOTIFICATION_RELEASED)//按钮点击释放后
                    {//按钮按下被释放
                        Click_button_flag = 1; //左滑

                        hsw_switch_button_mode(hsw_home_win);
                    }
                    break;

                case ID_BUTTON_RIGHT:
                     if (NCode == WM_NOTIFICATION_RELEASED)
                    {//按钮按下被释放
                        Click_button_flag = 2; //右滑
                    }
                    break;

                case ID_BUTTON_VOL_DE:
                case ID_BUTTON_VOL_IN:
                    if (NCode == WM_NOTIFICATION_CLICKED)
                    {}
                    else if (NCode == WM_NOTIFICATION_RELEASED)
                    {
                        GUI_CreateDialogBox(_aDialogCreate_Volume, GUI_COUNTOF(_aDialogCreate_Volume), _cbDialog_volume, pMsg->hWin, 0, 0);
                    }
                    break;

                default:
                    break;

            }
            break;


    case WM_PAINT:
        GUI_Clear();
        GUI_SetBkColor(_aColor[i_count]);//改变整个窗口的背景颜色
        GUI_Clear();

        //GUI_SetFont(GUI_FONT_32B_ASCII);
        //GUI_SetColor(GUI_WHITE);
        //GUI_DispStringAt("GUI_DispFloat():", 0, 0);
        break;


    default:
        WM_DefaultProc(pMsg);
        break;
    }
}


static void _cbDialog_volume(WM_MESSAGE* pMsg)
{
    WM_HWIN hItem;
    int NCode;
    int Id;

    hItem = pMsg->hWin;

    switch (pMsg->MsgId) {
    case WM_INIT_DIALOG:
        ///* 初始化Framewin控件 */
        //hItem = pMsg->hWin;
        //WINDOW_SetBkColor(hItem, 0x0000FFFF)
        break;


    case WM_NOTIFY_PARENT:
        Id = WM_GetId(pMsg->hWinSrc);
        NCode = pMsg->Data.v;
        switch (Id)
        {

        case ID_WINDOW_MODE_VOLUME_DE:
            volume_num--;
            if (volume_num < 1)
                volume_num = 0;
            break;

        case  ID_WINDOW_MODE_VOLUME_IN:
            volume_num++;
            if (volume_num > 99)
                volume_num = 100;
            break;



        default:
            break;

        }
        break;


    case WM_PAINT:
        GUI_SetFont(GUI_FONT_32B_ASCII);
        GUI_SetColor(GUI_WHITE);
        GUI_DispDecAt(volume_num, 278, 20, 3);
        break;


    default:
        WM_DefaultProc(pMsg);
        break;
    }

}




BUTTON_Handle hButton0;
BUTTON_Handle hButton1;
BUTTON_Handle hButton2;
BUTTON_Handle hButton3;
BUTTON_Handle hButton4;
BUTTON_Handle hButton5;



void  hsw_create_button_init(void)
{

    hButton0 = BUTTON_CreateEx(BUTTON_BT_INIT_X, BUTTON_BT_INIT_Y, 56, 56, hsw_home_win, WM_CF_SHOW, 0, ID_BUTTON_BT);
    hButton1 = BUTTON_CreateEx(BUTTON_CHARGING_INIT_X, BUTTON_CHARGING_INIT_Y, 56, 56, hsw_home_win, WM_CF_SHOW, 0, ID_BUTTON_CHARGING);
    hButton2 = BUTTON_CreateEx(BUTTON_VOL_DE_INIT_X, BUTTON_VOL_DE_INIT_Y, 56, 56, hsw_home_win, WM_CF_SHOW, 0, ID_BUTTON_VOL_DE);
    hButton3 = BUTTON_CreateEx(BUTTON_VOL_IN_INIT_X, BUTTON_VOL_IN_INIT_Y, 56, 56, hsw_home_win, WM_CF_SHOW, 0, ID_BUTTON_VOL_IN);
    hButton4 = BUTTON_CreateEx(BUTTON_LED_INIT_X, BUTTON_LED_INIT_Y, 56, 56, hsw_home_win, WM_CF_SHOW, 0, ID_BUTTON_LED);

    BUTTON_SetText(hButton0, button_name_table[0]);
    BUTTON_SetText(hButton1, button_name_table[1]);
    BUTTON_SetText(hButton2, button_name_table[2]);
    BUTTON_SetText(hButton3, button_name_table[3]);
    BUTTON_SetText(hButton4, button_name_table[4]);

    current_button_mode = 0;

}



void hsw_update_button_mode(WM_HWIN button_pWin)
{
   
    int new_index = 0;
    U8 i = 0;

    new_index = current_button_mode;

    for (i = 0; i < 5; i++)
    {
        button_ID_set_arr = new_index;
        new_index++;
        if (new_index >= BUTTON_MAX_MODE)
            new_index = 0;
    }

    WM_DeleteWindow(hButton0);
    WM_DeleteWindow(hButton1);
    WM_DeleteWindow(hButton2);
    WM_DeleteWindow(hButton3);
    WM_DeleteWindow(hButton4);


    hButton0 = BUTTON_CreateEx(BUTTON_BT_INIT_X, BUTTON_BT_INIT_Y, 56, 56, button_pWin, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[0]]);
    hButton1 = BUTTON_CreateEx(BUTTON_CHARGING_INIT_X, BUTTON_CHARGING_INIT_Y, 56, 56, button_pWin, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[1]]);
    hButton2 = BUTTON_CreateEx(BUTTON_VOL_DE_INIT_X, BUTTON_VOL_DE_INIT_Y, 56, 56, button_pWin, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[2]]);
    hButton3 = BUTTON_CreateEx(BUTTON_VOL_IN_INIT_X, BUTTON_VOL_IN_INIT_Y, 56, 56, button_pWin, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[3]]);
    hButton4 = BUTTON_CreateEx(BUTTON_LED_INIT_X, BUTTON_LED_INIT_Y, 56, 56, button_pWin, WM_CF_SHOW, 0, ID_Button_Table[button_ID_set_arr[4]]);


    BUTTON_SetText(hButton0, button_name_table[button_ID_set_arr[0]]);
    BUTTON_SetText(hButton1, button_name_table[button_ID_set_arr[1]]);
    BUTTON_SetText(hButton2, button_name_table[button_ID_set_arr[2]]);
    BUTTON_SetText(hButton3, button_name_table[button_ID_set_arr[3]]);
    BUTTON_SetText(hButton4, button_name_table[button_ID_set_arr[4]]);
}


void hsw_switch_button_mode(WM_HWIN button_pWin)
{
    int index = 0;
    U8 i = 0;

    index = current_button_mode;

    switch (Click_button_flag)
    {
        case 1://左滑

            index--; //
            if (index < 0)
                index = BUTTON_MAX_MODE - 1;

            Click_button_flag = 0;
            break;

        case 2://右滑

            index++;
            if (index >= BUTTON_MAX_MODE)
                index = 0;

            Click_button_flag = 0;
            break;

        default:
            break;
    };

    current_button_mode = index;

    //确定工作模式后,进行ui 的button切换
    hsw_update_button_mode(button_pWin);
}


/**
* @brief 以对话框方式间接创建控件
* @note 无
* @param 无
* @retval hWin:资源表中第一个控件的句柄
*/
WM_HWIN CreateFramewin(void)
{
    WM_HWIN hWin;

    hWin = GUI_CreateDialogBox(_aDialogCreate_Home, GUI_COUNTOF(_aDialogCreate_Home), _cbDialog_Home, WM_HBKWIN, 0, 0);

    return hWin;
}


/*********************************************************************
*
*       MainTask
*/
void MainTask(void)
{
        int xSize;
        int ySize;
        int time_count = 0;

        GUI_Init();
        // Enable motion support
        WM_MOTION_Enable(1);
        // Enable multi-buffering to avoid flickering.
        WM_MULTIBUF_Enable(1);
        GUI_MEMDEV_MULTIBUF_Enable(1);
        GUI_UC_SetEncodeUTF8();


        hsw_home_win = CreateFramewin();//获取父窗口的句柄


        //current_button_mode = 0;
        /*hsw_update_button_mode();*/
        hsw_create_button_init();

        while (1)
        {
            GUI_Delay(100);
        }
}

/*************************** End of file ****************************/


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2025-3-21 09:56:01 | 显示全部楼层
hsw1234 发表于 2025-3-20 14:48
这个是模拟的效果,本来想穿个短视频,不过好像不支持MP4格式

将所有按钮都创建到一个对话框资源列表里面,资源列表的WINDOW_CreateIndirect足够长,可以容下所有按钮,这样你就滑动的时候,移动对话框显示位置即可
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-25 21:29 , Processed in 0.261347 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表