OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2344|回复: 18

除了WM_PAINT,还有其他方法在framewin的客户区绘制图像的方法吗

[复制链接]

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
发表于 2020-3-6 09:51:00 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 守望者2481632 于 2020-3-6 09:54 编辑

我用guibuilder化了一个dialog,里面只包含了一个framewin,我想在framewin的客户区显示图片,但是图片太大了,没有足够的ram空间存放图片信息,所以我想分段显示,比如图片10k,我分10次显示,每次显示1k。
于是我对dialog的回调函数进行了测试。
发现如果触发了WM_PAINT,那么整个客户区都会重新绘制,那就不符合我的期望了。
如果不触发WM_PAINT,触发自定义的通知消息,我调用画点(GUI_DrawPoint)或者画线(GUI_DrawLine)函数,都无法在framewin的客户区显示。
还望大神们指点一二

这是emwin任务函数

void emwindemo_task(void *p_arg)
{
WM_HWIN hwin1;
WM_MESSAGE Msg;

BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);
CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX);
DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX);
FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX);
HEADER_SetDefaultSkin(HEADER_SKIN_FLEX);
MENU_SetDefaultSkin(MENU_SKIN_FLEX);
MULTIPAGE_SetDefaultSkin(MULTIPAGE_SKIN_FLEX);
PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
RADIO_SetDefaultSkin(RADIO_SKIN_FLEX);
SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX);
SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX);
SPINBOX_SetDefaultSkin(SPINBOX_SKIN_FLEX);
hwin1 = CreateFramewin1();
while(1)
{
  GUI_Delay(100);
  Msg.MsgId=WM_APP_SHOW_TEXT;
  Msg.hWinSrc = WM_HBKWIN;
  WM_SendMessage(WM_GetClientWindow(hwin1),&Msg);
}
}


这是dialog的回调函数

static void _cbDialog(WM_MESSAGE * pMsg)
{
WM_HWIN hItem;
static u16 x = 200;
static u16 y = 100;
switch (pMsg->MsgId)
{
  case WM_INIT_DIALOG:
   hItem = pMsg->hWin;
   FRAMEWIN_SetTitleHeight(hItem, 30);
   FRAMEWIN_SetFont(hItem, GUI_FONT_20_ASCII);
   FRAMEWIN_SetText(hItem, "photo display area");
   FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
   FRAMEWIN_SetTextColor(hItem, 0x000000FF);
  break;
  case WM_APP_SHOW_TEXT:
   GUI_SetColor(GUI_RED);
   GUI_DrawPoint(x,y);
   x++;
   if(x >= 400)
   {
    x = 200;
    y++;
   }
   if(y>=300)
   {
    y = 100;
   }
  break;
  default:
   WM_DefaultProc(pMsg);
  break;
}
}

最佳答案

查看完整内容[请看2#楼]

打个广告算了,,关注我的github https://github.com/WZTENG 里面的TSysMcu里面的图片显示,,就是在fragment中加个window直接显示图片的
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 09:51:01 | 显示全部楼层
守望者2481632 发表于 2020-3-6 15:36
是的,就是在framewin的客户区显示图片

打个广告算了,,关注我的github
https://github.com/WZTENG
里面的TSysMcu里面的图片显示,,就是在fragment中加个window直接显示图片的
https://github.com/WZTENG
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 10:10:31 | 显示全部楼层
调用这个WM_InvalidateArea()或WM_InvalidateRect()试试
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 14:00:51 | 显示全部楼层
WZTENG 发表于 2020-3-6 10:10
调用这个WM_InvalidateArea()或WM_InvalidateRect()试试

我试了一下,使用WM_InvalidateRect 无效化部分窗口,回调函数进入WM_PAINT,然后程序就卡死了
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 14:03:05 | 显示全部楼层
守望者2481632 发表于 2020-3-6 14:00
我试了一下,使用WM_InvalidateRect 无效化部分窗口,回调函数进入WM_PAINT,然后程序就卡死了

WM_PAINT里面什么都不写会卡死嘛
https://github.com/WZTENG
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 14:23:44 | 显示全部楼层
WZTENG 发表于 2020-3-6 14:03
WM_PAINT里面什么都不写会卡死嘛

WM_PAINT里面我加入的这些代码,现在不卡死了,但是这直接重绘了整个窗口,不是我指定的窗口区域啊
case WM_PAINT:
     GUI_SetBkColor(GUI_RED);
     GUI_Clear();
break;
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 14:27:07 | 显示全部楼层
守望者2481632 发表于 2020-3-6 14:23
WM_PAINT里面我加入的这些代码,现在不卡死了,但是这直接重绘了整个窗口,不是我指定的窗口区域啊
case ...

GUI是整个屏幕,不刷新就怪了,,
https://github.com/WZTENG
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 14:30:27 | 显示全部楼层
WM_PAINT:
    xxxxxxxxx;
    WM_DefaultProc(pMsg);
break;
这样写呢
https://github.com/WZTENG
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 14:35:34 | 显示全部楼层
WZTENG 发表于 2020-3-6 14:30
WM_PAINT:
    xxxxxxxxx;
    WM_DefaultProc(pMsg);

在WM_PAINT里面需不需要调用WM_GetInvalidRect的?来获取无效化区域?我也试了,获取的无效化区域不是我指定的区域啊,搞不懂了
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 14:39:13 | 显示全部楼层
守望者2481632 发表于 2020-3-6 14:35
在WM_PAINT里面需不需要调用WM_GetInvalidRect的?来获取无效化区域?我也试了,获取的无效化区域不是我 ...

最重要的是为什么任务没有调用类似这样的延时,,不是调用GUI的延时。
OSTimeDlyHMSM(xxxxxxxx);
https://github.com/WZTENG
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 14:44:16 | 显示全部楼层
定时刷新界面应该用gui自带的定时器timer来做比较好吧
      case WM_PAINT:
          xxxxxxxxx
          if (hTimer==0) {
              hTimer = WM_CreateTimer(pMsg->hWin, 1, 500, 0);
          }
      break;
      case WM_TIMER:
//          WM_InvalidateArea(&clockRect);
//          WM_InvalidateWindow(WM_GetActiveWindow());
          WM_InvalidateRect(pMsg->hWin, &clockRect);// 5.32
//          WM_SendMessageNoPara(WM_GetActiveWindow(), WM_PAINT);
          WM_RestartTimer(pMsg->Data.v, 500);
       break;
https://github.com/WZTENG
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 14:47:16 | 显示全部楼层
WZTENG 发表于 2020-3-6 14:39
最重要的是为什么任务没有调用类似这样的延时,,不是调用GUI的延时。
OSTimeDlyHMSM(xxxxxxxx);

官方例程里面emwin任务里面没有用OSTimeDlyHMSM延时,其他任务用了的,emwin任务都是用的GUI_Delay
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 14:51:16 | 显示全部楼层
守望者2481632 发表于 2020-3-6 14:47
官方例程里面emwin任务里面没有用OSTimeDlyHMSM延时,其他任务用了的,emwin任务都是用的GUI_Delay

之前用定时器是可以完成局部定时刷新的,,试下行不行,,不行就。。。。。
https://github.com/WZTENG
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 15:16:15 | 显示全部楼层
WZTENG 发表于 2020-3-6 14:51
之前用定时器是可以完成局部定时刷新的,,试下行不行,,不行就。。。。。

项目需求是在屏幕上显示图片,但是图片太大了,没有足够的ram空间存图片,所以我每次从rom中读取1k的图片数据,然后将这1k的图片信息绘制到framewin的客户区,所以WM_PAINT的触发条件是我读取完1k图片数据,而不是定时器timeout,我现在在做实验,利用画点函数一行一行的将framewin的客户区画满,所以无效化区域的y0和y1每次画完一行加1,我定义了一个全局的GUI_RECT,给它初始化为 x0=100 y0=100 x1=200 y1=200,用WM_InvalidateRect函数(hwin,GUI_RECT);然后触发了WM_PAINT,我在WM_PAINT里面调用WM_GetInvalidRect ,读取无效化区域,读出来跟我设置的不一样,就很纳闷了
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 15:23:09 | 显示全部楼层
守望者2481632 发表于 2020-3-6 15:16
项目需求是在屏幕上显示图片,但是图片太大了,没有足够的ram空间存图片,所以我每次从rom中读取1k的图片 ...

只显示图片,,不在图上显示其实东西???
https://github.com/WZTENG
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 15:36:29 | 显示全部楼层
WZTENG 发表于 2020-3-6 15:23
只显示图片,,不在图上显示其实东西???

是的,就是在framewin的客户区显示图片
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 15:44:15 | 显示全部楼层
守望者2481632 发表于 2020-3-6 15:36
是的,就是在framewin的客户区显示图片

void winXXX() {
    WM_HWIN nWin;

    nWin = WM_CreateWindow(x,y,width,height,WM_CF_SHOW|WM_CF_STAYONTOP,NULL,0);       
    WM_SelectWindow(nWin);

    开始画图吧
   
    // 不用或退出时删掉
    // WM_DeleteWindow(nWin);
}
创建windows时可以不用回调,,直接在上面画图就行了
https://github.com/WZTENG
回复

使用道具 举报

15

主题

57

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2017-8-4
在线时间
48 小时
 楼主| 发表于 2020-3-6 17:06:49 | 显示全部楼层
WZTENG 发表于 2020-3-6 15:44
void winXXX() {
    WM_HWIN nWin;

确实可以了,谢谢,但显示刷新太慢了,我绘制一个400*300的区域要好几秒钟
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2020-3-6 17:25:16 | 显示全部楼层
守望者2481632 发表于 2020-3-6 17:06
确实可以了,谢谢,但显示刷新太慢了,我绘制一个400*300的区域要好几秒钟

任务切换时间,读取时间,图片解码等等,都会影响,慢慢优化吧
https://github.com/WZTENG
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-21 20:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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