`
javababy1
  • 浏览: 1173893 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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;}结构。

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics