硬汉嵌入式论坛

 找回密码
 立即注册
搜索
查看: 1277|回复: 25
收起左侧

[emWin] 关于抗锯齿在浅背景色,深前景色时的毛刺问题请教。

[复制链接]

6

主题

36

回帖

54

积分

初级会员

积分
54
发表于 2026-6-10 09:55:39 | 显示全部楼层 |阅读模式
我使用的是GD32F470,通过16bit的8080并口驱动LCD,LCD是320*480的分辨率,emwin的颜色深度配置成RGB565,开启了窗口的内存设备标志(WM_SetCreateFlags(WM_CF_MEMDEV);),在使用发现如下现象,在圆角矩形的绘制时,使用0x00F7F0FA的背景色,使用0x009B42DF的前景色,绘制出来圆角矩形会有毛刺现象,下面是效果图:,绘制的代码如下:        
        case WM_PAINT:
        {
            GUI_RECT rt = {0};
            WM_GetClientRectEx(pMsg->hWin, &rt);
            GUI_AA_SetFactor(get_AA_factor());
            /* 绘制背景:主界面背景色 */
            GUI_SetBkColor(get_primary_bk_color());
            GUI_Clear();
            /* 圆角矩形,居中 */
            GUI_RECT boxRt;
            boxRt.x0 = LOCK_RECT_X;
            boxRt.y0 = LOCK_RECT_Y;
            boxRt.x1 = LOCK_RECT_X + LOCK_RECT_W - 1;
            boxRt.y1 = LOCK_RECT_Y + LOCK_RECT_H - 1;
            /* 圆角矩形外框:master色 */
            GUI_SetColor(get_master_color());
            GUI_AA_FillRoundedRectEx(&boxRt, LOCK_RECT_RAD);
            /* 圆角矩形内部:白色(内缩2px) */
            GUI_RECT innerRt = boxRt;
            innerRt.x0 += 2;
            innerRt.y0 += 2;
            innerRt.x1 -= 2;
            innerRt.y1 -= 2;
            GUI_SetColor(GUI_WHITE);
            GUI_AA_FillRoundedRectEx(&innerRt, LOCK_RECT_RAD - 2);
            /* 计算当前圆形中心X (基于滑动偏移) */
            int circleCX = LOCK_CIRCLE_HOME_X + s_lockDrag.offsetX;
            int circleCY = (boxRt.y0 + boxRt.y1) / 2;
            /* 解锁图标:紫色圆角矩形轨道 + 圆形图标(在轨道内部移动) */
            {
                /* 绘制紫色圆角矩形轨道:从右侧HOME位置延伸到当前圆形中心位置 */
                /* 圆形在轨道左端,轨道包裹圆形 */
                GUI_RECT trackRt;
                trackRt.x0 = circleCX - LOCK_ICON_CIRCLE_R;
                trackRt.y0 = circleCY - LOCK_ICON_CIRCLE_R;
                trackRt.x1 = LOCK_CIRCLE_HOME_X + LOCK_ICON_CIRCLE_R;
                trackRt.y1 = circleCY + LOCK_ICON_CIRCLE_R;
                GUI_SetColor(get_master_color());
                GUI_AA_FillRoundedRectEx(&trackRt, LOCK_ICON_CIRCLE_R);
                /* 在圆形位置绘制白色填充圆(覆盖紫色,形成图标背景) */
                GUI_AA_FillCircle(circleCX, circleCY, LOCK_ICON_CIRCLE_R - 2);
                /* 白色圆内绘制锁图标 (ICO_LOCK_WHITE, 24x24) */
                int icoX = circleCX - 12;
                int icoY = circleCY - 12;
                USER_BMP_DrawEx(ICO_LOCK_WHITE, icoX, icoY);
                /* 长按进度弧(仅在长按计时时显示,绘于图标外圈) */
                if(s_lockLongPress.active && s_lockLongPress.ticks > 0U)
                {
                    int progress = (int)s_lockLongPress.ticks * 100
                                    / (int)LOCK_LONGPRESS_MAX_TICKS;
                    int arcR = LOCK_ICON_CIRCLE_R + 3;
                    GUI_SetPenSize(3);
                    /* 灰色底圆环 */
                    GUI_SetColor(0x00CCCCCC);
                    GUI_DrawCircle(circleCX, circleCY, arcR);
                    /* 主色进度弧(从12点钟顺时针) */
                    GUI_SetColor(get_master_color());
                    GUI_DrawArc(circleCX, circleCY, arcR, arcR,
                                    90 - progress * 360 / 100, 90);
                    GUI_SetPenSize(1);
                }
            }
            /* 绘制"滑动解锁"文字(始终居中显示,不随拖动移动) */
            {
                GUI_RECT textRt = innerRt;
                GUI_SetFont(FONT_20_BOLD);
                GUI_SetTextMode(GUI_TEXTMODE_TRANS);
                GUI_SetColor(get_font_secondary_color());
                GUI_DispStringInRect(trUtf8(STR_SLIDE_TO_UNLOCK),
                    &textRt, GUI_TA_HCENTER | GUI_TA_VCENTER);
            }
            break;
        }
想请教一下有什么办法可以优化这个显示效果吗?


回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-10 09:59:57 | 显示全部楼层
这是显示效果,emwin的版本是6.52.

