DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1191|回复: 0
打印 上一主题 下一主题

[待整理] LabWindows/CVI虚拟仪器设计技术场景与游戏设计之: 移动控件

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-12 07:21:51 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
4.1 移动控件
        4.1.1 移动控件设计方法
        在应用程序中,面板是可以拖拽的,其他控件因不具备Movable 属性而不能移动。通常情况下,在运行时,控件设计好后很少会被移动到其他位置或者改变大小尺寸,而在程序设计阶段却需要经常改变。在程序运行期间,某些控件会影响界面的美观性,希望把它们挪个位置,以使界面更完美。对于一些游戏类开发,控件的移动是必需的功能,而且需要支持键盘和鼠标移动控件。LabWindows/CVI 在…\CVIxx\toolslib\custctrl 目录下提供了movectrl.h 、movectrl.c 、movectrl.fp 、movectrl.sub 等文件,可以在运行时状态方便地拖拽控件,改变位置与大小。
         
        对于一般开发工具而言,如Visual Basic 控件具有MouseDown 事件,可在其中用全局坐标变量OldX 和OldY 记录下鼠标按下时的位置,并使全局布尔型变量标识为True 用以标志鼠标被按下。在控件的MouseMove 事件中,如果标识为True ,则使该控件的左边界在原来的基础上加上水平方向的移动量(x - OldX) ,上边界在原来的基础上加上垂直方向的移动量(y - OldY)。在MouseUp 事件中,使标识变为False,表示鼠标已松开。在LabWindows/CVI 中,由于鼠标不支持MouseDown 事件,主要采用相近的鼠标事件EVENT_MOUSE_POINTER_MOVE 和EVENT_LEFT_CLICK 来记录OldX 和OldY,为控件的鼠标拖拽操作提供了一种思路。
         
        4.1.2 移动控件程序设计
        (1)面板设计
        编写一个运行程序时,利用鼠标调整Graph 控件的大小和位置,当鼠标放置于控件内时,显示手形,此时可以按下鼠标左键移动控件,当鼠标放置于控件右侧、下侧或右下角时,显示箭头形状,按下鼠标左键拖拽控件,可改变控件的大小尺寸。控件移动采用面板回调函数实现,控件尺寸改变采用Timer 定时器控制实现。面板设计如图4-1 所示,面板中主要控件属性设置如表4-1 所示。
       

        图4-1 移动控件面板

         
        表4-1 控件属性设置表
                               
                                        常量名

                       
                               
                                        控件类型

                       
                                                                        控件的主要属性
                       
                               
                                        PANEL

                       
                               
                                        Panel

                       
                                                                        标题:移动控件回调函数:PanelCB
                       
                               
                                        GRAPH

                       
                               
                                        Graph

                       
                                                                        标题:移动控件
                       
                               
                                        TIMER

                       
                               
                                         Timer

                       
                                                                        回调函数:timer Interval:0.01
                       
         
        (2)程序源代码
        //头文件声明
        #include <cvirte.h>
        #include <userint.h>
        #include "utility.h"
        #include "移动控件.h"
        static int panelHandle;
        //主函数
        int main (int argc, char *argv[])
        {
        if (InitCVIRTE (0, argv, 0) == 0)
        return &ndash;1; /* out of memory */
        if ((panelHandle = LoadPanel (0, " 移动控件.uir", PANEL)) < 0)
        return &ndash;1;
        DisplayPanel (panelHandle);
        RunUserInterface ();
        DiscardPanel (panelHandle);
        return 0;
        }
        //面板回调函数
        int CVICALLBACK PanelCB (int panel, int event, void *callbackData,
        int eventData1, int eventData2)
        {
        int LeftButtonDown;
        int y;
        int x;
        int CtrlTop;
        int CtrlLeft;
        int CursorStyle;
        //局部静态变量,旧X、坐标值
        static int OldX = 0;
        static int OldY = 0;
        switch (event)
        {
        //鼠标移动事件
        case EVENT_MOUSE_POINTER_MOVE:
        GetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_LEFT, &CtrlLeft);
        GetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_TOP, &CtrlTop);
        // 获得鼠标绝对位置、按键等属性
        GetGlobalMouseState (&panel, &x, &y, &LeftButtonDown, NULL, NULL);
        // 当鼠标左键按下时
        if (LeftButtonDown == 1)
        {
        // 获得鼠标指针形状
        GetMouseCursor (&CursorStyle);
        if (CursorStyle == VAL_OPEN_HAND_CURSOR)
        {
        SetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_LEFT, CtrlLeft + (x &ndash; OldX));
        SetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_TOP, CtrlTop + (y &ndash; OldY));
        // 将旧X、Y 坐标值以当前新值代替
        OldX = x;
        OldY = y;
        }
        }
        break;
        //鼠标左击事件
        case EVENT_LEFT_CLICK:
        // 获得鼠标绝对位置、按键等属性
        GetGlobalMouseState (&panel, &x, &y, &LeftButtonDown, NULL, NULL);
        // 获得鼠标指针形状
        GetMouseCursor (&CursorStyle);
        // 将旧X、坐标值以当前新值代替
        if (CursorStyle == VAL_OPEN_HAND_CURSOR)
        {
        OldX = x;
        OldY = y;
        }
        break;
        //关闭面板事件
        case EVENT_CLOSE:
        QuitUserInterface (0);
        break;
        }
        return 0;
        }
        //定时器
        int CVICALLBACK timer (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2)
        {
        int CtrlWidth;
        int CtrlHeight;
        int RightButtonDown;
        int LeftButtonDown;
        int y;
        int x;
        int CursorStyle;
        //定义为局部静态变量,始终保存鼠标指针形状参数
        static int MouseStyle = 0;
        switch (event)
        {
        case EVENT_TIMER_TICK:
        GetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_HEIGHT, &CtrlHeight);
        GetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_WIDTH, &CtrlWidth);
        //获得鼠标相对位置、按键等属性
        GetRelativeMouseState (panel, PANEL_GRAPH, &x, &y, &LeftButtonDown, &RightButton
        Down, NULL);
        //判断鼠标相对控件位置
        if (x > CtrlWidth &ndash; 5 && x < CtrlWidth + 5 && y > 0 && y < CtrlHeight)
        {
        //左右箭头
        MouseStyle = 1;
        }
        if (y > CtrlHeight &ndash; 5 && y < CtrlHeight + 5 && x > 0 && x < CtrlWidth)
        {
        //上下箭头
        MouseStyle = 2;
        }
        if (x > CtrlWidth &ndash; 5 && x < CtrlWidth + 5 && y > CtrlHeight &ndash; 5 && y < CtrlHeight + 5)
        {
        //"↖↘"箭头
        MouseStyle = 3;
        }
        if (x > 5 && x < CtrlWidth &ndash; 5 && y > 5 && y < CtrlHeight &ndash; 5)
        {
        //手型箭头
        MouseStyle = 4;
        }
        if (x < 0 || x > CtrlWidth + 5 || y < 0 || y > CtrlHeight + 5)
        {
        //默认箭头
        MouseStyle = 0;
        }
        //设置鼠标指针形状
        if (LeftButtonDown == 0)
        {
        switch (MouseStyle) {
        case 0:
        SetMouseCursor (VAL_DEFAULT_CURSOR);
        break;
        case 1:
        SetMouseCursor (VAL_SIZE_EW_CURSOR); break;
        case 2:
        SetMouseCursor (VAL_SIZE_NS_CURSOR);
        break;
        case 3:
        SetMouseCursor (VAL_SIZE_NW_SE_CURSOR); break;
        case 4:
        SetMouseCursor (VAL_OPEN_HAND_CURSOR);
        break;
        }
        } // 设置控件大小
        if (LeftButtonDown == 1 && x > 0 && y > 0) {
        GetMouseCursor (&CursorStyle); switch (CursorStyle)
        { case VAL_SIZE_EW_CURSOR:
        SetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_WIDTH, x); break;
        case VAL_SIZE_NS_CURSOR:
        SetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_HEIGHT, y);
        break;
        case VAL_SIZE_NW_SE_CURSOR:
        SetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_WIDTH, x); SetCtrlAttribute (panelHandle, PANEL_GRAPH, ATTR_HEIGHT, y);
        break;
        }
        } break;
        } return 0;
        }
         
         
        3:程序注释
        ① GetGlobalMouseState 函数获得鼠标状态信息,包括获得相对于屏幕的鼠标坐标。函数原型为:
        int GetGlobalMouseState (int *Panel_Handle, int *XCoordinate, int *YCoordinate, int *Left_Button_ Down, int *Right_Button_Down, int *Key_Modifiers);
        *Panel_Handle :鼠标经过的面板句柄。如果鼠标没有经过面板,则值为0。如果不需要返回参数值,可输入NULL。
        *XCoordinate:X轴坐标(相对于屏幕左侧边缘)。如果不需要返回参数值,可输入NULL。
        *YCoordinate:Y轴坐标(相对于屏幕顶部)。如果不需要返回参数值,可输入NULL。
        *Left_Button_Down :鼠标左键状态。0 表示左键弹起,1 表示左键按下。如果不需要返回参数值,可输入NULL 。
        *Right_Button_Down :鼠标右键状态。0 表示右键弹起,1 表示右键按下。如果不需要返回参数值,可输入NULL 。
        *Key_Modifiers :是否有Ctrl 、Alt 和Shift 键被按下,如果没有键被按下时值为0,否则为VAL_MENUKEY_MODIFIER 、VAL_UNDERLINE_MODIFIER 、VAL_SHIFT_MODIFIER 和VAL_SHIFT_AND_MENUKEY 按位或操作结果。常量说明如表4-2 所示。
         
        表4-2 Key Modifiers 参数表
                               
                                        常量名

                       
                               
                                        常量值

                       
                               
                                        说明

                       
                               
                                        VAL_MENUKEY_MODIFIER

                       
                               
                                        1L << 16

                       
                               
                                        Ctrl 键

                       
                               
                                        VAL_UNDERLINE_MODIFIER

                       
                               
                                        1L << 17

                       
                               
                                        Alt 键

                       
                               
                                        VAL_SHIFT_MODIFIER

                       
                               
                                        1L << 18

                       
                               
                                        Shift 键

                       
                               
                                        VAL_SHIFT_AND_MENUKEY

                       
                               
                                        (1L << 18) | (1L << 16)

                       
                               
                                        Shift 键+Ctrl 键

                       
         
        ② GetMouseCursor 函数返回鼠标指针形状参数。函数原型为:
        int GetMouseCursor (int *Mouse_Cursor_Style);
        *Mouse_Cursor_Style :鼠标指针形状值。指针形状说明如表4-3 所示。
         
        表4-3 鼠标指针参数表
                               
                                        常量名

                       
                               
                                        常量值

                       
                               
                                        VAL_DEFAULT_CURSOR

                       
                               
                                        &ndash;1L

                       
                               
                                        VAL_CHECK_CURSOR

                       
                               
                                        11L

                       
                               
                                        VAL_CROSS_HAIR_CURSOR

                       
                               
                                        12L

                       
                               
                                        VAL_BOX_CURSOR

                       
                               
                                        13L

                       
                               
                                        VAL_POINTING_FINGER_CURSOR

                       
                               
                                        14L

                       
                               
                                        VAL_OPEN_HAND_CURSOR

                       
                               
                                        15L

                       
                               
                                        VAL_QUESTION_MARK_CURSOR

                       
                               
                                        16L

                       
                               
                                        VAL_HOUR_GLASS_CURSOR

                       
                               
                                        17L

                       
                               
                                        VAL_HIDDEN_CURSOR

                       
                               
                                        18L

                       
                               
                                        VAL_SIZE_NS_CURSOR

                       
                               
                                        19L

                       
                               
                                        VAL_SIZE_EW_CURSOR

                       
                               
                                        20L

                       
                               
                                        VAL_SIZE_NW_SE_CURSOR

                       
                               
                                        21L

                       
                               
                                        VAL_SIZE_NE_SW_CURSOR

                       
                               
                                        22L

                       
                               
                                        VAL_CLOSED_HAND_CURSOR

                       
                               
                                        23L

                       
                               
                                        VAL_SIZE_EW_CURSOR_2

                       
                               
                                        26L

                       
                               
                                        VAL_SIZE_NS_CURSOR_2

                       
                               
                                        27L

                       
                               
                                        VAL_MOVE_CURSOR

                       
                               
                                        28L

                       
         
        ③ GetRelativeMouseState 函数
        获得鼠标状态信息,包括获得相对于控件的鼠标坐标。如果Control_ID 为0,返回相对于面板的坐标。函数原型为:
        int GetRelativeMouseState (int Panel_Handle, int Control_ID, int *XCoordinate, int *YCoordinate, int *Left_Button_Down, int *Right_Button_Down, int *Key_Modifiers);
         
        ④ SetMouseCursor 函数设置鼠标指针形状参数。函数原型为:
        int SetMouseCursor (int Mouse_Cursor_Style);
         
        ⑤ 控件拖拽操作
        在LabWindows/CVI 中,虽然有鼠标的拖拽操作函数,但主要是针对文件拖拽功能的EnableDragAndDrop 函数,需要为面板回调函数安装EVENT_FILESDROPPED 事件,很难用于控件的拖拽操作。在本例程中,利用GetGlobalMouseState 函数查询鼠标左键是否被按下,利用面板EVENT_MOUSE_POINTER_MOVE 事件来响应控件拖拽操作,并确定控件的新位置。对于EVENT_LEFT_CLICK 事件,只是在鼠标点击时会产生触发响应,而EVENT_MOUSE_POINTER_ MOVE 事件只要鼠标移动就会产生,具有实时响应特性,因此,拖拽操作的主要过程可以写在该事件中。EVENT_LEFT_CLICK 事件的作用是更新一次点击操作完成后的新的X和Y轴坐标。另外,改变控件大小的代码写到了Timer 控件里,并且,当鼠标处于控件的左侧边缘、下部边缘以及左下角时,鼠标会显示不同的形状,当按下鼠标时,通过实时响应鼠标相对于控件的坐标位置来调整控件的尺寸大小。
         
        (4)运行效果图
        点击工具栏中的Debug Project 按钮,程序开始运行,其效果如图4-2 所示。
       

        4-2 运行效果图

         

        相关阅读
        《虚拟仪器技术,将“软件就是仪器”进行到底!》
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2025-8-1 20:23 , 耗时 0.102013 秒, 21 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

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