我的第一个minigui程序

      第一次在Linux环境下编程,使用minigui做个界面显示位置和速度曲线。Windows下写过一些C程序,minigui学习了两个礼拜,研究了点Emacs,边写边学习。

      在104系统上运行,与底层FPGA通信,将其采集到的数据读入并显示。FPGA此处不谈,记录下minigui,以helloworld为例。

 

/**********************************************************************************/

#include <stdio.h>
 
#include <minigui/common.h> //包括minigui常用的宏以及数据类型的定义
#include <minigui/minigui.h> //包含全局的和通用的接口函数以及某些杂项函数的定义
#include <minigui/gdi.h> //包含minigui绘图函数的接口定义
#include <minigui/window.h> //包含窗口有关的宏、数据类型、数据接口定义以及函数接口声明
//#include <minigui/control.h> //包含libminigui中所有内建控件的接口定义

 

/*程序入口*/

int MiniGUIMain (int argc, const char* argv[]) //argc:命令行参数个数  argv参数字符串数组指针
{
    MSG Msg; //window.h中
    HWND hMainWnd;
    MAINWINCREATE CreateInfo; //描述一个主窗口的属性
    //const char* old_renderer;
 
#ifdef _MGRM_PROCESSES
    JoinLayer(NAME_DEF_LAYER , "helloworld" , 0 , 0);  //MiniGUI-Processes模式下加入层(客户端)
#endif
 
    CreateInfo.dwStyle = WS_VISIBLE | WS_BORDER | WS_CAPTION; //设置主窗口风格:可见|有边框|有标题栏
    CreateInfo.dwExStyle = WS_EX_NONE; //扩展风格:无
    CreateInfo.spCaption = "HelloWorld"; //标题
    CreateInfo.hMenu = 0; //主菜单:无
    CreateInfo.hCursor = GetSystemCursor(0); //设置主窗口的光标为系统缺省光标
    CreateInfo.hIcon = 0; //图标:无
    CreateInfo.MainWindowProc = HelloWinProc; //设置主窗口的窗口函数,所有发往该窗口的消息由该函数处理 
    CreateInfo.lx = 0; //屏幕上的位置(0,0)、(320,240)
    CreateInfo.ty = 0;
    CreateInfo.rx = 320;
    CreateInfo.by = 240;
    CreateInfo.iBkColor = COLOR_lightwhite; //背景色
    CreateInfo.dwAddData = 0; //附加数据:无

             //在窗口过程中,可以使用GetWindowAdditionalData函数获取该指针,从而获得所需要传递的参数。

    CreateInfo.hHosting = HWND_DESKTOP; //设置主窗口的托管窗口为桌面窗口
             //MiniGUI-Threads 中每个线程创建的第一个主窗口,其托管窗口必须是桌面,即 HWND_DESKTOP

            //该线程的其他窗口,必须由属于同一线程的已有主窗口作为托管窗口。

            //系统在托管窗口为 HWND_DESKTOP 时创建新的消息队列,

            //而在指定非桌面的窗口作为托管窗口时,使用该托管窗口的消息队列,

            //也就是说,同一线程中的所有主窗口应该使用同一个消息队列。

            //在调用 MiniGUIMain 之前,MiniGUI 启动自己的桌面窗口(Desktop)。
    //old_renderer = SetDefaultWindowElementRender("classic");

    hMainWnd = CreateMainWindow (&CreateInfo); //创建一个主窗口,返回值为所创建主窗口的句柄
 
    if (hMainWnd == HWND_INVALID)
        return -1;
 
    ShowWindow(hMainWnd, SW_SHOWNORMAL); //显示:参数1:所要显示的窗口句柄  参数2:显示窗口的方式(显示/隐藏)
 
    while (GetMessage(&Msg, hMainWnd)) { //参数1:要获取消息的主窗口的句柄  参数2:指向MSG结构的指针
                                      //GetMessage函数将用从消息队列中取出的消息来填充该消息结构的各个域
        TranslateMessage(&Msg); //把击键消息转换为MSG_CHAR消息,然后直接发送到窗口过程函数
        DispatchMessage(&Msg); //把消息发往该消息的目标窗口的窗口过程,让其处理。
                             //处理完消息后,应用程序的窗口函数将返回到DispatchMessage函数,再返回到应用程序代码,
                             //应用程序又从下一个GetMessage函数调用开始消息循环。
    }
 
    //SetDefaultWindowElementRenderer(old_renderer);
    MainWindowThreadCleanup (hMainWnd); //清除主窗口所使用消息队列系统资源

    return 0;
}

 

 