12.png
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-10 10:38:02 | 显示全部楼层
在你的程序里面运行下这个,看看抗锯齿效果显示正常不,如果正常,没问题




[C] 纯文本查看 复制代码
/*********************************************************************
* SEGGER Microcontroller GmbH *
* Solutions for real time microcontroller applications *
* *
* emWin example code *
* *
**********************************************************************
----------------------------------------------------------------------
File : AA_Lines.c
Purpose : Shows lines with different antialiasing qualities
----------------------------------------------------------------------
*/
#include "GUI.h"
/*******************************************************************
*
* Show lines with different antialiasing qualities
*
********************************************************************
*/
static void DemoAntialiasing(void) {
int i, x1, x2, y;
y = 2;
//
// Set drawing attributes
//
GUI_SetColor(GUI_BLACK);
GUI_SetBkColor(GUI_WHITE);
GUI_Clear();
x1 = 10;
x2 = 90;
//
// Draw lines without antialiasing
//
GUI_DispStringHCenterAt("\nNormal", (x1 + x2) / 2, 10);
for (i = 1; i < 12; i++) {
GUI_SetPenSize(i);
GUI_DrawLine(x1, 40 + i * 15, x2, 40 + i * 15 + y);
}
x1 = 110;
x2 = 190;
//
// Draw lines with antialiasing quality factor 2
//
GUI_AA_SetFactor(2);
GUI_DispStringHCenterAt("Antialiased\n\nusing factor 2", (x1 + x2) / 2, 10);
for (i = 1; i < 12; i++) {
GUI_SetPenSize(i);
GUI_AA_DrawLine(x1, 40 + i * 15, x2, 40 + i * 15 + y);
}
x1 = 210;
x2 = 290;
//
// Draw lines with antialiasing quality factor 6
//
GUI_AA_SetFactor(6);
GUI_DispStringHCenterAt("Antialiased\n\nusing factor 6", (x1 + x2) / 2, 10);
for (i = 1; i < 12; i++) {
GUI_SetPenSize(i);
GUI_AA_DrawLine(x1, 40 + i * 15, x2, 40 + i * 15 + y);
 
}
}
/*******************************************************************
*
* MainTask
*
********************************************************************
*/
void MainTask(void) {
GUI_Init();
DemoAntialiasing();
while(1)
GUI_Delay(100);
}


回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-10 13:48:48 | 显示全部楼层
eric2013 发表于 2026-6-10 10:38
在你的程序里面运行下这个,看看抗锯齿效果显示正常不,如果正常,没问题

这是按照例程显示出来的效果,抗锯齿效果也是异常的,这个问题有哪些排查和修复的方向吗?


下载.png
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-10 15:14:22 | 显示全部楼层
qtxxcj123 发表于 2026-6-10 13:48
这是按照例程显示出来的效果,抗锯齿效果也是异常的,这个问题有哪些排查和修复的方向吗?

换个emWin5.x版本试试
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-10 16:52:36 | 显示全部楼层
eric2013 发表于 2026-6-10 15:14
换个emWin5.x版本试试

直接更换STemWIn5.26的库,没有做其他修改,得到的图片是这样的。也很奇怪。


下载 (1).png
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-10 17:26:02 | 显示全部楼层
qtxxcj123 发表于 2026-6-10 16:52
直接更换STemWIn5.26的库,没有做其他修改,得到的图片是这样的。也很奇怪。

emWin底层接口的读像素是不是没做好,把游标箭头显示出来,然后界面滑动看看是不是有拖影

点评

