|
发表于 2020-6-24 10:19:39
|
显示全部楼层
13楼的代码缺少数组下标,我改了如下帮我看看,我的表针显示透明部分为黑色
/*-------- 使用 流位图显示, app图标描述结构体 --------------*/
typedef struct
{
const char *pFileNamePath; // 图标文件名路径
} CLOCK_BITMAP_ITEM_STREAM;
/*-----------------------------------------------------------
流数据取数据说明如下:
1. 先准备好需要的图标图片,*.bmp,*.png格式的,必须带透明通道的图片
2. 使用 st 提供的工具软件 BmpCvtST.exe (版本v532或v5.40都行) 打开已准备好的图片
3. 打开后什么也不修改直接 点击 Files->Save as ... 选择 *.dta 格式 按保存
4. a: 如果选择 True color with alpha 格式保存的,是按照 每个像素 4 字节取码的 +16Byte
b: 如果选择 High color with Alpha(565) 格式保存的,是按照 rgb565格式保存,另外还多了一个字节的透明通道数据 实际是按照 3字节保存数据 +16Byte
5. 比如一个图片像素为 96*96,那么按照 565格式取码后的大小为 96*3*96+16大小
-----------------------------------------------------------*/
static const CLOCK_BITMAP_ITEM_STREAM ClockStreamBitmapItemTab1[]=
{
// 图片旋转 只支持 ARGB8888 格式,切记切记
"0:/ICON/Clock_Icon/ARGB8888/ClockFace_294.dta",
"0:/ICON/Clock_Icon/ARGB8888/ClockHour_30_74.dta",
"0:/ICON/Clock_Icon/ARGB8888/ClockMinute_18_115.dta",
"0:/ICON/Clock_Icon/ARGB8888/ClockSecond_10_156.dta",
};
typedef struct
{
const int xSize;
const int ySize;
}_ClockPosStreamTypeDef;
const _ClockPosStreamTypeDef _ClockPosStream[]=
{
294, 294,
30, 74,
18, 115,
10, 156
};
typedef struct
{
GUI_MEMDEV_Handle hMem1_Clock[4]; // 时钟表盘、表针,数组0表示表盘背景,1表示时针,2表示分针,3表示秒针
GUI_MEMDEV_Handle hMem1_ClockDest; // 目标内存
GUI_MEMDEV_Handle hMem1_ClockLcd; // 显示内存
GUI_BITMAP Bitmap[4]; // 时钟表盘、表针,数组0表示表盘背景,1表示时针,2表示分针,3表示秒针
GUI_LOGPALETTE Palette[4];
uint8_t *_acComBuff ;
uint8_t *_acClockBuf[4] ; // 时钟表盘、表针,数组0表示表盘背景,1表示时针,2表示分针,3表示秒针
} _ClockPramTypeDef;
_ClockPramTypeDef * _ClockParm = NULL;
/*-------------- 星期的显示 ---------------------*/
static const char *ucWeekDay[7] =
{
"一",
"二",
"三",
"四",
"五",
"六",
"日"
};
/*******************************************************************************
*函数名称 : GUI_MEMDEV_RTC_ClockInit
*功能描述 : 初始化内存设备,在GUI_Init()之后调用, 也可以在 WM_INIT_DIALOG 这个里面调用一次, 初始化只执行一次即可
*输入参数 : 无
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
static void GUI_MEMDEV_RTC_ClockInit(void)
{
FIL CLOCK_File;
FRESULT result;
UINT bw;
int i = 0;
// 此内存申请后就不释放了,因为程序一直在运行
_ClockParm = (_ClockPramTypeDef *)myMalloc( SRAMEX, sizeof(_ClockPramTypeDef)); // SRAMDTCM
for( i=0; i<4; i++ )
{
result = f_open( &CLOCK_File, ClockStreamBitmapItemTab1.pFileNamePath, FA_READ );
if ( result != FR_OK )
{
printf("open file fail %d\n", result );
myFree( SRAMEX,(void *) _ClockParm );
return;
}
_ClockParm->_acClockBuf = myMalloc( SRAMEX, CLOCK_File.obj.objsize );
_ClockParm->_acComBuff = _ClockParm->_acClockBuf;
result = f_read( &CLOCK_File, _ClockParm->_acComBuff, CLOCK_File.obj.objsize, &bw );
if ( result != FR_OK )
{
__IO int cc;
for( cc=0; cc<i; cc++ )
{
_ClockParm->_acComBuff = _ClockParm->_acClockBuf[cc];
myFree( SRAMEX, (void *) _ClockParm->_acComBuff ); // 使用完后释放内存
}
f_close( &CLOCK_File );
myFree( SRAMEX, (void *) _ClockParm );
return ;
}
f_close( &CLOCK_File );
}
for( i=0; i<4; i++ )
{
// 适用与 emwin > v5.32 ARGB / ABGR 库 版本
// 显示表盘背景, 在单片机上绘制 32bit BMP 图片数据文件,必须使用 GUI_MEMDEV_CreateFixed32 这个函数
// 图片旋转只支持 32bit 格式的图片,切记切记 2018.06.14 21:10
_ClockParm->hMem1_Clock = GUI_MEMDEV_CreateFixed32( 0, // 创建具有 32bpp 颜色深度和 GUICC_8888 颜色转换的内存设备
0,
_ClockPosStream.xSize,
_ClockPosStream.ySize );
GUI_MEMDEV_Select( _ClockParm->hMem1_Clock);
_ClockParm->_acComBuff = _ClockParm->_acClockBuf;
// GUI_SetBkColor( GUI_TRANSPARENT ); // 清除背景色 0xFFC0C0C0 GUI_TRANSPARENT
// GUI_Clear();
GUI_CreateBitmapFromStream( &_ClockParm->Bitmap, &_ClockParm->Palette, _ClockParm->_acComBuff );
GUI_DrawBitmap( &_ClockParm->Bitmap, 0, 0 );
}
_ClockParm->hMem1_ClockDest = GUI_MEMDEV_CreateFixed32( 18, 28+79, // 最终显示的 x,y 地址
_ClockPosStream[0].xSize, // 与显示最大表盘尺寸宽度一致即可
_ClockPosStream[0].ySize );
_ClockParm->hMem1_ClockLcd = GUI_MEMDEV_CreateFixed32( 18, 28+79, // 最终显示的 x,y 地址
_ClockPosStream[0].xSize, // 与显示最大表盘尺寸宽度一致即可
_ClockPosStream[0].ySize );
//-----------------------------------------------------------------------------------------
GUI_MEMDEV_Select(0);
GUI_MEMDEV_CopyFromLCD( _ClockParm->hMem1_ClockLcd ); // 将 LCD 内容复制到存储设备
// 释放申请内存
for( i=0; i<4; i++ )
{
_ClockParm->_acComBuff = _ClockParm->_acClockBuf;
myFree( SRAMEX, (void *) _ClockParm->_acComBuff); // 使用完后释放内存
}
// myFree( SRAMEX,(void *) _ClockParm ); // 这个 _ClockParm 参数不能够释放,因为程序一直在运行
/* 配置回之前选择的目标窗口 */
// WM_SelectWindow( hWinOld );
}
/*******************************************************************************
*函数名称 : Clock_DrawDisp
*功能描述 : 更新时钟表盘
*输入参数 : 无
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
void Clock_DrawDisp(void)
{
int t0; // 用于三个指针的计数
int t1;
int t2;
// 时间与日期需要同时获取,切记切记,
RTC_GetTime();
RTC_GetDate();
t0 = 360 - (g_tRTC.Sec * 6); // 第一个指针计数,用于旋转秒针 (6度/秒,顺时针方向换算成逆时针方向)
t1 = 360 - (g_tRTC.Min *6) -(g_tRTC.Sec /10); // 第二个指针计数,用于旋转分针. 秒针每移动10秒,分钟移动的角度为1度
/*------------------------------------------------------------------------
g_tRTC.Hour%12 是把 24 小时制式转化为 12 小时制,*30是因为时针每小时运行 30 度,
((sTime.Minutes /10)*5) 这句是分钟每移动10分钟,小时时针移动 5 度
--------------------------------------------------------------------------*/
t2 = 360 - (((g_tRTC.Hour)%12) * 30) - ((g_tRTC.Min /10)*5);
GUI_MEMDEV_Select( _ClockParm->hMem1_ClockDest );
GUI_MEMDEV_Write( _ClockParm->hMem1_ClockLcd ); // 将给定存储设备的内容写入当前选定的存储设备中,
// 即hMem1_ClockLcd -> hMem1_ClockDest
StreamBitmapDisp( "0:/ICON/Clock_Icon/bk_blue2.dta", 0, 28 );
// GUI_BMP_ShowBkPicture(); // 使用 emwin v5.40 ABGR 版本,需要在此处重新绘制一下背景色,否则表盘不会显示透明功能
// 如果使用单色背景色,则此处不需要,但需要吧 GUI_CreateBitmapFromStream 此函数
// 之前屏蔽的函数打开即可,切记切记 2018.07.05 sws
GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[0], _ClockParm->hMem1_ClockDest,
0, // 显示地址由 hMemDest、hMemLcd 决定
0, // 显示地址由 hMemDest、hMemLcd 决定
0, // 因为显示表盘不需要旋转,所以此次的值为0
1000);
GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[1], _ClockParm->hMem1_ClockDest,
147-15, // 显示时针计算方法,表盘的中心x坐标 - 时针的中心x坐标,偏移量
// 已经在创建时设定好的,也就是以创建时的坐标为基准
147-34,
t2 * 1000,
1000 );
GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[2], _ClockParm->hMem1_ClockDest,
147-9,
147-57,
t1 * 1000,
1000 );
GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[3], _ClockParm->hMem1_ClockDest,
147-5,
147-78,
t0 * 1000,
1000 );
GUI_MEMDEV_Select(0);
GUI_MULTIBUF_Begin();
GUI_MEMDEV_CopyToLCD( _ClockParm->hMem1_ClockDest ); // 将内容显示到 LCD 屏幕上
GUI_MULTIBUF_End();
}
/*-------------- 对话框资源列表 ---------------------------------*/
// 特别注意:对话框资源列表的第一个控件必须是框架窗口或者窗口,其它的控件都不可以是第一个
static const GUI_WIDGET_CREATE_INFO _aDialogCreateRTC[] =
{
{ WINDOW_CreateIndirect, "Window", ID_WINDOW_0, 0, 28, 800, 452, 0, 0x0, 0 },
{ TEXT_CreateIndirect, "日期", GUI_ID_TEXT0, 270, 60, 200, 20, 0,0},
{ TEXT_CreateIndirect, "时间", GUI_ID_TEXT1, 420, 60, 200, 20, 0,0},
{ TEXT_CreateIndirect, "星期", GUI_ID_TEXT2, 270, 80, 200, 20, 0,0},
{ TEXT_CreateIndirect, "闹钟", GUI_ID_TEXT3, 420, 80, 200, 20, 0,0},
{ BUTTON_CreateIndirect, "DlgBack", ID_BUTTON_0, 691, 5, 100, 56, 0, 0, 0 }, // 返回按钮
{ BUTTON_CreateIndirect, "TimeSet", ID_BUTTON_1, 0, 390, 134, 62, 0, 0, 0 }, // 时间设置按钮
};
/*******************************************************************************
*函数名称 : _cbButtonBack
*功能描述 : “返回”按钮回调函数 ID_BUTTON_0
*输入参数 : *pMsg 消息指针
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
static void _cbButtonBack( WM_MESSAGE * pMsg )
{
WM_HWIN hWin;
hWin = pMsg->hWin;
switch ( pMsg->MsgId )
{
case WM_PAINT:
if ( BUTTON_IsPressed( hWin ))
{
StreamBitmapDisp("0:/ICON/Clock_Icon/clock_back_d.dta", 0, 0 );
}
else
{
StreamBitmapDisp("0:/ICON/Clock_Icon/clock_back_u.dta", 0, 0 );
}
break;
default:
BUTTON_Callback( pMsg );
}
}
/*******************************************************************************
*函数名称 : _cbButtonSet
*功能描述 : “时间设置”按钮回调函数 ID_BUTTON_1
*输入参数 : *pMsg 消息指针
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
static void _cbButtonSet( WM_MESSAGE * pMsg )
{
WM_HWIN hWin;
hWin = pMsg->hWin;
switch ( pMsg->MsgId )
{
case WM_PAINT:
if( BUTTON_IsPressed( hWin ))
{
GUI_SetAlpha( 0xB0 );
StreamBitmapDisp( "0:/ICON/Clock_Icon/clock_set1.dta", 0, 0 );
GUI_SetAlpha( 0 );
}
else
{
StreamBitmapDisp( "0:/ICON/Clock_Icon/clock_set1.dta", 0, 0 );
}
break;
default:
BUTTON_Callback( pMsg );
}
}
/*******************************************************************************
*函数名称 : Clock_Update
*功能描述 : 更新时间
*输入参数 : *pMsg 消息指针变量
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
static void Clock_Update( WM_MESSAGE *pMsg )
{
char buf[30];
WM_HWIN hWin = pMsg->hWin;
RTC_GetTime();
RTC_GetDate();
RTC_GetAlarmA();
/* 更新时间 */
sprintf( buf, "时间: %0.2d:%0.2d:%0.2d ", g_tRTC.Hour, g_tRTC.Min, g_tRTC.Sec );
TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT1 ), buf );
/* 更新日期 */
sprintf( buf, "日期: %0.4d/%0.2d/%0.2d", g_tRTC.Year, g_tRTC.Mon, g_tRTC.Day );
TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT0 ), buf );
/* 更新星期 */
sprintf( buf, "星期: %s", ucWeekDay[g_tRTC.Week-1]);
TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT2 ), buf );
/* 更新闹钟 */
sprintf( buf, "闹钟: %0.2d:%0.2d:%0.2d ", g_tAlarm.Hour, g_tAlarm.Min, g_tAlarm.Sec );
TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT3 ), buf );
}
/*******************************************************************************
*函数名称 : InitDialogRTC
*功能描述 : 时钟对话框回调函数中的初始化消息
*输入参数 : *pMsg 消息指针变量
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
static void InitDialogRTC( WM_MESSAGE * pMsg )
{
WM_HWIN hWin = pMsg->hWin;
WM_HWIN hItem;
WM_CreateTimer( WM_GetClientWindow( hWin ), // 接受信息的窗口的句柄
0, // 用户定义的Id。如果不对同一窗口使用多个定时器,此值可以设置为零
10, // 周期,此周期过后指定窗口应收到消息
0 ); // 留待将来使用,应为0
hItem = WM_GetDialogItem( pMsg->hWin, ID_BUTTON_0 ); // “返回”
WM_SetHasTrans( hItem );
WM_SetCallback( hItem, _cbButtonBack );
hItem = WM_GetDialogItem( pMsg->hWin, ID_BUTTON_1 ); // “时钟设置”
WM_SetHasTrans( hItem );
WM_SetCallback( hItem, _cbButtonSet );
TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT0 ), &GUI_FontHZHT16 ); // "日期"
TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT1 ), &GUI_FontHZHT16 ); // "时间"
TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT2 ), &GUI_FontHZHT16 ); // "星期"
TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT3 ), &GUI_FontHZHT16 ); // "闹钟"
GUI_MEMDEV_RTC_ClockInit();
}
/*******************************************************************************
*函数名称 : _cbCallbackRTC
*功能描述 : 回调函数
*输入参数 : *pMsg 消息指针变量
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
static void _cbCallbackRTC( WM_MESSAGE * pMsg )
{
int NCode, Id;
WM_HWIN hWin = pMsg->hWin;
GUI_RECT rRTC = {18, 28+79, 294+18-1, 294+28+79-1};
switch ( pMsg->MsgId )
{
case WM_PRE_PAINT: // WM_PAINT 消息发出前,WM 将此消息发送到窗口
/*--------------------------------------------------------------
一般的内存设备动画函数不使用多重缓冲。但在某些情况下,启用多个缓冲区是有意义的。
如果启用动画函数在显示器上绘制内存设备之前 / 之后使用 GUI_MULTIBUF_Begin() 和
GUI_MULTIBUF_Begin()。
-----------------------------------------------------------------*/
GUI_MULTIBUF_Begin();
break;
case WM_PAINT:
{
GUI_SetBkColor( GUI_BLACK );
GUI_Clear();
StreamBitmapDisp( "0:/ICON/Clock_Icon/bk_blue2.dta", 0, 0 ); // 背景
Clock_DrawDisp(); // 更新时钟表盘
break;
}
case WM_POST_PAINT: // WM_PAINT 消息处理后,WM 立即将此消息发送到窗口
/*--------------------------------------------------------------
一般的内存设备动画函数不使用多重缓冲。但在某些情况下,启用多个缓冲区是有意义的。
如果启用动画函数在显示器上绘制内存设备之前 / 之后使用 GUI_MULTIBUF_Begin() 和
GUI_MULTIBUF_Begin()。
-----------------------------------------------------------------*/
GUI_MULTIBUF_End();
break;
case WM_TIMER: // 定时1ms更新一次时间
WM_InvalidateRect( hWin, &rRTC ); // 使窗口的指定矩形区域无效
Clock_Update( pMsg ); // 更新时间
WM_RestartTimer( pMsg->Data.v, 1000 ); // 重新启动定时器
break;
case WM_INIT_DIALOG:
InitDialogRTC( pMsg ); // 时钟对话框回调函数中的初始化消息
break;
case WM_KEY:
switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key )
{
case GUI_KEY_ESCAPE:
GUI_EndDialog( hWin, 1 );
break;
case GUI_KEY_ENTER:
GUI_EndDialog( hWin, 0 );
break;
}
break;
case WM_NOTIFY_PARENT:
Id = WM_GetId( pMsg->hWinSrc );
NCode = pMsg->Data.v;
switch ( Id )
{
case ID_BUTTON_0: // "返回"按钮,此例子未使用
switch( NCode )
{
case WM_NOTIFICATION_CLICKED:
//GUI_EndDialog( hWin, 0);
break;
}
break;
case ID_BUTTON_1: // "时间设置"
switch( NCode )
{
case WM_NOTIFICATION_CLICKED:
App_SetTimeAlarm(); // 创建设置时间/闹钟对话框
break;
}
break;
}
break;
default:
WM_DefaultProc( pMsg );
}
}
/*******************************************************************************
*函数名称 : MainTask_Calendar01
*功能描述 : 时钟GUI主函数
*输入参数 : 无
*输出参数 : 无
*返 回 值 : 无
-------------------------------------------------------------------------------*/
void MainTask_Calendar01(void)
{
GUI_CURSOR_Show();
GUI_SetBkColor( GUI_BLACK );
GUI_Clear();
// 创建时钟对话框
GUI_CreateDialogBox( _aDialogCreateRTC, GUI_COUNTOF(_aDialogCreateRTC), &_cbCallbackRTC, 0, 0, 0 );
while(1)
{
GUI_Delay(10);
}
}
|
|