Allegro学习笔记十六

PS:因为第13游戏杆、14播放波形文件、15播放MIDI 我这里缺设备,没办法测试。而且这3个方面与我现在的工作暂时没有特别大的联系,就条过了。但是不想在编排上出现混乱,所以暂时没有学习笔记十三、十四、十五~

http://wiki.allegro.cc/AllegroExamples 以上是英文例子站点。

by Shawn Hargreaves,allegro的作者

目录: 1 Allegro 例子

1.1 exhello
1.2 exmem
1.3 expat
1.4 expal
1.5 exflame
1.6 exbuf
1.7 exflip
1.8 exfixed
1.9 exfont
1.10exmouse
1.11extimer
1.12exkeys
1.16exgui

/*
 *    Example program for the Allegro library, by Elias Pschernig.
 *
 *    这个例子展示了如何使用 GUI.
 *    通过简单的对话框操作实现了一个文本或一个位图到
 *    到更加复杂的多选列表, Allegro提供了一个框架
 *    可以自定义以便适合你的工程。
 */


#include <stdio.h>

#include <allegro.h>
#include "example.h"


/* maximum number of bytes a single (Unicode) character can have */
/* 定义了单字符(Unicode)的最大字节数 */
#define MAX_BYTES_PER_CHAR 4

/* for the d_edit_proc object */
/* d_edit_proc对象相关定义 */
#define LEN 32
char the_string[(LEN + 1) * MAX_BYTES_PER_CHAR] = "Change Me!";

/* for the d_text_box_proc object */
/* d_text_box_proc对象相关定义 */
char the_text[] =
   "I'm text inside a text box./n/n"
   "I can have multiple lines./n/n"
   "If I grow too big to fit into my box, I get a scrollbar to "
   "the right, so you can scroll me in the vertical direction. I will never "
   "let you scroll in the horizontal direction, but instead I will try to "
   "word wrap the text.";

/* for the multiple selection list */
/* 多选列表相关定义 */
char sel[10];

/* for the example bitmap */
/* 示例位图相关定义 */
DATAFILE *datafile;

 

/* callback function to specify the contents of the listbox */
/* listbox中指定内容的回调函数 */
char *listbox_getter(int index, int *list_size)
{
   static char *strings[] =
   {
      "Zero",  "One",   "Two",   "Three", "Four",  "Five",
      "Six",   "Seven", "Eight", "Nine",  "Ten"
   };

   if (index < 0) {
      *list_size = 11;
      return NULL;
   }
   else {
      return strings[index];
   }
}

 

/* Used as a menu-callback, and by the quit button. */
/* 在菜单型的对象上使用的回调函数,这里是"退出"按钮 */
int quit(void)
{
   if (alert("Really Quit?", NULL, NULL, "&Yes", "&No", 'y', 'n') == 1)
      return D_CLOSE;
   else
      return D_O_K;
}

 

/* A custom dialog procedure, derived from d_button_proc. It intercepts
 * the D_CLOSE return of d_button_proc, and calls the function in dp3.
 */
/* 一个自定义的对话框过程,通过d_button_proc来驱动,它截获来自d_button_proc
 * 的返回值D_CLOSE,并且在dp3中调用此函数
 */
int my_button_proc(int msg, DIALOG *d, int c)
{
   int ret = d_button_proc(msg, d, c);
   if (ret == D_CLOSE && d->dp3)
      return ((int (*)(void))d->dp3)();
   return ret;
}

 

/* Our about box. */
/* "about"对话框 */
int about(void)
{
   alert("* exgui *",
         "",
         "Allegro GUI Example",
         "Ok", 0, 0, 0);
   return D_O_K;
}

 

/* Another menu callback. */
/* 其他的菜单回调函数 */
int menu_callback(void)
{
   char str[256];

   ustrzcpy(str, sizeof str, active_menu->text);
   alert("Selected menu item:", "", ustrtok(str, "/t"), "Ok", NULL, 0, 0);
   return D_O_K;
}

 

/* Menu callback which toggles the checked status. */
/* 关于checkbox的回调函数 */
int check_callback(void)
{
   active_menu->flags ^= D_SELECTED;
   if (active_menu->flags & D_SELECTED)
      active_menu->text = "Checked";
   else
      active_menu->text = "Unchecked";

   alert("Menu item has been toggled!", NULL, NULL, "Ok", NULL, 0, 0);
   return D_O_K;
}

 