[mw_shl_code=c,true]/********************************************************************* * * Public data * ********************************************************************** */ /****  详情 回复 发表于 2026-6-11 08:58
关于底层接口的读像素我发现了一个问题,那就是我使用GUI_DEVICE_API封装emWin的底层驱动,但是读像素的接口永远没有被调用,我在DBG的时候,给_GetPixelIndex打了断点,但是这个断电好像并没有被调用过(在图像或界  详情 回复 发表于 2026-6-11 08:56
[mw_shl_code=c,true]/********************************************************************* * 读点函数 */ static LCD_PIXELINDEX _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) { LCD_PI  详情 回复 发表于 2026-6-11 08:35
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-11 08:35:29 | 显示全部楼层
eric2013 发表于 2026-6-10 17:26
emWin底层接口的读像素是不是没做好,把游标箭头显示出来,然后界面滑动看看是不是有拖影

[C] 纯文本查看 复制代码
/*********************************************************************
*
    读点函数
*/
static LCD_PIXELINDEX _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y)
{
    LCD_PIXELINDEX PixelIndex;
    #if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
    int xPhys, yPhys;

    xPhys = LOG2PHYS_X(x, y);
    yPhys = LOG2PHYS_Y(x, y);
    #else
#define xPhys x
#define yPhys y
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    {
        PixelIndex = monitor_get_pixel(x, y);
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
    #endif
    return PixelIndex;
}

这个是读点函数,内部读RAM 中 300Kb缓存区里面的点数据,没有从LCD读取点数据。
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-11 08:56:30 | 显示全部楼层
eric2013 发表于 2026-6-10 17:26
emWin底层接口的读像素是不是没做好,把游标箭头显示出来,然后界面滑动看看是不是有拖影

关于底层接口的读像素我发现了一个问题,那就是我使用GUI_DEVICE_API封装emWin的底层驱动,但是读像素的接口永远没有被调用,我在DBG的时候,给_GetPixelIndex打了断点,但是这个断电好像并没有被调用过(在图像或界面切换时)。
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-11 08:58:47 | 显示全部楼层
eric2013 发表于 2026-6-10 17:26
emWin底层接口的读像素是不是没做好,把游标箭头显示出来,然后界面滑动看看是不是有拖影

[C] 纯文本查看 复制代码
/*********************************************************************
*
*       Public data
*
**********************************************************************
*/
/*********************************************************************
*
*       GUI_DEVICE_API structure
*/
const GUI_DEVICE_API GUIDRV_Template_API =
{
    //
    // Data
    //
    DEVICE_CLASS_DRIVER,
    //
    // Drawing functions
    //
    _DrawBitmap,
    _DrawHLine,
    _DrawVLine,
    _FillRect,
    _GetPixelIndex,
    _SetPixelIndex,
    _XorPixel,
    //
    // Set origin
    //
    _SetOrg,
    //
    // Request information
    //
    _GetDevFunc,
    _GetDevProp,
    _GetDevData,
    _GetRect,
};

这是部分代码片段。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-11 09:27:05 | 显示全部楼层
qtxxcj123 发表于 2026-6-11 08:58
[mw_shl_code=c,true]/*********************************************************************
*
*   ...

代码没贴全

点评

[mw_shl_code=c,true]/********************************************************************* * Portions COPYRIGHT 2013 STMicroelectronics * * Portions SEGGER Microcont  详情 回复 发表于 2026-6-11 11:02
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-11 11:02:12 | 显示全部楼层

[C] 纯文本查看 复制代码
/*********************************************************************
*          Portions COPYRIGHT 2013 STMicroelectronics                *
*          Portions SEGGER Microcontroller GmbH & Co. KG             *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2013  SEGGER Microcontroller GmbH & Co. KG       *
*                                                                    *
*        Internet: [url]www.segger.com[/url]    Support:  [email]support@segger.com[/email]    *
*                                                                    *
**********************************************************************

** emWin V5.22 - Graphical user interface for embedded applications **
All  Intellectual Property rights  in the Software belongs to  SEGGER.
emWin is protected by  international copyright laws.  Knowledge of the
source code may not be used to write a similar product.  This file may
only be used in accordance with the following terms:

The  software has  been licensed  to STMicroelectronics International
N.V. a Dutch company with a Swiss branch and its headquarters in Plan-
les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the
purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_
troller products commercialized by Licensee only, sublicensed and dis_
tributed under the terms and conditions of the End User License Agree_
ment supplied by STMicroelectronics International N.V.
Full source code is available at: [url]www.segger.com[/url]

We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : GUIDRV_Template.c
Purpose     : Template driver, could be used as starting point for new
              simple display drivers supporting only one color depth.
---------------------------END-OF-HEADER------------------------------
*/

/**
  ******************************************************************************
  * @attention
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        [url]http://www.st.com/software_license_agreement_liberty_v2[/url]
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

#include <stddef.h>

#include "LCD_Private.h"
#include "GUI_Private.h"
#include "LCD_ConfDefaults.h"
#include "st7365p/monitor_st7365p.h"
/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
/*********************************************************************
*
*       Macros for MIRROR_, SWAP_ and LUT_
*/
#if (!defined (LCD_LUT_COM) && !defined(LCD_LUT_SEG))
    #if   (!LCD_MIRROR_X && !LCD_MIRROR_Y && !LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) x
        #define LOG2PHYS_Y(x, y) y
    #elif (!LCD_MIRROR_X && !LCD_MIRROR_Y &&  LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) y
        #define LOG2PHYS_Y(x, y) x
    #elif (!LCD_MIRROR_X &&  LCD_MIRROR_Y && !LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) x
        #define LOG2PHYS_Y(x, y) LCD_YSIZE - 1 - (y)
    #elif (!LCD_MIRROR_X &&  LCD_MIRROR_Y &&  LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) y
        #define LOG2PHYS_Y(x, y) LCD_XSIZE - 1 - (x)
    #elif ( LCD_MIRROR_X && !LCD_MIRROR_Y && !LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) LCD_XSIZE - 1 - (x)
        #define LOG2PHYS_Y(x, y) y
    #elif ( LCD_MIRROR_X && !LCD_MIRROR_Y &&  LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) LCD_YSIZE - 1 - (y)
        #define LOG2PHYS_Y(x, y) x
    #elif ( LCD_MIRROR_X &&  LCD_MIRROR_Y && !LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) LCD_XSIZE - 1 - (x)
        #define LOG2PHYS_Y(x, y) LCD_YSIZE - 1 - (y)
    #elif ( LCD_MIRROR_X &&  LCD_MIRROR_Y &&  LCD_SWAP_XY)
        #define LOG2PHYS_X(x, y) LCD_YSIZE - 1 - (y)
        #define LOG2PHYS_Y(x, y) LCD_XSIZE - 1 - (x)
    #endif
#else
    #if   ( defined (LCD_LUT_COM) && !defined(LCD_LUT_SEG))
        #define LOG2PHYS_X(x, y) x
        #define LOG2PHYS_Y(x, y) LCD__aLine2Com0[y]
    #elif (!defined (LCD_LUT_COM) &&  defined(LCD_LUT_SEG))
        #define LOG2PHYS_X(x, y) LCD__aCol2Seg0[x]
        #define LOG2PHYS_Y(x, y) y
    #elif ( defined (LCD_LUT_COM) &&  defined(LCD_LUT_SEG))
        #define LOG2PHYS_X(x, y) LCD__aCol2Seg0[x]
        #define LOG2PHYS_Y(x, y) LCD__aLine2Com0[y]
    #endif
#endif

/*********************************************************************
*
*       Types
*
**********************************************************************
*/
typedef struct
{
    PTR_ADDR VRAMAddr;
    int xSize, ySize;
    int vxSize, vySize;
    int vxSizePhys;
    int BitsPerPixel;
} DRIVER_CONTEXT_TEMPLATE;

/*********************************************************************
*
*       Static functions
*
**********************************************************************
*/
/*********************************************************************
 打点函数
*/
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, LCD_PIXELINDEX PixelIndex)
{
    monitor_put_pixel(x, y, PixelIndex);
}


