vc mscomm串口通信使用了CButtonST按钮类软件分析
使用了mscomm串口控件,
使用了CButtonST按钮类,
使用CDigitalClock类设置时间。
使用静态文本框实现了系统时间的显示控件,引入按钮文件BtnST.cpp,BtnST中使用了 BCMenu类。
对话框背景色及字体颜色设置,
在初始化实例中设置:
CDoorControlApp theApp;///// // CDoorControlApp initialization BOOL CDoorControlApp::InitInstance() {AfxEnableControlContainer();// Standard initialization// If you are not using these features and wish to reduce the size// of your final executable, you should remove from the following// the specific initialization routines you do not need. #ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL #elseEnable3dControlsStatic(); // Call this when linking to MFC statically #endif// SetDialogBkColor(RGB(245,250,190),RGB(0,0,250));//设置对话框的背景色及字体颜色,前面为背景色,后面是字体颜色 CDoorControlDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK }else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel }// Since the dialog has been closed, return FALSE so that we exit the// application, rather than start the application's message pump.return FALSE; }
主对话框头文件中:
class CDoorControlDlg : public CDialog { // Construction public:char ConvertHexChar(char ch);//转换字符->十六进制int String2Hex(CString str, CByteArray &senddata);//字符串->十六进制void EableSetting(BOOL able);HICON m_hIcon_comoff;//关闭串口图标HICON m_hIcon_comon;//打开串口图标BOOL m_bcomonoff;//串口状态标志
整个程序文件:
使用了 BCMenu类,CDigitalClock类
图标是图片控件:
文本框控件:属性:
串口控件属性:
按钮控件,在主对话框初始化函数中,用到按钮类的对话框的头文件中要引入#include "BtnST.h"文件
//按钮的设置m_btn_com.SubclassDlgItem(IDC_BTN_ONOFF,this);m_btn_com.SetIcon(IDI_ICON_COMOF);//图标// m_btn_com.SetFlat(FALSE);m_btn_com.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(208,100,208)); //颜色m_btn_com.SetColor(CButtonST::BTNST_COLOR_BK_FOCUS, RGB(208,208,208));m_btn_com.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 10);
通过按钮类:CButtonST::,来设置按钮各种状态时候的背景颜色,
按钮控件要继承自 CButtonST
// CDoorControlDlg dialog #include "BtnST.h" #include "DigitalClock.h" #include "Management.h"class CDoorControlDlg : public CDialog { // Construction public:char ConvertHexChar(char ch);//转换字符->十六进制int String2Hex(CString str, CByteArray &senddata);//字符串->十六进制void EableSetting(BOOL able);HICON m_hIcon_comoff;//关闭串口图标HICON m_hIcon_comon;//打开串口图标BOOL m_bcomonoff;//串口状态标志CDoorControlDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CDoorControlDlg)enum { IDD = IDD_DOORCONTROL_DIALOG };CDigitalClock m_digital_clock;CButtonST m_btn_lookback;CButtonST m_btn_loadsys;CButtonST m_btn_manage;//手动添加变量定义CStatic m_ctrlIconOpenoff;CButtonST m_btn_receclr;CButtonST m_btn_send;
添加了一个按钮,然后手动设置变量 CButtonST m_onbuton1;
按钮类的 头文件中引入了#include "BCMenu.h"文件。
// Uncomment the following 2 lines to enable support for BCMenu class #define BTNST_USE_BCMENU #include "BCMenu.h"// Uncomment the following line to enable support for sound effects #define BTNST_USE_SOUND#if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000
对话框初始化函数中,添加按钮的设置函数:
m_onbutton1.SubclassDlgItem(IDC_BUTTON1,this);m_onbutton1.SetIcon(IDI_ICON_ADD);m_onbutton1.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(208,208,208)); m_onbutton1.SetColor(CButtonST::BTNST_COLOR_BK_FOCUS, RGB(208,208,208));m_onbutton1.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);
实现效果:
完成按钮的设置使用。
打开串口按钮:
// TODO: Add extra initialization hereSetTimer(1,10,NULL);//获取系统时间并显示到静态文本框//打开串口按钮的设置m_btn_com.SubclassDlgItem(IDC_BTN_ONOFF,this);m_btn_com.SetIcon(IDI_ICON_COMOF);//图标 // m_btn_com.SetFlat(FALSE);m_btn_com.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(208,100,208)); //颜色m_btn_com.SetColor(CButtonST::BTNST_COLOR_BK_FOCUS, RGB(208,208,208));m_btn_com.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 10);//串口状态图标
列表框的样式属性:
列表框添加了变量后:
void CManagement::DoDataExchange(CDataExchange* pDX) {CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CManagement) // DDX_Control(pDX, IDC_BUN_DELET, m_btn_delet); DDX_Control(pDX, IDC_LIST, m_list);//}}AFX_DATA_MAP }
在对话框的初始化函数中设置列表框样式等,添加初始化数据:
// CManagement message handlers BOOL CManagement::OnInitDialog() {CDialog::OnInitDialog();// TODO: Add extra initialization herem_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);//样式m_list.SetBkColor(RGB(247,247,255));//控件背景色m_list.SetTextColor(RGB(0,0,255));//文本色m_list.SetTextBkColor(RGB(247,247,255));//文本的背景色//列表框每列的标题,属性设置m_list.InsertColumn(0, "卡号", LVCFMT_LEFT, 120);//第一列m_list.InsertColumn(1, "姓名", LVCFMT_LEFT, 90);//第二列m_list.InsertColumn(2, "权限", LVCFMT_LEFT, 180);//第三列m_list.InsertColumn(3, "最近使用时间", LVCFMT_LEFT, 200);//第四列//第一行m_list.InsertItem(0,"15870295");//第一列m_list.SetItemText(0,1,"小陈");//第二列m_list.SetItemText(0,2,"1,2,3,4,5");//第三列m_list.SetItemText(0,3,"2011,4,20 23:22:11");//第四列//第二行m_list.InsertItem(1,"02112126");m_list.SetItemText(1,1,"小论");m_list.SetItemText(1,2,"5,6,7");m_list.SetItemText(1,3,"2011,4,21 13:02:18");//第三行m_list.InsertItem(2,"18112125");m_list.SetItemText(2,1,"陈宏论");m_list.SetItemText(2,2,"5,9");m_list.SetItemText(2,3,"2011,4,21 21:22:00");//第四行m_list.InsertItem(3,"20888103");m_list.SetItemText(3,1,"Google");m_list.SetItemText(3,2,"1,2,9");m_list.SetItemText(3,3,"2010,4,20 02:24:41");
主对话框控件的变量值,设置之后:
void CDoorControlDlg::DoDataExchange(CDataExchange* pDX) {CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CDoorControlDlg) DDX_Control(pDX, IDC_STATIC_TIME, m_digital_clock);DDX_Control(pDX, IDC_STATIC_OPENOFF, m_ctrlIconOpenoff);DDX_Text(pDX, IDC_EDIT_RECEIVE, m_receive);DDX_Text(pDX, IDC_EDIT_SEND, m_send);DDX_Control(pDX, IDC_MSCOMM1, m_mscom);DDX_Check(pDX, IDC_CHECK_AUTOSEND, m_check_autoS);DDX_Check(pDX, IDC_CHECK_HEXS, m_check_hexS);DDX_Check(pDX, IDC_CHECK_HEXR, m_check_hexR);//}}AFX_DATA_MAP }
主对话框
// CDoorControlDlg dialog CDoorControlDlg::CDoorControlDlg(CWnd* pParent /*=NULL*/): CDialog(CDoorControlDlg::IDD, pParent) {//{{AFX_DATA_INIT(CDoorControlDlg)m_receive = _T("");//接收的字符串m_send = _T("");//发送的字符串m_check_autoS = FALSE;//自动发送m_check_hexS = FALSE;//十六进制发送m_check_hexR = FALSE;//十六进展接收//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);m_bcomonoff=FALSE;//串口状态标志位串口处于关闭状态 }
主对话框初始化函数中;
启动定时器,按钮图标和颜色设置,串口状态图标资源引入,设置主对话框显示的标题,
给组合框控件添加串口号,选择默认串口号。
// TODO: Add extra initialization hereSetTimer(1,10,NULL);//按钮的设置m_btn_com.SubclassDlgItem(IDC_BTN_ONOFF,this);m_btn_com.SetIcon(IDI_ICON_COMOF);//图标 // m_btn_com.SetFlat(FALSE);m_btn_com.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(208,100,208)); //颜色m_btn_com.SetColor(CButtonST::BTNST_COLOR_BK_FOCUS, RGB(208,208,208));m_btn_com.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 10);//串口状态图标m_hIcon_comon = AfxGetApp()->LoadIcon(IDI_ICON_COMLEDON); //串口指示灯打开状态图标的设置m_hIcon_comoff = AfxGetApp()->LoadIcon(IDI_ICON_COMLEDOFF);//关闭状态图标m_ctrlIconOpenoff.SetIcon(m_hIcon_comoff);//串口指示灯初始状态为关闭//设置主对话框窗口标题SetWindowText("电梯门禁系统上位机!");//串口号选择的组合框设置((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM1");//串口号选择复选框的设置((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM2");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM3");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM4");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM5");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM6");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM7");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM8");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM9");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM10");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM11");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM12");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM13");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM14");((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString("COM15");((CComboBox *)GetDlgItem(IDC_COMBO1))->SetCurSel(0);//选择默认的COMM0口 UpdateData(FALSE); //更新屏幕显示return TRUE; // return TRUE unless you set the focus to a control }
打开关闭串口按钮
//打开关闭串口按钮 void CDoorControlDlg::OnBtnOnoff() {/* m_mscom.SetCommPort(3); //串口1m_mscom.SetInBufferSize(1024); //设置输入缓冲区的大小,Bytes m_mscom.SetOutBufferSize(512); //设置输入缓冲区的大小,Bytes if(!m_mscom.GetPortOpen()) //打开串口{m_mscom.SetPortOpen(true); }m_mscom.SetInputMode(1); //设置输入方式为二进制方式 m_mscom.SetSettings("9600,n,8,1"); //设置波特率等参数 m_mscom.SetRThreshold(1); //为1表示有一个字符即引发事件 m_mscom.SetInputLen(0); */// TODO: Add your control notification handler code hereif(!m_bcomonoff) //第一次点击,打开串口 {if(m_mscom.GetPortOpen()){AfxMessageBox("该端口已经被打开或者被占用!");}int ComSel;ComSel=((CComboBox *)GetDlgItem(IDC_COMBO1))->GetCurSel();//串口号索引值 m_mscom.SetCommPort(ComSel+1); //选择串口号m_mscom.SetInputMode(1);//设置输入方式为二进制方式 m_mscom.SetInBufferSize(1024);//设置输入缓冲区的大小,Bytesm_mscom.SetOutBufferSize(512);//设置输出缓冲区的大小,Bytesm_mscom.SetSettings("9600,n,8,1"); //设置波特率等参数 if(!m_mscom.GetPortOpen())m_mscom.SetPortOpen(TRUE);else{AfxMessageBox("该端口已经被打开或者被占用!");}m_mscom.SetRThreshold(1);//为1表示有一个字符即引发事件m_mscom.SetInputLen(0);m_mscom.GetInput();EableSetting(FALSE);//获取串口号的 组合框不可用m_ctrlIconOpenoff.SetIcon(m_hIcon_comon);//设置串口打开图标((CButton *)GetDlgItem(IDC_BTN_ONOFF))->SetWindowText("关闭串口");//设置按钮控件文本内容m_bcomonoff=TRUE;//串口打开标志位 }else if(m_bcomonoff) //第2次点击,关闭串口 {int ComSel;ComSel=((CComboBox *)GetDlgItem(IDC_COMBO1))->GetCurSel();m_mscom.SetPortOpen(FALSE);EableSetting(TRUE);//获取串口号的 组合框可用m_ctrlIconOpenoff.SetIcon(m_hIcon_comoff);((CButton *)GetDlgItem(IDC_BTN_ONOFF))->SetWindowText("打开串口");m_bcomonoff=FALSE;} }
串口组合框使能
//串口组合框使能 void CDoorControlDlg::EableSetting(BOOL able) {GetDlgItem(IDC_COMBO1)->EnableWindow(able); //串口组合框使能UpdateData(FALSE); //更新屏幕显示 }
串口控件,接收触发函数:
BEGIN_EVENTSINK_MAP(CDoorControlDlg, CDialog)//{{AFX_EVENTSINK_MAP(CDoorControlDlg)ON_EVENT(CDoorControlDlg, IDC_MSCOMM1, 1 /* OnComm */, OnOnCommMscomm1, VTS_NONE)//}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP()
接收函数:
void CDoorControlDlg::OnOnCommMscomm1() {// TODO: Add your control notification handler code hereUpdateData(true);VARIANT variant_inp;COleSafeArray safearray_inp;long i = 0;int len;char rxdata[1000];CString tmp;switch (m_mscom.GetCommEvent()){case 2://表示接收缓冲区内有字符 {variant_inp = m_mscom.GetInput();safearray_inp = variant_inp;len = safearray_inp.GetOneDimSize();for (i = 0; i < len; i++){safearray_inp.GetElement(&i, &rxdata[i]);//转换为BYTE型数组 }for(i=0;i<len;i++) //将数组转换为Cstring型变量 {BYTE bt=*(char*)(rxdata+i); //字符型if(m_check_hexR){tmp.Format("%X ",bt); //将字符以十六进制方式送入临时变量strtemp存放,注意这里加入一个空隔m_receive+=tmp;}else tmp.Format("%c",bt); //将字符送入临时变量strtemp存放 }rxdata[i] = '\0';}if(!m_check_hexR)m_receive +=rxdata;UpdateData(false);break;default:break;}}
发送函数:
//发送数据到串口 void CDoorControlDlg::OnBtnSend() {// TODO: Add your control notification handler code hereUpdateData(true);CByteArray sendArr; WORD wLength;CByteArray hexdata;wLength = m_send.GetLength();sendArr.SetSize(wLength);for(int i =0; i<wLength; i++){sendArr.SetAt(i, m_send.GetAt(i));}if(m_check_hexS){int len=String2Hex(m_send,hexdata);m_mscom.SetOutput(COleVariant(hexdata));}elsem_mscom.SetOutput(COleVariant(sendArr));}
清除接收和发送文本框内容、
void CDoorControlDlg::OnBtnSendclr() {// TODO: Add your control notification handler code herem_send="";UpdateData(false); }void CDoorControlDlg::OnBtnRececlr() {// TODO: Add your control notification handler code herem_receive="";UpdateData(false); }
定时器函数: 系统时间获取显示,时间显示静态文本框的背景色设置,文本色设置
void CDoorControlDlg::OnTimer(UINT nIDEvent) {// TODO: Add your message handler code here and/or call defaultCTime time=CTime::GetCurrentTime();//获取时间int nHour=time.GetHour();int nMinute=time.GetMinute();int nSecond=time.GetSecond();//设置显示时间的静态文本框控件,m_digital_clock.SetBkColor(RGB(250,200,100)); //设置时间背景色m_digital_clock.SetTextColor(RGB(0,0,255));//文本色m_digital_clock.SetClock(nHour,nMinute,nSecond);//设置时钟 CDialog::OnTimer(nIDEvent); }
使用了 设置显示时间的类,来实现时间的显示:
void CDigitalClock::SetClock(int nHour, int nMinute, int nSecond) {m_nHour = nHour;m_nMinute = nMinute;m_nSecond = nSecond;DrawTimer(); }
字符串转换:
int CDoorControlDlg::String2Hex(CString str, CByteArray &senddata) {int hexdata,lowhexdata;int hexdatalen=0;int len=str.GetLength();senddata.SetSize(len/2);for(int i=0;i<len;){char lstr,hstr=str[i];if(hstr==' '){i++;continue;}i++;if(i>=len)break;lstr=str[i];hexdata=ConvertHexChar(hstr);lowhexdata=ConvertHexChar(lstr);if((hexdata==16)||(lowhexdata==16))break;else hexdata=hexdata*16+lowhexdata;i++;senddata[hexdatalen]=(char)hexdata;hexdatalen++;}senddata.SetSize(hexdatalen);return hexdatalen;}
十六进制:
char CDoorControlDlg::ConvertHexChar(char ch) {//这是一个将字符转换为相应的十六进制值的函数//功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1if((ch>='0')&&(ch<='9'))return ch-0x30;else if((ch>='A')&&(ch<='F'))return ch-'A'+10;else if((ch>='a')&&(ch<='f'))return ch-'a'+10;else return (-1);}
清除数据:
//清除发送 void CDoorControlDlg::OnBtnSendclr() {// TODO: Add your control notification handler code herem_send="";UpdateData(false); } //清除接收 void CDoorControlDlg::OnBtnRececlr() {// TODO: Add your control notification handler code herem_receive="";UpdateData(false); }
几个按钮的响应:
//管理人员信息 void CDoorControlDlg::OnBtnAdmin() {// TODO: Add your control notification handler code here CManagement dlg;dlg.DoModal(); } //启动系统 void CDoorControlDlg::OnBtnLoadsys() {// TODO: Add your control notification handler code hereMessageBox("这部分还没加!"); } //查询历史记录 void CDoorControlDlg::OnBtnLookback() {// TODO: Add your control notification handler code hereMessageBox("这部分还没加!"); }
单选框的实现:没有实现代码。
////十六进制接收 void CDoorControlDlg::OnCheckHexr() {// TODO: Add your control notification handler code here // UpdateData(TRUE); } //十六进制发送 void CDoorControlDlg::OnCheckHexs() {// TODO: Add your control notification handler code here // UpdateData(TRUE); } //1s自动发送 void CDoorControlDlg::OnCheckAutosend() {// TODO: Add your control notification handler code here // UpdateData(TRUE); }
转载于:https://www.cnblogs.com/rechen/p/5085377.html
vc mscomm串口通信使用了CButtonST按钮类软件分析相关推荐
- 用VC开发串口通信dll控件
VC串口通信技术网<VC串口上位机编程方法简介>介绍了串口编程的常见方法,其中就有使用串口dll控件的方法,dll是一种动态链接库,使用起来非常方便. 本文利用VC编程工具,对Window ...
- VC++6.0上实现PC机与单片机串口通信的PC端上位机软件
1.简介 我做这个的主要原因是选了一个PC和单片机的全双工串口通信作为课设题目,单片机端是用汇编语言编程且要预先下载到板子里,关于这个这里我就不多说,主要说说怎么实现PC端的上位机软件.早知道要写软件 ...
- 基于VC++开发串口通信的方法
串行通信中的关键是串行通信设备的初始化.数据的发送和接收及其实现方式. 在Dos环境下,用户可以直接对通信设备编程,可以通过查询中断的方式使用通信设备.但是Windows不提倡应用程序直接控制硬件,而 ...
- 计算机网络实验vc6实现串口通信,用vc的串口通信实验报告.docx
文档介绍: 编程实验报告实验题目:串口通信班级:学号:姓名:日期:2015-6-8一.实验要求把两台计算机的串口通过串口线连在一起,通过串口实现两台计算机通讯.可以利用高级语言.C语言编程实现,要求程 ...
- VS2010中MSCOMM 串口通信控件的注册使用
VS2010本身并不自带MSCOMM控件,因此在Win7.win8/8.1系统中使用VS2010进行串口编程时, 在COM控件一栏中没法找到. 网上解决这个问题的文章很多,但尝试了很多种方法都没有解决 ...
- RS232与串口通信的4个注意事项详解
RS232和串口通信,用于串口设备的数据采集软件,包括仪表.天平.秤或任何RS232仪器.WinWedge直接将数据捕获到Excel.Access或任何Windows应用程序或网页.它甚至可以从COM ...
- 【转】Qt串口通信专题教程
查看以前的教程:Qt编写串口通信程序全程图文讲解 查看Wincom和Lincom介绍:Qt跨平台串口通信软件Wincom与Lincom 下载软件,文档和源码:资源下载 --------------20 ...
- 手机APP开发之MIT Appinventor详细实战教程(一),利用通过蓝牙控制单片机,以及实现单片机与android设备之间的串口通信
目录 (一)前期软件准备和硬件准备 ( 二 ) 实现的思路和操作原理 ( 三) 具体的操作方法 MIT Appinventor 是编程领域较为受欢迎且适用的编程软件 ,因其操作流程和使用方法简单,一直 ...
- VS_MFC:CSerialPort串口通信
参考链接: Afx全局函数及MFC常见数据类型 CSerialport类开源地址(国人在github上托管的) CSerialPort串口类最新修正版及源码简单分析 Remon提供的串口类网址 ...
最新文章
- badboy页面脚本发生错误,解决方案
- Centos挂载硬盘
- 计算机系统基础:数字的机器表示
- java增删改查_Java程序员你真的甘心只做增删改查吗
- C#如何安全、高效地玩转任何种类的内存之Span的本质(一)。
- 7-25 朋友圈 (25 分)(详解+并查集的了解和应用)
- vue 实现横向时间轴
- python与线性代数 解线性方程组
- Clojure 的身份与状态思想
- 第二节:Web前端-ASP.NET之C#基础
- java spring 事务传播_深入理解Spring的事务传播行为
- ubuntu下用户的创建、修改
- A[1083]List Grade 水题
- 架构之美第九章-架构与设计
- Nagel-Schreckenberg(交通流)模型——python实现
- 传统数据与大数据对比
- 泰拉瑞亚 阿里云服务器搭建记录
- 如何一周之内摸清一个行业?
- 短视频直播电商抖音项目孵化流程运营带货商业计划书方案范本
- EasyExcel工具类(开箱即用)
热门文章
- Entity Framework第三篇IQueryable和list本地集合
- Linux下用多种模式实现双网卡绑定!
- 为什么不早一点告诉我?——情场篇
- Windows PowerShell 2.0创建调用脚本文件
- 汉字的动态编码与显示方案
- PrintNightmare 漏洞的补丁管用吗?安全界和微软有不同看法
- 速修复!VMware vCenter Server 所有版本受严重的 RCE 漏洞影响
- 看我如何绕过Cloudflare 的 SQL 注入过滤
- 解决 Laravel/Lumen 出现 Please provide a valid cache path 问题
- 用Unity的Animation播放Animator动画Clip