/* the submenu */
/* 子菜单 */
MENU submenu[] =
{
   { "Submenu",            NULL,   NULL, D_DISABLED,       NULL  },
   { "",                   NULL,   NULL, 0,                NULL  },
   { "Checked",  check_callback,   NULL, D_SELECTED,       NULL  },
   { "Disabled",           NULL,   NULL, D_DISABLED,       NULL  },
   { NULL,                 NULL,   NULL, 0,                NULL  }
};


/* the first menu in the menubar */
/* 菜单栏的第1个菜单 */
MENU menu1[] =
{
   { "Test &1 /t1", menu_callback,  NULL,      0,  NULL  },
   { "Test &2 /t2", menu_callback,  NULL,      0,  NULL  },
   { "&Quit /tq/Esc",        quit,  NULL,      0,  NULL  },
   { NULL,                   NULL,  NULL,      0,  NULL  }
};

 

/* the second menu in the menubar */
/* 菜单栏的第2个菜单 */
MENU menu2[] =
{
   { "&Test",    menu_callback,     NULL,   0,  NULL  },
   { "&Submenu",          NULL,  submenu,   0,  NULL  },
   { NULL,                NULL,     NULL,   0,  NULL  }
};

 

/* the help menu */
/* 帮助菜单 */
MENU helpmenu[] =
{
   { "&About /tF1",     about,  NULL,      0,  NULL  },
   { NULL,               NULL,  NULL,      0,  NULL  }
};

 

/* the main menu-bar */
/* 主菜单栏 */
MENU the_menu[] =
{
   { "&First",  NULL,   menu1,          0,      NULL  },
   { "&Second", NULL,   menu2,          0,      NULL  },
   { "&Help",   NULL,   helpmenu,       0,      NULL  },
   { NULL,      NULL,   NULL,           0,      NULL  }
};

 

extern int info1(void);
extern int info2(void);
extern int info3(void);

#define LIST_OBJECT     26
#define TEXTLIST_OBJECT 27
#define SLIDER_OBJECT   29
#define BITMAP_OBJECT   32
#define ICON_OBJECT     33