/*********************************************************************
*
    读点函数
*/
static LCD_PIXELINDEX _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y)
{
    LCD_PIXELINDEX PixelIndex;
    #if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
    int xPhys, yPhys;

    xPhys = LOG2PHYS_X(x, y);
    yPhys = LOG2PHYS_Y(x, y);
    #else
#define xPhys x
#define yPhys y
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    {
        PixelIndex = monitor_get_pixel(x, y);
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
    #endif
    return PixelIndex;
}
/*********************************************************************
*
*       _XorPixel
*/
static void _XorPixel(GUI_DEVICE * pDevice, int x, int y)
{
    LCD_PIXELINDEX PixelIndex;
    LCD_PIXELINDEX IndexMask;

    PixelIndex = _GetPixelIndex(pDevice, x, y);
    IndexMask  = pDevice->pColorConvAPI->pfGetIndexMask();
    _SetPixelIndex(pDevice, x, y, PixelIndex ^ IndexMask);
}

/*********************************************************************
*
*       _FillRect
*/
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1)
{

    LCD_PIXELINDEX ColorIndex;
    int x;

    if (GUI_pContext->DrawMode & LCD_DRAWMODE_XOR)
    {
        for (; y0 <= y1; y0++)
        {
            for (x = x0; x <= x1; x++)
            {
                _XorPixel(pDevice, x, y0);
            }
        }
    }
    else
    {
        ColorIndex = LCD__GetColorIndex();
        monitor_fill_rect(x0, y0, x1 - x0 + 1, y1 - y0 + 1, ColorIndex);
    }
}


/*********************************************************************
*
*       _DrawHLine
*/
static void _DrawHLine(GUI_DEVICE * pDevice, int x0, int y, int x1)
{
    LCD_PIXELINDEX ColorIndex;
    ColorIndex = LCD__GetColorIndex();
    monitor_draw_h_line(x0, y, x1, ColorIndex);
}

/*********************************************************************
*
*       _DrawVLine, not optimized
*/
static void _DrawVLine(GUI_DEVICE * pDevice, int x, int y0, int y1)
{
    LCD_PIXELINDEX ColorIndex;
    ColorIndex = LCD__GetColorIndex();
    monitor_draw_v_line(x, y0, y1, ColorIndex);
}

/*********************************************************************
*
*       Draw Bitmap 1 BPP
*/
static void _DrawBitLine1BPP(GUI_DEVICE * pDevice, int x, int y, U8 const GUI_UNI_PTR * p, int Diff, int xsize, const LCD_PIXELINDEX * pTrans)
{
    LCD_PIXELINDEX IndexMask, Index0, Index1, Pixel;

    Index0 = *(pTrans + 0);
    Index1 = *(pTrans + 1);
    x += Diff;
    switch (GUI_pContext->DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR))
    {
        case 0:
            do
            {
                _SetPixelIndex(pDevice, x++, y, (*p & (0x80 >> Diff)) ? Index1 : Index0);
                if (++Diff == 8)
                {
                    Diff = 0;
                    p++;
                }
            }
            while (--xsize);
            break;
        case LCD_DRAWMODE_TRANS:
            do
            {
                if (*p & (0x80 >> Diff))
                    _SetPixelIndex(pDevice, x, y, Index1);
                x++;
                if (++Diff == 8)
                {
                    Diff = 0;
                    p++;
                }
            }
            while (--xsize);
            break;
        case LCD_DRAWMODE_XOR | LCD_DRAWMODE_TRANS:
        case LCD_DRAWMODE_XOR:
            IndexMask = pDevice->pColorConvAPI->pfGetIndexMask();
            do
            {
                if (*p & (0x80 >> Diff))
                {
                    Pixel = _GetPixelIndex(pDevice, x, y);
                    _SetPixelIndex(pDevice, x, y, Pixel ^ IndexMask);
                }
                x++;
                if (++Diff == 8)
                {
                    Diff = 0;
                    p++;
                }
            }
            while (--xsize);
            break;
    }
}