/*窗口函数*/

//窗口过程是一个特定类型的函数,用来接收和处理所有发送到该窗口的消息。

//每个控件类有一个窗口过程,属于同一控件类的所有控件共用同一个窗口过程来处理消息。

static int HelloWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)

//窗口过称函数,参数与MSG结构的前4个域相同 //由minigui调用,是一个回调函数
{
    HDC hdc;
    switch (message) {
        case MSG_PAINT: //屏幕输出
            hdc = BeginPaint (hWnd); //获得设备上下文句柄
            TextOut (hdc, 60, 60, "Hello world!"); //文本输出
            EndPaint (hWnd, hdc); //释放设备上下文句柄
            return 0;
 
        case MSG_CLOSE: //点击关闭按钮时
            DestroyMainWindow (hWnd); //销毁主窗口
            PostQuitMessage (hWnd); //在消息队列中投入一个MSG_QUIT消息,

                                               //当GetMessage函数取出MSG_QUIT消息时将返回0.,最终导致程序退出消息循环
            return 0;
    }
    return DefaultMainWinProc(hWnd, message, wParam, lParam); //默认处理
}

/**********************************************************************************/

以上是完整的helloworld程序,可以直接用。

 

  

接下来是对话框,有模态对话框和非模态对话框之分。

 

模态对话框就是显示之后,用户不能再切换到其他主窗口进行工作的对话框,而只能在关闭之后,才能使用其他的主窗口。MiniGUI 中,使用 DialogBoxIndirectParam 函数建立的对话框就是模态对话框。实际上,该对话框首先根据模板建立对话框,然后禁止其托管主窗口,并在主窗口的 MSG_CREATE 消息中创建控件,之后发送 MSG_INITDIALOG 消息给回调函数,最终建立一个新的消息循环,并进入该消息循环,直到程序调用 EndDialog 函数为止。

 

非模态对话框在利用对话框模板中的数据建立主窗口之后,会立即返回。使用 CreateMainWindowIndirect函数建立普通的主窗口。

  

对话框模板