/* here it comes - the big bad ugly DIALOG array for our main dialog */
/* 让我们开始吧 - 一个为我们的主对话框而建立的巨大的、糟糕的、丑陋的对话框数组 */
DIALOG the_dialog[] =
{
   /* 对话框处理函数    left  top   width hgt  fg  bg  hotkey  对象状态   对话框需

要的数据对象,int d1,d2  void* dp dp2 dp3 */
   /* (dialog proc)     (x)   (y)   (w)   (h) (fg)(bg) (key) (flags)     (d1) (d2) 

  (dp)                   (dp2) (dp3) */
  
   /* this element just clears the screen, therefore it should come before the

others */
   /* 这个元素用来清屏,因此它应该在所有其他元素之前 */
   { d_clear_proc,        0,   0,    0,    0,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  },
  
   /* these just display text, either left aligned, centered, or right aligned */
   /* 这些用来显示文本,包括居左,居中,或居右 */
   { d_text_proc,         0,  20,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_text_proc",          NULL, NULL  },
   { d_ctext_proc,      318,  20,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_ctext_proc",         NULL, NULL  },
   { d_rtext_proc,      636,  20,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_rtext_proc",         NULL, NULL  },
  
   /* lots of descriptive text elements */
   /* 许多描述文本元素(就是label) */
   { d_text_proc,         0,   0,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_menu_proc->",        NULL, NULL  },
   { d_text_proc,         0,  40,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_button_proc->",      NULL, NULL  },
   { d_text_proc,         0,  70,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_check_proc->",       NULL, NULL  },
   { d_text_proc,         0, 100,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_radio_proc->",       NULL, NULL  },
   { d_text_proc,         0, 130,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_edit_proc->",        NULL, NULL  },
   { d_text_proc,         0, 150,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_list_proc->",        NULL, NULL  },
   { d_text_proc,         0, 200,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_text_list_proc->",   NULL, NULL  },
   { d_text_proc,         0, 250,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_textbox_proc->",     NULL, NULL  },
   { d_text_proc,         0, 300,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_slider_proc->",      NULL, NULL  },
   { d_text_proc,         0, 330,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_box_proc->",         NULL, NULL  },
   { d_text_proc,         0, 360,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_shadow_box_proc->",  NULL, NULL  },
   { d_text_proc,         0, 390,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_keyboard_proc. Press F1 to see me trigger the about box.", NULL, NULL  },
   { d_text_proc,         0, 410,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_clear_proc. I draw the white background.", NULL, NULL  },
   { d_text_proc,         0, 430,    0,    0,   0,  0,    0,      0,       0,   0, 

  "d_yield_proc. I make us play nice with the OS scheduler.", NULL, NULL  },
   { d_rtext_proc,      636,  40,    0,    0,   0,  0,    0,      0,       0,   0, 

  "<-d_bitmap_proc",      NULL, NULL  },
   { d_rtext_proc,      636,  80,    0,    0,   0,  0,    0,      0,       0,   0, 

  "<-d_icon_proc",        NULL, NULL  },
  
   /* a menu bar - note how it auto-calculates its dimension if they are not given

*/
   /* 一个菜单栏 - 注意:如果没有给出尺寸,他是如何自动计算出自己的尺寸 */
   { d_menu_proc,       160,   0,    0,    0,   0,  0,    0,      0,       0,   0, 

  the_menu,               NULL, NULL  },
  
   /* some more GUI elements, all of which require you to specify their dimensions

*/
   /* 其他的GUI元素,他们全部都需要你给出尺寸 */
   { d_button_proc,     160,  40,  160,   20,   0,  0,  't',      0,       0,   0, 

  "&Toggle Me!",          NULL, NULL  },
   { d_check_proc,      160,  70,  160,   20,   0,  0,  'c',      0,       0,   0, 

  "&Check Me!",           NULL, NULL  },
   { d_radio_proc,      160, 100,  160,   19,   0,  0,  's',      0,       0,   0, 

  "&Select Me!",          NULL, NULL  },
   { d_radio_proc,      320, 100,  160,   19,   0,  0,  'o',      0,       0,   0, 

  "&Or Me!",              NULL, NULL  },
   { d_edit_proc,       160, 130,  160,    8,   0,  0,    0,      0,     LEN,   0, 

  the_string,             NULL, NULL  },
   { d_list_proc,       160, 150,  160,   44,   0,  0,    0,      0,       0,   0, 

  (void *)listbox_getter, sel,  NULL  },
   { d_text_list_proc,  160, 200,  160,   44,   0,  0,    0,      0,       0,   0, 

  (void *)listbox_getter, NULL, NULL  },
   { d_textbox_proc,    160, 250,  160,   48,   0,  0,    0,      0,       0,   0, 

  (void *)the_text,       NULL, NULL  },
   { d_slider_proc,     160, 300,  160,   12,   0,  0,    0,      0,     100,   0, 

  NULL,                   NULL, NULL  },
   { d_box_proc,        160, 330,  160,   20,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  },
   { d_shadow_box_proc, 160, 360,  160,   20,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  },

   /* note how we don't fill in the dp field yet, because we first need to load the

bitmap */
   /* 注意:我们还没有填充dp指向,因为首先我们需要加载一张图片(就是先加载,后使用)

*/
   { d_bitmap_proc,     480,  40,   30,   30,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  },
   { d_icon_proc,       480,  80,   30,   30,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  },
  
   /* the quit and info buttons use our customized dialog procedure, using dp3 as

callback */
   /* "退出"和"信息"按钮使用我们自定义的对话框过程,使用dp3来回调 */
   { my_button_proc,      0, 450,  160,   20,   0,  0,  'q', D_EXIT,       0,   0, 

  "&Quit",                NULL, (void *)quit  },
   { my_button_proc,    400, 150,  160,   20,   0,  0,  'i', D_EXIT,       0,   0, 

  "&Info",                NULL, (void *)info1 },
   { my_button_proc,    400, 200,  160,   20,   0,  0,  'n', D_EXIT,       0,   0, 

  "I&nfo",                NULL, (void *)info2 },
   { my_button_proc,    400, 300,  160,   20,   0,  0,  'f', D_EXIT,       0,   0, 

  "In&fo",                NULL, (void *)info3 },

   /* the next two elements don't draw anything */
   /* 接下来的两个元素不需要绘制 */
   { d_keyboard_proc,     0,   0,    0,    0,   0,  0,    0,      0,  KEY_F1,   0, 

  (void *)about,          NULL, NULL  },
   { d_yield_proc,        0,   0,    0,    0,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  },
   { NULL,                0,   0,    0,    0,   0,  0,    0,      0,       0,   0, 

  NULL,                   NULL, NULL  }
};

 

/* These three functions demonstrate how to query dialog elements. */
/* 这3个函数展示了如何轮循对话框元素(它们并不是去轮循,而是他们实现了轮
/* 循时应该干的事情,说白了也是回调函数) */
int info1(void)
{
   char buf1[256];
   char buf2[256] = "";
   int i, s = 0, n;

   listbox_getter(-1, &n);
   /* query the list proc */
   /* 轮循列表事件 */
   for (i = 0; i < n; i++) {
      if (sel[i]) {
         uszprintf(buf1, sizeof buf1, "%i ", i);
         ustrzcat(buf2, sizeof buf2, buf1);
         s = 1;
      }
   }
   if (s)
      ustrzcat(buf2, sizeof buf2, "are in the multiple selection!");
   else
      ustrzcat(buf2, sizeof buf2, "There is no multiple selection!");
   uszprintf(buf1, sizeof buf1, "Item number %i is selected!",
      the_dialog[LIST_OBJECT].d1);
   alert("Info about the list:", buf1, buf2, "Ok", NULL, 0, 0);
   return D_O_K;
}

int info2(void)
{
   char buf[256];

   /* query the textlist proc */
   /* 轮循文本列表事件 */
   uszprintf(buf, sizeof buf, "Item number %i is selected!",
      the_dialog[TEXTLIST_OBJECT].d1);
   alert("Info about the text list:", NULL, buf, "Ok", NULL, 0, 0);
   return D_O_K;
}

int info3(void)
{
   char buf[256];

   /* query the slider proc */
   /* 轮循事件 */
   uszprintf(buf, sizeof buf, "Slider position is %i!",
     the_dialog[SLIDER_OBJECT].d2);
   alert("Info about the slider:", NULL, buf, "Ok", NULL, 0, 0);
   return D_O_K;
}

 

int main(int argc, char *argv[])
{
   char buf[256];
   int i;

   /* initialise everything */
   /* 初始化所有的一切 */
   if (allegro_init() != 0)
      return 1;
   install_keyboard();
   install_mouse();
   install_timer();

   if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
      if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) != 0) {
  set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
  allegro_message("Unable to set any graphic mode/n%s/n", allegro_error);
  return 1;
      }
   }

   /* load the datafile */
   /* 读取数据文件 */
   replace_filename(buf, argv[0], "example.dat", sizeof(buf));
   datafile = load_datafile(buf);
   if (!datafile) {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Error loading %s!/n", buf);
      return 1;
   }

   set_palette((RGB*)(datafile[THE_PALETTE].dat));

   /* set up colors */
   /* 设置颜色 */
   gui_fg_color = makecol(0, 0, 0);
   gui_mg_color = makecol(128, 128, 128);
   gui_bg_color = makecol(200, 240, 200);
   set_dialog_color(the_dialog, gui_fg_color, gui_bg_color);

   /* white color for d_clear_proc and the d_?text_procs */
   /* 清屏事件和文本事件将使用白色 */
   the_dialog[0].bg = makecol(255, 255, 255);
   for (i = 4; the_dialog[i].proc; i++) {
      if (the_dialog[i].proc == d_text_proc ||
          the_dialog[i].proc == d_ctext_proc ||
          the_dialog[i].proc == d_rtext_proc)
      {
         the_dialog[i].bg = the_dialog[0].bg;
      }
   }
  
   /* fill in bitmap pointers */
   /* 填充位图指针 */
   the_dialog[BITMAP_OBJECT].dp = datafile[SILLY_BITMAP].dat;
   the_dialog[ICON_OBJECT].dp = datafile[SILLY_BITMAP].dat;
  
   /* shift the dialog 2 pixels away from the border */
   /* 总是使对话框相对于边框偏移2个像素(制造阴影效果) */
   position_dialog(the_dialog, 2, 2);
  
   /* do the dialog */
   /* 执行对话框(轮循,消息机制启动之类的意思) */
   do_dialog(the_dialog, -1);

   unload_datafile(datafile); /* 关闭数据文件 */
  
   return 0;
}
END_OF_MAIN()
---------------------------------------------------------------------------------------------------------------------
小结十六:
PS:无疑这个例子是庞大的,但是它所展示的例子可能是最有用的之一。慢慢来总结。
1、#include "example.h"
它没什么好说的,实际内容如下:
#define BIG_FONT                         0        /* FONT */
#define SILLY_BITMAP                     1        /* BMP  */
#define THE_PALETTE                      2        /* PAL  */

2、DATAFILE *datafile;
它是allegro自定义的数据类型,使用特有的数据文件,可以通过针对此文件的工具grabber.exe来察看和修改它。在这里,它包括了3个部分,字体、位图、调色板。
datafile[SILLY_BITMAP].dat
这是使用datafile的方式,SILLY_BITMAP只是一个索引值,事实上可以通过.ini文件配合,从而彻底舍弃example.h,并且使我们的exe成为一个工厂--专门负责搭建界面,而.dat和.ini则是原料。
(PS:我做了次时间旅行,在我学习到笔记21的程度,我又回来丰富了下这里的小节第2点。因为我发现22exdata实际上就是这里的知识的运用。而且,GUI+config+datafile正是我所需要的,剩下的事情就是将这些知识运用到我的任务之中!老天,我找到解决方案了~)

3、也许我找到了解决问题的最快途径:修改位图部分。但实际上当我更改成一个24位位图,显示的效果显然并不理想。要理解造成这个问题的原因,需要理解2个方面:颜色深度和调色板。
一、在程序中加载24位位图的时候,使用的load_bitmap(path,palette)中会返回位图使用的PALETTE,并存在palette中以供使用。在24位色深模式下的问题是24位位图不存在调色板,因此最开始调用的set_palette(((RGB*)(datafile[THE_PALETTE].dat)))之中的颜色数据实际上和bitmap的显示无关的。因此palette实际上是NULL的,而企图使用set_palette(palette)来使绘制位图时颜色正常是多余且错误的行为,而且会造成使用调色板的对象在绘制的时候出现颜色混乱。正确的方法是set_color_depth(24)(这句添加在设置显示模式之前) ;+ load_bitmap(path,NULL);的组合。
二、另一个方面---在8位色深时---由于这个模式下,显示位图或者其他任何需要绘制的对象必须要有调色板,因此必须有一个统一的调色板--位图制作的时候使用的是它,设计程序的时候使用的也是它。显然,这个时候会非常麻烦。所以我还是采用24+NULL的方式来显示我需要的东西。当我在程序中正确的设置之后,显示便没有问题了。
但是在datafile中添加新的24位位图时,还是会出现颜色不对的问题,就象24位位图被显示在了256色的模式下,大部分颜色都丢失了。这个问题需要牵扯到美工..所以暂时先放在这里...

4、set_palette((RGB*)(datafile[THE_PALETTE].dat));
重点是(RGB*)的强制转换,set_palette()接受一个PALETTE类型参数,但是datafile[THE_PALETTE].dat是一个void*类型,那么需要强制转换,(PALETTE)是不被VS接受的,因为PALETTE实际上只是RGB[256]的别名,因此在转换的时候,应该直接使用最初的定义,RGB数组,也就是void*转RGB*。原例没有这样的转换,应该是在VS2005环境下特有的毛病,毕竟4.2.2是上个月才出来的。

5、char *listbox_getter(int index, int *list_size)
它在   { d_list_proc,       160, 150,  160,   44,   0,  0,    0,      0,       0,   0,    (void *)listbox_getter, sel,  NULL  },
中被调用,作为d_list_proc的回调函数,实现的是当发生d_list_proc事件时,储存已经被选择了的Item->name,方便btnInfo使用。

6、Menu对象。
就是个Menu对象,可以察看帮助文件,对于它的应用绝不仅限于这个例子,它可以做出右键菜单,但它并不在我急须掌握的知识之内。等回头有空闲时间了再来对付它。

7、Dialog对象
它并不是IDE中的TDialog对象,也许将Dialog翻译成“会话过程”或“对话过程”更能够反映出它的本质,它相当于“事件列表”或“消息队列”。然后使用do_dialog(the_dialog, -1);来轮循这个列表(或队列)。这很了不起~这样的仿消息机制在DOS下建立GUI时将带来相当大的方便!
        实现感知能力的思想是“热区”(hot area)。我知道你在想什么:)--你肯定在想"重叠",但实际上并不是那样。
        首先在显示方面,对象(热区)是绘制上去的,因此在Dialog数组靠后位置的对象将显示在上面,就象Zorder从0开始排列那样。但是激活的对象将完全显示-完全显示并不代表全部热区都生效。
        其次靠后的对象的热区有优先响应权,也就是说,你必须将鼠标移动到某个对象没有被覆盖的区域才可以触发它--如果它被位置靠后的元素完全覆盖了,那你只有通过热键来激活它--如果你设置了热键:)。所以同一个点只有最后形成的热区才响应,这点很重要。

8、d_*_proc
int d_clear_proc(int msg, DIALOG *d, int c);
清屏,当为会话的第1个对象时有效
int d_box_proc(int msg, DIALOG *d, int c);
画个矩形框
int d_shadow_box_proc(int msg, DIALOG *d, int c);
画个带阴影的矩形框
int d_bitmap_proc(int msg, DIALOG *d, int c);
在屏幕上绘制dp所指向的位图.
int d_text_proc(int msg, DIALOG *d, int c);
int d_ctext_proc(int msg, DIALOG *d, int c);
int d_rtext_proc(int msg, DIALOG *d, int c);
在屏幕上输出文本.dp指向需要显示的字符串。d_ctext_proc()居中,d_rtext_proc()居右,'&'之后的字符被转义为带下划线的热键, 输入"&&"显示"&",dp2指向自定义字体。
int d_button_proc(int msg, DIALOG *d, int c);
int d_check_proc(int msg, DIALOG *d, int c);
int d_radio_proc(int msg, DIALOG *d, int c);
int d_icon_proc(int msg, DIALOG *d, int c);
int d_keyboard_proc(int msg, DIALOG *d, int c);
int d_edit_proc(int msg, DIALOG *d, int c);
int d_list_proc(int msg, DIALOG *d, int c);
int d_text_list_proc(int msg, DIALOG *d, int c);
int d_textbox_proc(int msg, DIALOG *d, int c);
int d_slider_proc(int msg, DIALOG *d, int c);
int d_menu_proc(int msg, DIALOG *d, int c);
int d_yield_proc(int msg, DIALOG *d, int c);
我会回来再次编辑这些东西的..经过1个下午的探路,我发现通过这个例子来研究操纵消息还为时过早:(


9、/* These three functions demonstrate how to query dialog elements. */
/* 这3个函数展示了如何轮循对话框元素(它们并不是去轮循,而是他们实现了轮
/* 循时应该干的事情,说白了也是回调函数) */
要理解这段话需要注意很多地方:
1、这些回调函数最终都将将返回同一个值D_O_K,这个值的意思就是这个对象啥玩意都不做,具体的返回值在下面:
   D_O_K          - 标准返回值
   D_CLOSE        - 通知对话管理程序关闭对话
   D_REDRAW       - 通知对话管理程序重画整个对话
   D_WANTFOCUS    - 该对象请求输入焦点
   D_USED_CHAR    - 如果MSG_CHAR 和 MSG_XCHAR 输入了字符则返回该值
2、调用这些函数的4个会话过程my_button_proc,实际上具有与d_button_proc一样的行为。
   int ret = d_button_proc(msg, d, c); // 诀窍就在这里。
3、my_button_proc有个标志量D_EXIT,这个标志量指示当它被执行之后,将关闭整个会话响应,也就是返回D_CLOSE;

然后再来看my_button_proc究竟如何决定返回值:
   if (ret == D_CLOSE && d->dp3)
      return ((int (*)(void))d->dp3)();
   return ret;
ret == D_CLOSE 这里表示,如果我们不加干涉的话,d_button_proc的正常值应该是D_CLOSE,
就是上面第3点的情况,返回值为D_CLOSE。

那么再来看 d->pd3 这里表示执行dp3所指的回调函数。所有与此有关的回调函数只有2个返回值:
D_O_K   0  info123,这3个函数的返回值
D_CLOSE 非0
但是我们干涉它了!dp3回调函数返回的值才是最终的返回值,因此ret == D_CLOSE对于这3个调用来说,恒为0;
所以看起来这个my_button_proc就是d_button_proc,没什么区别。
但是它提供了一套思路,可以通过构造Dialog结构,来使my_*_proc成为不同的对象,采用不同的对象处理方式,这里实际上想做的是"模拟继承":表示你需要用什么,就可以保留什么。

10、这个例子并没有展示如何建立自己的do_dialog,或类似switch(msg){case:break;}结构。

我尝试过多种修改方法..只是让我更加的糊涂而已..因此要做的事情就是:继续前进~! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值