/*********************************************************************
*
*       Draw Bitmap 2 BPP
*/
static void  _DrawBitLine2BPP(GUI_DEVICE * pDevice, int x, int y, U8 const GUI_UNI_PTR * p, int Diff, int xsize, const LCD_PIXELINDEX * pTrans)
{
    LCD_PIXELINDEX Pixels, PixelIndex;
    int CurrentPixel, Shift, Index;

    Pixels = *p;
    CurrentPixel = Diff;
    x += Diff;
    switch (GUI_pContext->DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR))
    {
        case 0:
            if (pTrans)
            {
                do
                {
                    Shift = (3 - CurrentPixel) << 1;
                    Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
                    PixelIndex = *(pTrans + Index);
                    _SetPixelIndex(pDevice, x++, y, PixelIndex);
                    if (++CurrentPixel == 4)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            else
            {
                do
                {
                    Shift = (3 - CurrentPixel) << 1;
                    Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
                    _SetPixelIndex(pDevice, x++, y, Index);
                    if (++CurrentPixel == 4)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            break;
        case LCD_DRAWMODE_TRANS:
            if (pTrans)
            {
                do
                {
                    Shift = (3 - CurrentPixel) << 1;
                    Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
                    if (Index)
                    {
                        PixelIndex = *(pTrans + Index);
                        _SetPixelIndex(pDevice, x, y, PixelIndex);
                    }
                    x++;
                    if (++CurrentPixel == 4)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            else
            {
                do
                {
                    Shift = (3 - CurrentPixel) << 1;
                    Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
                    if (Index)
                    {
                        _SetPixelIndex(pDevice, x, y, Index);
                    }
                    x++;
                    if (++CurrentPixel == 4)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            break;
    }
}

/*********************************************************************
*
*       Draw Bitmap 4 BPP
*/
static void  _DrawBitLine4BPP(GUI_DEVICE * pDevice, int x, int y, U8 const GUI_UNI_PTR * p, int Diff, int xsize, const LCD_PIXELINDEX * pTrans)
{
    LCD_PIXELINDEX Pixels, PixelIndex;
    int CurrentPixel, Shift, Index;

    Pixels = *p;
    CurrentPixel = Diff;
    x += Diff;
    switch (GUI_pContext->DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR))
    {
        case 0:
            if (pTrans)
            {
                do
                {
                    Shift = (1 - CurrentPixel) << 2;
                    Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
                    PixelIndex = *(pTrans + Index);
                    _SetPixelIndex(pDevice, x++, y, PixelIndex);
                    if (++CurrentPixel == 2)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            else
            {
                do
                {
                    Shift = (1 - CurrentPixel) << 2;
                    Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
                    _SetPixelIndex(pDevice, x++, y, Index);
                    if (++CurrentPixel == 2)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            break;
        case LCD_DRAWMODE_TRANS:
            if (pTrans)
            {
                do
                {
                    Shift = (1 - CurrentPixel) << 2;
                    Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
                    if (Index)
                    {
                        PixelIndex = *(pTrans + Index);
                        _SetPixelIndex(pDevice, x, y, PixelIndex);
                    }
                    x++;
                    if (++CurrentPixel == 2)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            else
            {
                do
                {
                    Shift = (1 - CurrentPixel) << 2;
                    Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
                    if (Index)
                    {
                        _SetPixelIndex(pDevice, x, y, Index);
                    }
                    x++;
                    if (++CurrentPixel == 2)
                    {
                        CurrentPixel = 0;
                        Pixels = *(++p);
                    }
                }
                while (--xsize);
            }
            break;
    }
}

/*********************************************************************
*
*       Draw Bitmap 8 BPP
*/
static void  _DrawBitLine8BPP(GUI_DEVICE * pDevice, int x, int y, U8 const GUI_UNI_PTR * p, int xsize, const LCD_PIXELINDEX * pTrans)
{
    LCD_PIXELINDEX Pixel;

    switch (GUI_pContext->DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR))
    {
        case 0:
            if (pTrans)
            {
                for (; xsize > 0; xsize--, x++, p++)
                {
                    Pixel = *p;
                    _SetPixelIndex(pDevice, x, y, *(pTrans + Pixel));
                }
            }
            else
            {
                for (; xsize > 0; xsize--, x++, p++)
                {
                    _SetPixelIndex(pDevice, x, y, *p);
                }
            }
            break;
        case LCD_DRAWMODE_TRANS:
            if (pTrans)
            {
                for (; xsize > 0; xsize--, x++, p++)
                {
                    Pixel = *p;
                    if (Pixel)
                    {
                        _SetPixelIndex(pDevice, x, y, *(pTrans + Pixel));
                    }
                }
            }
            else
            {
                for (; xsize > 0; xsize--, x++, p++)
                {
                    Pixel = *p;
                    if (Pixel)
                    {
                        _SetPixelIndex(pDevice, x, y, Pixel);
                    }
                }
            }
            break;
    }
}

/*********************************************************************
*
*       Draw Bitmap 16 BPP, not optimized
*
* Purpose:
*   Drawing of 16bpp high color bitmaps.
*   Only required for 16bpp color depth of target. Should be removed otherwise.
*/
static void _DrawBitLine16BPP(GUI_DEVICE * pDevice, int x, int y, U16 const GUI_UNI_PTR * p, int xsize)
{

    monitor_draw_h_color_line(x, y, xsize, (uint16_t *)p);
}

/*********************************************************************
*
*       Draw Bitmap 32 BPP, not optimized
*
* Purpose:
*   Drawing of 32bpp true color bitmaps.
*   Only required for 32bpp color depth of target. Should be removed otherwise.
*/
static void _DrawBitLine32BPP(GUI_DEVICE * pDevice, int x, int y, U32 const GUI_UNI_PTR * p, int xsize)
{
    monitor_draw_h_color_line(x, y, xsize, (uint16_t *)p);
}

/*********************************************************************
*
*       _DrawBitmap
*/
static void _DrawBitmap(GUI_DEVICE * pDevice, int x0, int y0,
                        int xSize, int ySize,
                        int BitsPerPixel,
                        int BytesPerLine,
                        const U8 GUI_UNI_PTR * pData, int Diff,
                        const LCD_PIXELINDEX * pTrans)
{
    int i;

    switch (BitsPerPixel)
    {
        case 1:
            for (i = 0; i < ySize; i++)
            {
                _DrawBitLine1BPP(pDevice, x0, i + y0, pData, Diff, xSize, pTrans);
                pData += BytesPerLine;
            }
            break;
        case 2:
            for (i = 0; i < ySize; i++)
            {
                _DrawBitLine2BPP(pDevice, x0, i + y0, pData, Diff, xSize, pTrans);
                pData += BytesPerLine;
            }
            break;
        case 4:
            for (i = 0; i < ySize; i++)
            {
                _DrawBitLine4BPP(pDevice, x0, i + y0, pData, Diff, xSize, pTrans);
                pData += BytesPerLine;
            }
            break;
        case 8:
            for (i = 0; i < ySize; i++)
            {
                _DrawBitLine8BPP(pDevice, x0, i + y0, pData, xSize, pTrans);
                pData += BytesPerLine;
            }
            break;
        //
        // Only required for 16bpp color depth of target. Should be removed otherwise.
        //
        case 16:
            for (i = 0; i < ySize; i++)
            {
                _DrawBitLine16BPP(pDevice, x0, i + y0, (const U16 *)pData, xSize);
                pData += BytesPerLine;
            }
            break;
        //
        // Only required for 32bpp color depth of target. Should be removed otherwise.
        //
        case 32:
            for (i = 0; i < ySize; i++)
            {
                _DrawBitLine32BPP(pDevice, x0, i + y0, (const U32 *)pData, xSize);
                pData += BytesPerLine;
            }
            break;
    }
}

/*********************************************************************
*
*       _InitOnce
*
* Purpose:
*   Allocates a fixed block for the context of the driver
*
* Return value:
*   0 on success, 1 on error
*/
static int _InitOnce(GUI_DEVICE * pDevice)
{
    DRIVER_CONTEXT_TEMPLATE * pContext;

    if (pDevice->u.pContext == NULL)
    {
        pDevice->u.pContext = GUI_ALLOC_GetFixedBlock(sizeof(DRIVER_CONTEXT_TEMPLATE));
        pContext = (DRIVER_CONTEXT_TEMPLATE *)pDevice->u.pContext;
        pContext->BitsPerPixel = LCD__GetBPP(pDevice->pColorConvAPI->pfGetIndexMask());
    }
    return pDevice->u.pContext ? 0 : 1;
}

/*********************************************************************
*
*       _GetDevProp
*/
static I32 _GetDevProp(GUI_DEVICE * pDevice, int Index)
{
    DRIVER_CONTEXT_TEMPLATE * pContext;

    pContext = (DRIVER_CONTEXT_TEMPLATE *)pDevice->u.pContext;
    switch (Index)
    {
        case LCD_DEVCAP_XSIZE:
            return pContext->xSize;
        case LCD_DEVCAP_YSIZE:
            return pContext->ySize;
        case LCD_DEVCAP_VXSIZE:
            return pContext->vxSize;
        case LCD_DEVCAP_VYSIZE:
            return pContext->vySize;
        case LCD_DEVCAP_BITSPERPIXEL:
            return pContext->BitsPerPixel;
        case LCD_DEVCAP_NUMCOLORS:
            return 0;
        case LCD_DEVCAP_XMAG:
            return 1;
        case LCD_DEVCAP_YMAG:
            return 1;
        case LCD_DEVCAP_MIRROR_X:
            return 0;
        case LCD_DEVCAP_MIRROR_Y:
            return 0;
        case LCD_DEVCAP_SWAP_XY:
            return 0;
    }
    return -1;
}

/*********************************************************************
*
*       _GetDevData
*/
static const void * _GetDevData(GUI_DEVICE * pDevice, int Index)
{
    GUI_USE_PARA(pDevice);
    #if GUI_SUPPORT_MEMDEV
    switch (Index)
    {
        case LCD_DEVDATA_MEMDEV:
            return (void *)&GUI_MEMDEV_DEVICE_16; // TBD: Has to be adapted to the right memory device depending on the used color depth!
    }
    #else
    GUI_USE_PARA(Index);
    #endif
    return NULL;
}

/*********************************************************************
*
*       _GetRect
*/
static void _GetRect(GUI_DEVICE * pDevice, LCD_RECT * pRect)
{
    DRIVER_CONTEXT_TEMPLATE * pContext;

    pContext = (DRIVER_CONTEXT_TEMPLATE *)pDevice->u.pContext;
    pRect->x0 = 0;
    pRect->y0 = 0;
    pRect->x1 = pContext->vxSize - 1;
    pRect->y1 = pContext->vySize - 1;
}

/*********************************************************************
*
*       _SetOrg
*/
static void _SetOrg(GUI_DEVICE * pDevice, int x, int y)
{
    LCD_X_SETORG_INFO Data = {0};

    Data.xPos = x;
    Data.yPos = y;
    LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_SETORG, (void *)&Data);
}

/*********************************************************************
*
*       Static code: Functions available by _GetDevFunc()
*
**********************************************************************
*/
/*********************************************************************
*
*       _SetVRAMAddr
*/
static void _SetVRAMAddr(GUI_DEVICE * pDevice, void * pVRAM)
{
    DRIVER_CONTEXT_TEMPLATE * pContext;
    LCD_X_SETVRAMADDR_INFO Data = {0};

    _InitOnce(pDevice);
    if (pDevice->u.pContext)
    {
        pContext = (DRIVER_CONTEXT_TEMPLATE *)pDevice->u.pContext;
        pContext->VRAMAddr = (U32)pVRAM;
        Data.pVRAM = pVRAM;
        LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_SETVRAMADDR, (void *)&Data);
    }
}

/*********************************************************************
*
*       _SetVSize
*/
static void _SetVSize(GUI_DEVICE * pDevice, int xSize, int ySize)
{
    DRIVER_CONTEXT_TEMPLATE * pContext;

    _InitOnce(pDevice);
    if (pDevice->u.pContext)
    {
        pContext = (DRIVER_CONTEXT_TEMPLATE *)pDevice->u.pContext;
        pContext->vxSize = xSize;
        pContext->vySize = ySize;
        pContext->vxSizePhys = xSize;
    }
}

/*********************************************************************
*
*       _SetSize
*/
static void _SetSize(GUI_DEVICE * pDevice, int xSize, int ySize)
{
    DRIVER_CONTEXT_TEMPLATE * pContext;
    LCD_X_SETSIZE_INFO Data = {0};

    _InitOnce(pDevice);
    if (pDevice->u.pContext)
    {
        pContext = (DRIVER_CONTEXT_TEMPLATE *)pDevice->u.pContext;
        pContext->vxSizePhys = (pContext->vxSizePhys == 0) ? xSize : pContext->vxSizePhys;
        pContext->xSize = xSize;
        pContext->ySize = ySize;
        Data.xSize = xSize;
        Data.ySize = ySize;
        LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_SETSIZE, (void *)&Data);
    }
}
/*********************************************************************
*
*       _Init
*/
static int  _Init(GUI_DEVICE * pDevice)
{
    int r;

    r = _InitOnce(pDevice);
    r |= LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_INITCONTROLLER, NULL);
    return r;
}

/*********************************************************************
*
*       _On
*/
static void _On (GUI_DEVICE * pDevice)
{
    LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_ON, NULL);
}

/*********************************************************************
*
*       _Off
*/
static void _Off (GUI_DEVICE * pDevice)
{
    LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_OFF, NULL);
}

/*********************************************************************
*
*       _SetLUTEntry
*/
static void _SetLUTEntry(GUI_DEVICE * pDevice, U8 Pos, LCD_COLOR Color)
{
    LCD_X_SETLUTENTRY_INFO Data = {0};

    Data.Pos   = Pos;
    Data.Color = Color;
    LCD_X_DisplayDriver(pDevice->LayerIndex, LCD_X_SETLUTENTRY, (void *)&Data);
}

/*********************************************************************
*
*       _GetDevFunc
*/
static void (* _GetDevFunc(GUI_DEVICE ** ppDevice, int Index))(void)
{
    GUI_USE_PARA(ppDevice);
    switch (Index)
    {
        case LCD_DEVFUNC_SET_VRAM_ADDR:
            return (void (*)(void))_SetVRAMAddr;
        case LCD_DEVFUNC_SET_VSIZE:
            return (void (*)(void))_SetVSize;
        case LCD_DEVFUNC_SET_SIZE:
            return (void (*)(void))_SetSize;
        case LCD_DEVFUNC_INIT:
            return (void (*)(void))_Init;
        case LCD_DEVFUNC_ON:
            return (void (*)(void))_On;
        case LCD_DEVFUNC_OFF:
            return (void (*)(void))_Off;
        case LCD_DEVFUNC_SETLUTENTRY:
            return (void (*)(void))_SetLUTEntry;
    }
    return NULL;
}

/*********************************************************************
*
*       Public data
*
**********************************************************************
*/
/*********************************************************************
*
*       GUI_DEVICE_API structure
*/
const GUI_DEVICE_API GUIDRV_Template_API =
{
    //
    // Data
    //
    DEVICE_CLASS_DRIVER,
    //
    // Drawing functions
    //
    _DrawBitmap,
    _DrawHLine,
    _DrawVLine,
    _FillRect,
    _GetPixelIndex,
    _SetPixelIndex,
    _XorPixel,
    //
    // Set origin
    //
    _SetOrg,
    //
    // Request information
    //
    _GetDevFunc,
    _GetDevProp,
    _GetDevData,
    _GetRect,
};

/*************************** End of file ****************************/
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-11 16:25:10 | 显示全部楼层
qtxxcj123 发表于 2026-6-11 11:02
[mw_shl_code=c,true]/*********************************************************************
*      ...

你的显示屏有触摸功能吧,将emWin的游标箭头显示出来,然后滑动,会进入这个函数的

static LCD_PIXELINDEX _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y)

点评

使用GUI_CURSOR_Show();显示了游标箭头,然后通过GUI_PID_StoreState改变PID,达到游标箭头移动的效果。移动时发现,确实响应了monitor_get_pixel函数,移动过程没有出现残影等问题。  详情 回复 发表于 2026-6-12 09:00
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-12 09:00:16 | 显示全部楼层
eric2013 发表于 2026-6-11 16:25
你的显示屏有触摸功能吧,将emWin的游标箭头显示出来,然后滑动,会进入这个函数的

static LCD_PIXELI ...

使用GUI_CURSOR_Show();显示了游标箭头,然后通过GUI_PID_StoreState改变PID,达到游标箭头移动的效果。移动时发现,确实响应了monitor_get_pixel函数,移动过程没有出现残影等问题。

滑动的动态gif

滑动的动态gif
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-13 09:39:06 | 显示全部楼层
qtxxcj123 发表于 2026-6-12 09:00
使用GUI_CURSOR_Show();显示了游标箭头,然后通过GUI_PID_StoreState改变PID,达到游标箭头移动的效果。 ...

在图形显示区里面拖拽

点评

嗯嗯,是在这个显示区域滑动吗?好像也么有异常。  详情 回复 发表于 2026-6-13 15:53
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-13 15:53:37 | 显示全部楼层
eric2013 发表于 2026-6-13 09:39
在图形显示区里面拖拽

嗯嗯,是在这个显示区域滑动吗?好像也么有异常。

在显示区域滑动的效果。

在显示区域滑动的效果。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-15 09:14:02 | 显示全部楼层
qtxxcj123 发表于 2026-6-13 15:53
嗯嗯,是在这个显示区域滑动吗?好像也么有异常。

修改下你的底层接口文件。

仅实现这两个函数,其他都默认,不要做修改
_SetPixelInde
_GetPixelInde

排除接口函数实现问题

点评

默认是指传入NULL指针吗?emwin好像不会处理NULL指针。  详情 回复 发表于 2026-6-17 09:31
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-17 09:31:52 | 显示全部楼层
eric2013 发表于 2026-6-15 09:14
修改下你的底层接口文件。

仅实现这两个函数,其他都默认,不要做修改

默认是指传入NULL指针吗?emwin好像不会处理NULL指针。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-17 10:02:16 | 显示全部楼层
qtxxcj123 发表于 2026-6-17 09:31
默认是指传入NULL指针吗?emwin好像不会处理NULL指针。

获取这个GUI Template原始文件,仅修改这两个函数就行
_SetPixelInde
_GetPixelInde

其它函数不要做任何修改

点评

这个GUI_Template的原始文件已经遗失了,从接受项目开始就是这个文件。,我也怀疑是这个有问题,打算切换成EMWIN内部的API模板试试了。  详情 回复 发表于 2026-6-17 10:17
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-17 10:17:24 | 显示全部楼层
eric2013 发表于 2026-6-17 10:02
获取这个GUI Template原始文件,仅修改这两个函数就行
_SetPixelInde
_GetPixelInde

这个GUI_Template的原始文件已经遗失了,从接受项目开始就是这个文件。,我也怀疑是这个有问题,打算切换成EMWIN内部的API模板试试了。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-18 10:31:01 | 显示全部楼层
qtxxcj123 发表于 2026-6-17 10:17
这个GUI_Template的原始文件已经遗失了,从接受项目开始就是这个文件。,我也怀疑是这个有问题,打算 ...

这个里面有

MDK安装包中带的emWin库已经升级到最新的5.46e
https://forum.anfulai.cn/forum.p ... 2903&fromuid=58
(出处: 硬汉嵌入式论坛)

点评

直接替换GUI_Template.c文件后,显示没有变化,还是显示异常的。  详情 回复 发表于 2026-6-18 16:59
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-6-18 16:59:46 | 显示全部楼层
eric2013 发表于 2026-6-18 10:31
这个里面有

MDK安装包中带的emWin库已经升级到最新的5.46e

直接替换GUI_Template.c文件后,显示没有变化,还是显示异常的。
微信图片_20260618165913_71_32.jpg
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124238
QQ
发表于 2026-6-29 09:53:54 | 显示全部楼层
qtxxcj123 发表于 2026-6-18 16:59
直接替换GUI_Template.c文件后,显示没有变化,还是显示异常的。

现在解决了吗

点评

然后我想换的888色彩,深入之后发现,我的面板只支持18bit的颜色深度,24bit的颜色深度会被转换为18bit,所以改善也不大。  详情 回复 发表于 2026-7-16 09:48
后续根据AI的建议,使用了高分辨率坐标,效果有改善,但是并没有达到预期。  详情 回复 发表于 2026-7-16 09:47
并没有,赶项目进度去了。感觉要换888试一下,颜色过度可能太大了。  详情 回复 发表于 2026-7-1 19:07
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-7-1 19:07:44 | 显示全部楼层

并没有,赶项目进度去了。感觉要换888试一下,颜色过度可能太大了。
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-7-16 09:47:42 | 显示全部楼层

后续根据AI的建议,使用了高分辨率坐标,效果有改善,但是并没有达到预期。
回复

使用道具 举报

6

主题

36

回帖

54

积分

初级会员

积分
54
 楼主| 发表于 2026-7-16 09:48:39 | 显示全部楼层

然后我想换的888色彩,深入之后发现,我的面板只支持18bit的颜色深度,24bit的颜色深度会被转换为18bit,所以改善也不大。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-9 03:56 , Processed in 0.613155 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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