MiniGUI  中,用两个结构来表示对话框模板(<minigui/window.h> ,如下所示:

 

typedef struct

{

     char*       class_name;             // control class

     DWORD       dwStyle;                // control style

     int         x, y, w, h;             // control position in dialog

     int         id;                     // control identifier

     const char* caption;                // control caption

     DWORD       dwAddData;              // additional data

     DWORD       dwExStyle;              // control extended style

} CTRLDATA;                     //用来定义控件

typedef CTRLDATA* PCTRLDATA;

 

typedef struct

{

    DWORD       dwStyle;                // dialog box style

    DWORD       dwExStyle;              // dialog box extended style

    int         x, y, w, h;             // dialog box position

    const char* caption;                // dialog box caption

    HICON       hIcon;                  // dialog box icon

    HMENU       hMenu;                  // dialog box menu

    int         controlnr;              // number of controls

    PCTRLDATA   controls;               // poiter to control array

    DWORD       dwAddData;              // addtional data, must be zero

} DLGTEMPLATE;                 //用来定义对话框本身

typedef DLGTEMPLATE* PDLGTEMPLATE;

 

        在程序中,应该首先利用 CTRLDATA  定义对话框中所有的控件,并用数组表示。控件在该数组中的顺序,也就是对话框中用户按TAB键时的控件切换顺序。然后定义对话框,指定对话框中的控件数目,并指定 DLGTEMPLATE  结构中的 controls  指针指向定义控件的数组。

例如:

static CTRLDATA ButtonCtrls[BUTTONNUM];
static DLGTEMPLATE ButtonPanel = {
    WS_VISIBLE | WS_THINFRAME,
    WS_EX_NONE, 0,0,0,0,
    "buttonlist",
    0,0,
    BUTTONNUM, ButtonCtrls,
    0
};

 

ButtonPanel.controls = ButtonCtrls;

定义完对话框模板数据后,需要定义对话框的回调函数。

 

对话框操作函数 (不一定仅在对话框中可用)

函数名称  用途  备注

DestroyAllControls  销毁所有的子窗口  

GetDlgCtrlID  根据控件句柄获取控件标识符  

GetDlgItem  根据控件标识符获取控件句柄  

GetDlgItemInt  获取控件文本并转换为整数值  

SetDlgItemInt  根据整数值设置控件文本  

GetDlgItemText  获取子控件文本  功能同 GetWindowText

GetDlgItemText2  获取子控件文本  根据文本长度自动分配内存,应用程序负责释放该内存

SetDlgItemText  设置子控件文本  功能同 SetWindowText

GetNextDlgGroupItem  获取下一个同组子控件  用于遍历同组控件,参阅 WS_GROUP 风格

GetNextDlgTabItem  获取下一个“TAB 键停止”子控件  用于TAB键游历控件,参阅WS_TABSTOP风格

SendDlgItemMessage  向子控件发送消息  功能同 SendMessage

CheckDlgButton  设置检查框子控件的选中状态  

CheckRadioButton  设置单选按钮子控件的选中状态

IsDlgButtonChecked  检查子按钮是否选中  

GetDlgDefPushButton  获取当前默认子按钮  

 

 

通用窗口操作函数

函数名称  用途  备注

UpdateWindow  立即更新某个窗口  

ShowWindow  显示或隐藏某个窗口  

IsWindowVisible  判断某个窗口是否可见  控件和主窗口均可用

EnableWindow  使能或禁止某个窗口  

IsWindowEnabled  判断某个窗口是否可用  

GetClientRect  获取窗口客户区矩形  

GetWindowRect  获取窗口矩形  屏幕坐标系中的窗口尺寸

GetWindowBkColor  获取窗口背景色  

SetWindowBkColor  设置窗口背景色  

GetWindowFont  获取窗口默认字体  

SetWindowFont  设置窗口默认字体  

GetWindowCursor  获取窗口光标  

SetWindowCursor  设置窗口光标  

GetWindowStyle  获取窗口风格  

GetWindowExStyle  获取窗口扩展风格  

GetFocusChild  获取拥有输入焦点的子窗口  

SetFocusChild  设置焦点子窗口  

GetWindowCallbackProc  获取窗口过程函数  

SetWindowCallbackProc  设置窗口过程函数  

GetWindowAdditionalData  获取窗口附加数据一

SetWindowAdditionalData  设置窗口附加数据一

GetWindowAdditionalData2  获取窗口附加数据二

SetWindowAdditionalData2  设置窗口附加数据二

对话框和控件在内部已使用附加数据二,保留附加数据一给应用程序使用

GetWindowCaption  获取窗口标题    通常用于主窗口

SetWindowCaption  设置窗口标题    通常用于主窗口

InvalidateRect  使窗口的给定矩形区域无效  将引发窗口重绘

GetUpdateRect  获取窗口当前的无效区域外包矩形

ClientToScreen  将窗口客户区坐标转换为屏幕坐标

ScreenToClient  将屏幕坐标转换为客户区坐标  

WindowToScreen  将窗口坐标转换为屏幕坐标  

ScreenToWindow  将屏幕坐标转换为窗口坐标  

IsMainWindow  判断给定窗口是否为主窗口  

IsControl  判断给定窗口是否为控件  

IsDialog  判断给定窗口是否为对话框  

GetParent  获取窗口的父窗口句柄  主窗口的父窗口永远为HWND_DESKTOP

GetMainWindowHandle  返回包含某个窗口的主窗口句柄  

GetNextChild  获取下一个子窗口  用于遍历某个窗口的所有子窗口

GetNextMainWindow  获取下一个主窗口句柄  用于遍历所有主窗口

GetHosting  获取某个主窗口的托管窗口  

GetFirstHosted  获取某个主窗口的第一个被托管窗口

GetNextHosted  获取下一个被托管窗口  用于遍历某个主窗口的所有被托管窗口

GetActiveWindow  获取当前活动主窗口  

SetActiveWindow  设置当前活动主窗口  

GetCapture  获取当前捕获鼠标的窗口

SetCapture  捕获鼠标

ReleaseCapture  释放鼠标

MoveWindow  移动窗口或改变窗口大小  

ScrollWindow  滚动窗口客户区的内容 

 

 

事件钩子

        通常情况下,键盘事件和鼠标事件以其正常的途径从底层设备传递到最终的应用程序窗口过程中进行处理。MiniGUI 提供了一种机制,使得我们可以在这些事件转换成相应的消息并传递到具体的窗口之前截获这些事件,然后有两种选择:让事件继续沿着正常的路径传递;或者打断事件的传递。这种机制就是钩子机制。

       钩子其实是一个回调函数,如果应用程序注册有钩子,系统就会在传递消息的中途调用这个回调函数,然后根据该回调函数的返回值来判断是否继续传递消息。

MiniGUI-Threads  MiniGUI-Standalone  模式下定义的钩子回调函数的原型如下所示:

typedef int (* MSGHOOK)(void* context, HWND dst_wnd, int msg, WPARAM wparam, LPARAM lparam);

 

其中,context  是注册钩子时传入的一个上下文信息,可以是一个指针;dst_wnd  是该消息的目标主窗口;msg 是消息标识符;wparam lparam 是消息的两个参数。钩子函数的返回值决定了系统是否继续传递事件:返回 HOOK_GOON  将继续传递事件;返回 HOOK_STOP  将停止事件的继续传递。

注册键盘和鼠标事件的钩子函数:

MSGHOOK GUIAPI RegisterKeyMsgHook (void* context, MSGHOOK hook);

MSGHOOK GUIAPI RegisterMouseMsgHook (void* context, MSGHOOK hook);

调用这两个函数时,只需传入上下文信息以及钩子回调函数的指针即可。成功时会返回先前注册的钩子函数指针。如果想注销先前注册的钩子函数,只需为 hook 参数传入 NULL RegisterKeyMsgHook (0, old_hook);

 

 

窗口重绘

一般来说,在以下情况下,MiniGUI程序的窗口过程会接收到一个MSG_PAINT消息:

1、用户移动窗口或显示窗口时,MiniGUI向先前被隐藏的窗口发送MSG_PAINT消息;

2、程序使用InvalidateRect函数来更新窗口的无效区域,这将产生一个MSG_PAINT消息;

3、程序调用UpdateWindow函数来重绘窗口;

4、覆盖程序窗口的对话框或消息框被消除;

5、下拉或弹出菜单被消除。

 

基本绘图函数

void GUIAPI SetPixel (HDC hdc, int x, int y, gal_pixel c);

void GUIAPI SetPixelRGB (HDC hdc, int x, int y, int r, int g, int b);

gal_pixel GUIAPI GetPixel (HDC hdc, int x, int y);

void GUIAPI GetPixelRGB (HDC hdc, int x, int y, int* r, int* g, int* b);

gal_pixel GUIAPI RGB2Pixel (HDC hdc, int r, int g, int b);

void GUIAPI LineTo (HDC hdc, int x, int y);

void GUIAPI MoveTo (HDC hdc, int x, int y);

void GUIAPI Circle (HDC hdc, int x, int y, int r);

void GUIAPI Rectangle (HDC hdc, int x0, int y0, int x1, int y1);

菜单

定时器

 

MiniGUI  中,应用程序可以调用 SetTimer 函数创建定时器。SetTimer  的第三个参数用来指定定时器的间隔,默认以 10 毫秒为单位。

 

当创建的定时器到期时,创建定时器时指定的窗口就会收到 MSG_TIMER 消息,并传递到期的定时器标识号。

在不需要定时器时,应用程序可以调用 KillTimer 函数删除定时器。

应用程序还可以调用 ResetTimer 函数重新设定定时器的间隔。

IsTimerInstalled 函数用于检查一个定时器是否被安装到指定的窗口上。

HaveFreeTimer 用于检测系统中是否还有可用的定时器资源。

 

 

其他一些说明

1、设备字体

2、文本输出

3、颜色

4、输入框限制

SetWindowCallbackProc(hwndedit, RestrictedEditBox); 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(struct,Class,dialog,emacs,hook,DST)