爱技术

 找回密码
 注册会员

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 5219|回复: 12
收起左侧

【专题文章】手机中的窗体

[复制链接]
发表于 2005-8-10 00:00:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册会员 微信登录

x
手机中的窗体

(我的例子中的函数都是以6688V55的地址为准,其他机型请大家参照查找响应函数,函数肯能有所差别)

一、浅谈手机中的窗体机制
在西门子的手机中使用了消息驱动的窗体机制,非常类似于windows中的机制。因为我对其运行机制并不是完全了解,所以在这里只说一下我的了解。
在西门子的手机中一个窗体的基本元素有标题,图标,滚动条,菜单项(菜单项图标,类似于List的Image),软键(按钮?)这些元素在具体的窗体中并不是全部出现的。我的理解是有一个基本的窗体,而其他的各种窗体只不过是这个窗体的实例化时的结果。而窗体的行为也类似于用windows的WindowsProc函数,响应具体的事件(类似的也有一个消息驱动的机制,很抱歉,我不能全部了解),比如大家经常看到这样的形式:
mov     [-r0], r9
mov     [-r0], r8
mov     r9, r13
mov     r8, r12
extp    r15, #1
mov     r12, [r14+4]
cmp     r12, #88h ; '?
jmpr    cc_Z, loc_D52318
cmp     r12, #90h ; '?
jmpr    cc_Z, loc_D52318
cmp     r12, #0F8h ; '?
jmpr    cc_Z, loc_D522F0
cmp     r12, #0F9h ; '?
jmpr    cc_Z, loc_D5230A
jmpr    cc_UC, loc_D52348

其实就是一个窗口函数的形式,而大家一般修改的按键响应我想只是OnKeyDown一样的函数。但是具体的消息定义我也不是很清楚。因为如此,我只总结一下我明白的东西,就当作是抛砖引玉,希望可以对大家有用!

二、一个基本的窗体
先说一个比较复杂的窗体,就是有标题,图标,滚动条,菜单的那种窗体,其实很多简单的窗体只是它的一个特列而已!主要是通过他来介绍一下常用的数据结构,为后面的理解作好准备。它涉及的主要函数有:

//创建窗体(需要注意的是int是16位整型,而所有指针都是32位的),需要注意的其他机型的
//函数可能和这个有所不同,但一般都有这两个结构参数。
int CreateMenu(int bBorder, int * ,int, wndFrame*, wndClass*, int*, int*, int*, int*)
//设置菜单项的信息,类似于windows的List控件的列表项自绘制函数,
//支持一个ImageList,而nImage则是序号,从0开始
int OnDrawMenuItem(int *, int *, int nImage)
//取得选中的菜单项的序号
int GetSelectMenuItem(struct MenuItem *)
//更新菜单项,这个函数会导致OnDrawMenuItem被调用,来更新菜单信息。
int UpdateMenuItem(struct MenuItem *)

//窗体的框架信息
struct wndFrame{
int unKnown_1;
int unKnown_2;
int ViewWidth;  //窗体的视图区域宽度,比如菜单中可能只有中间一条是,类似于ClientRect
int ViewHeight; //窗体的视图区域高度
int *pImageID;  //指向窗体图标序号的地址
int nTitleID;   //菜单标题的字串ID
int EndMask;    //通常7FFFh
}

typedef int (*MessgeFunction)(int *, int *); //回调函数指针

//窗口类信息
struct wndClass{
int * pUnknown_1;
MessgeFunction pOnkeyDown;                //按键响应函数
int * pUnknown_2;
int * pUnknown_3;
KeyCodeInfo * pKeyCodeInfo;                //窗体的软键信息       
KeyDefOrder * pKeyDefOrder;                //软键配置信息组
int nWndType;                                //窗体的类型信息
int nUnknown_4;
MessgeFunction OnMenuItemInit;         //菜单项初始化函数,注意是函数指针,请参考C语言相关内容。
MenuItem * pMenuItemList;                //菜单项结构列表       
MessgeFunction *pItemSelectFunList;         //菜单项被选中的函数
int nItemCount;                                //菜单项数量
}

//软键的虚键值信息
struct KeyCodeInfo{
KeyCodeDef * pKeyCodeDef;        //软键定义列表       
int nDefCount;                        //软键配置信息组的数量(有待商榷)
}

//软键的虚键值定义
struct KeyCodeDef
{
int nShortPressCode;                //短按软键的键值
int nLongPressCode;                //长按软键的键值
int nStringID;                        //软键显示的字串ID
}

//软键配置信息组
struct KeyDefOrder{
int nLeftKeyDefOrder;                //左软键的配置信息,是在软键定义列表中的序号
int nRightKeyDefOrder;                //右软键的配置信息,是在软键定义列表中的序号
}

//菜单项信息
struct MenuItem{       
int * nImageList;                //菜单的Image列表,以0结束       
int nNormalStringID;                //通常模式下的菜单字串ID
int nBigFontStrID;                //大字符模式下的菜单字串ID
int nUnkown_1                       
int * KeyDefOrder;                //菜单项被选择时软键的信息,比如选择框和帮助信息会在软键上有不同显示和虚键值。
int nType;                        //类型信息,细节未知
int nFlag;                        //标志,比如隐藏菜单就通过这个标志,系统由一个函数,用这个值作为参数来返回TRUE和FALSE信息。
}

具体的信息可以看Patch实例,用户配置菜单。因为程序过长,就不列出,有兴趣的可以看以前的帖子。
在那个程序中,主要实现的是函数有OnMenuItemInit,如下:

//菜单项初始化函数,R14是菜单项序号,开始于0
OnMenuItemInit proc far  
        mov     r2, #0         
        cmp     r14, #0
        jmpr    cc_Z, loc_EE       
        mov     r2, r14
        callr   IsFlagTrue        ;判断对应的标志位(一个Bit)是否为1
        and     r2, r1
        jmpr    cc_Z, loc_EC
        mov     r2, #1               
        jmpr    cc_UC, loc_EE

loc_EC:                       
        mov     r2, #2

loc_EE:                       
                              
        mov     [-r0], r2        ;设置ImageOrder
        calls   seg(SetMenu),sof(SetMenu) ;设置MenuItem
        add     r0, #2
        rets
OnMenuItemInit endp

//标志判断函数
IsFlagTrue proc near                       
                              
        mov     r1, #1
        sub     r2, #1
        shl     r1, r2
        extp    #42h, #1
        mov     r2, 3EFCh
        ret
IsFlagTrue   endp

//菜单响应函数
OnSelect proc far  ; start main of patch
        mov     [-r0], r12     
        mov     [-r0], r13
        calls   seg(GetSelectMenu),sof(GetSelectMenu)   //判断被选中的菜单项Order
        mov     r2, r4
        callr   loc_F8
        xor     r2, r1
        extp    #0Eh, #1               
        mov     3A42h, r2                                 //更新数据,有意义的Action       
        mov     r13, [r0+]
        mov     r12, [r0+]
        jmps    seg(UpdateMenu),sof(UpdateMenu)         //更新菜单项信息,这里主要是图片
OnSelect endp

三、其他的窗体函数
前面我做过猜测,就是所有的窗体都是一个基本的函数创建出来,在我在解读FireWare的过程中,发现这样的函数是确实存在的,我就以6688为例说一下这些函数的关系。
A、)
以下的窗体虽然各有不同,但是他们都是由一个函数0xF3:E9FA  CreateWnd(struct WndStruct*)创造的,再细分一下,又分成两类,有边框(一个矩形的框,如选项对话框等)和无边框的,分别由如下函数创建。
CreateWnd_FullScreen(struct WndStruct*) 0xF3:EA82  
CreateWnd_Pop(struct WndStruct*) 0xF3:EA8A      
这两个函数都是调用CreateWnd的。而在第二节中说到的CreateMenu最终也是要调用CreateWnd_FullScreen的。
下面我们看一下6688中存在的窗体类型。

1、基本的菜单式窗体。就是第一节中所说所说的类型,他拥有几乎所有的界面元素。代表:基本的菜单大都是这一类。通过第一个参数bBorder可以决定最后调用CreateWnd_FullScreen还是CreateWnd_Pop,如果bBorder是1,那么则创建一个有边框的弹出式窗体。

2、无标题和图标的窗体。这类窗体没有标题和图标,没有菜单,一般是一张图片。代表:游戏的开始画面,6688和x618的图形菜单也是基于这类窗体。如下是猜数字的主函数:
0xD1:AD08 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0xD1:AD08 loc_D1AD08:                           ; CODE XREF: 0xD1:AD76J
0xD1:AD08                 mov     [-r0], r9
0xD1:AD0A                 mov     [-r0], r8
0xD1:AD0C                 mov     r12, #898Ch   0xD3898C MMIMalloc
0xD1:AD10                 mov     r13, #0D3h ;
0xD1:AD14                 mov     r14, #89C8h   0xD389C8 MMIFree
0xD1:AD18                 mov     r15, #0D3h ;
0xD1:AD1C                 calls   0E2h, InitScreen
0xD1:AD20                 mov     r8, r4
0xD1:AD22                 mov     r9, r5
0xD1:AD24                 mov     r12, r8
0xD1:AD26                 mov     r13, r9
0xD1:AD28                 mov     r14, #2CB6h   ; 0xD1:ACB6 窗口的相关结构
0xD1:AD2C                 mov     r15, #346h
0xD1:AD30                 calls   0E2h, sub_E2367F   //填充窗口结构
......
//略去和创建窗口无关的部分
......
0xD1:AD68                 mov     r12, r8
0xD1:AD6A                 mov     r13, r9
0xD1:AD6C                 calls   0F3h, CreateWnd_FullScreen //在这里直接调用的创建noBorder的窗口函数
0xD1:AD70                 mov     r8, [r0+]
0xD1:AD72                 mov     r9, [r0+]
0xD1:AD74                 rets
0xD1:AD76 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//窗口结构的相关信息
0xD1:AC9E                 dw 2Fh                //软键定义Order_0,键码为2F
0xD1:ACA0                 dw 2Fh
0xD1:ACA2                 dw 38Ch               //文字为"Options"
0xD1:ACA4                 dw 5                  //软键定义Order_1,键码为5
0xD1:ACA6                 dw 5
0xD1:ACA8                 dw 303h               //文字为"Start"
0xD1:ACAA                 dw 2C9Eh              //KeyCodeInfo, 有1套配置
0xD1:ACAC                 dw 346h
0xD1:ACAE                 dw 1
0xD1:ACB0                 dw 0                  //配置信息,左软键用Order为0的配置
0xD1:ACB2                 dw 1                  //右软键用Order为1的配置
0xD1:ACB4                 dw 107h               //图标ID
0xD1:ACB6                 dw 0                  ; field_0
0xD1:ACB6                 dw 0                  ; field_2
0xD1:ACB6                 dw 0ACDCh             ; OnCommandOff
0xD1:ACB6                 dw 0D1h               ; OnCommandPage
0xD1:ACB6                 dw 0                  ; field_8
0xD1:ACB6                 dw 0                  ; field_A
0xD1:ACB6                 dw 0E636h             ; field_C
0xD1:ACB6                 dw 0F3h               ; field_E
0xD1:ACB6                 dw 2CB0h              ; SKeyItem_Offset
0xD1:ACB6                 dw 346h               ; SKeyItem_Page
0xD1:ACB6                 dw 2CAAh              ; SKeyListOffset
0xD1:ACB6                 dw 346h               ; SKeyList_Page
0xD1:ACB6                 dw 0                  ; field_18
0xD1:ACB6                 dw 0                  ; field_1A
0xD1:ACB6                 dw 65h                ; Weigth
0xD1:ACB6                 dw 41h                ; Heigth
0xD1:ACB6                 dw 2CB4h              ; IconOffset
0xD1:ACB6                 dw 346h               ; IconPage
0xD1:ACB6                 dw 0                  ; field_24

这里面的主要结构如下
struct wndClass_2{
int * pUnknown_1;
MessgeFunction pOnkeyDown;        //按键响应函数
int * pUnknown_2;
MessgeFunction pUnknown_3;  //未知的函数,一般是直接返回,即ret;
KeyCodeInfo * pKeyCodeInfo;        //窗体的软键信息       
KeyDefOrder * pKeyDefOrder;        //软键配置信息组
int unKnown_4;
int unKnown_5;
int ViewWidth;              //窗体的视图区域宽度
int ViewHeight;             //窗体的视图区域高度
int *pImageID;              //指向窗体图标序号的地址
int unKnown_6;               //菜单标题的字串ID
}

此外,说一下这里面的按键响应函数
0xD1:ACDC ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0xD1:ACDC                 mov     [-r0], r8
0xD1:ACDE                 mov     r8, #0FFFFh       //按键响应函数的返回值,意义下面解释
0xD1:ACE2                 extp    r15, #1
0xD1:ACE4                 mov     r12, [r14+2]
0xD1:ACE8                 cmp     r12, #2Fh ; '/'   //左软键
0xD1:ACEC                 jmpr    cc_Z, loc_D1ACF4
0xD1:ACEE                 cmp     r12, #5           //右软键
0xD1:ACF0                 jmpr    cc_Z, loc_D1ACFA
0xD1:ACF2                 jmpr    cc_UC, loc_D1AD00
0xD1:ACF4 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0xD1:ACF4 loc_D1ACF4:                           ; CODE XREF: 0xD1:ACECj
0xD1:ACF4                 calls   0D1h, sub_D18BAA
0xD1:ACF8                 jmpr    cc_UC, loc_D1AD02
0xD1:ACFA ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0xD1:ACFA loc_D1ACFA:                           ; CODE XREF: 0xD1:ACF0j
0xD1:ACFA                 calls   0D1h, sub_D1AC32
0xD1:ACFE                 jmpr    cc_UC, loc_D1AD02
0xD1:AD00 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0xD1:AD00 loc_D1AD00:                           ; CODE XREF: 0xD1:ACF2j
0xD1:AD00                 mov     r8, #0
0xD1:AD02 loc_D1AD02:                           ; CODE XREF: 0xD1:ACF8j
0xD1:AD02                                       ; 0xD1:ACFEj
0xD1:AD02                 mov     r4, r8
0xD1:AD04                 mov     r8, [r0+]
0xD1:AD06                 rets
0xD1:AD08 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

这里面需要注意是按键响应函数的返回值,如果按键已经被处理,那么需要返回-1(0FFFFh),则消息系统会认为你已经处理,否则会转到系统的默认窗口函数去处理。

3、消息框的窗体,类似于windows的MessageBox,可以显示文本信息,并制定图标,和键盘控制,如一般的确认对话框。如下是写短消息时选项中按清除文本后的处理:
//次函数最终根据bBorder调用CreateWnd_FullScreen还是CreateWnd_Pop。
0xE6:017E MessageBox(int bBorder, int * Prama, int , struct wndClass_3 * pwndClass)

0xD5:63AE ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0xD5:63AE DeleteText:                           ; CODE XREF: 0xD5:62B6j
0xD5:63AE                 mov     r12, r8
0xD5:63B0                 mov     r13, r9
0xD5:63B2                 calls   0E5h, sub_E5F0FC
0xD5:63B6                 mov     r8, r4
0xD5:63B8                 mov     r9, r5
0xD5:63BA                 mov     r6, #3A04h    ; 0xD4:FA04
0xD5:63BE                 mov     r7, #353h
0xD5:63C2                 mov     [-r0], r7
0xD5:63C4                 mov     [-r0], r6
0xD5:63C6                 mov     r12, #1
0xD5:63C8                 mov     r13, r8
0xD5:63CA                 mov     r14, r9
0xD5:63CC                 calls   0E6h, MessageBox
0xD5:63D0                 add     r0, #4
0xD5:63D2                 jmpa    cc_UC, loc_D5646E
0xD5:63D6 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

0xD4:FA04                 dw 0
0xD4:FA06                 dw 0
0xD4:FA08                 dw 6152h
0xD4:FA0A                 dw 0D5h
0xD4:FA0C                 dw 0
0xD4:FA0E                 dw 0
0xD4:FA10                 dw 0E636h
0xD4:FA12                 dw 0F3h
0xD4:FA14                 dw 39B6h
0xD4:FA16                 dw 399h
0xD4:FA18                 dw 399Ch
0xD4:FA1A                 dw 399h
0xD4:FA1C                 dw 1
0xD4:FA1E                 dw 0
0xD4:FA20                 dw 4E6h               ; 删除文本?Delete Text?
0xD4:FA22                 dw 39F2h
0xD4:FA24                 dw 399h
0xD4:FA26                 dw 0
0xD4:FA28                 dw 3
0xD4:FA2A                 dw 2
0xD4:FA2C                 dw 0
0xD4:FA2E                 dw 0
0xD4:FA30                 dw 0
0xD4:FA30 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

这里面的主要结构如下
struct wndClass_2{
int * pUnknown_1;
MessgeFunction pOnkeyDown;        //按键响应函数
int * pUnknown_2;
MessgeFunction pUnknown_3;  //未知的函数,一般是直接返回,即ret;
KeyCodeInfo * pKeyCodeInfo;        //窗体的软键信息       
KeyDefOrder * pKeyDefOrder;        //软键配置信息组
int unKnown_4;
int unKnown_5;
int nStringID               //显示的消息的StringID
int *pImageID;              //指向窗体图标序号的地址
int unKnown_6;
int unKnown_7;
int unKnown_8;
int unKnown_9;
int unKnown_A;
int unKnown_B;
}


4、简单消息框的窗体。只是简单的显示一条消息,有三类(i,v,无图标)。其中参数r12来决定由没有边框。本质上,以上的几个函数都是下面复杂窗体的一个特例,为了使用方便,特独立列出!主要有以下三个函数:
0xE6:04A8 MessageBox_v(int bBorder, int nStringID)//消息框图标为i
0xE6:0508 MessageBox_i(int bBorder, int nStringID)//消息框图标为v
0xE6:0538 MessageBox_NoIcon(int bBorder, int nStringID) //无图标
这三个函数比较简单,主要是根据bBorder来决定两个不同的结构,然后调用CreateWnd_FullScreen或CreateWnd_Pop。


               
B、)

                                                       待续。。。。。。。。。。。
[此贴子已经被作者于2004-3-28 21:03:29编辑过]

 楼主| 发表于 2005-8-10 00:01:00 | 显示全部楼层
待续。。。。
最近一直很忙,每天只是匆忙来看一下,很是过意不去。
这个关于窗体的,一直想写了(好像是在进阶的计划里面的),赶在这个周末,把它写完!
大家如果有兴趣和问题,不妨一起讨论,把Unknown变成specific!
发表于 2005-8-10 00:02:00 | 显示全部楼层
必然签到 :)     窗体一直只有个模糊的理解,这样能比较详细的了解一下了。
发表于 2005-8-10 00:03:00 | 显示全部楼层
我也来签到!回去慢慢学习。
发表于 2005-8-10 00:04:00 | 显示全部楼层
怎能不支持呢?
宝贵的经验可以造福不少SPGCer啊!
发表于 2005-8-10 00:05:00 | 显示全部楼层
支持呀!
发表于 2005-8-10 00:06:00 | 显示全部楼层
终于出来了,太好了。
支持!感谢!
发表于 2005-8-10 00:07:00 | 显示全部楼层
签到!
发表于 2005-8-10 00:08:00 | 显示全部楼层
学习中……
发表于 2005-8-10 00:09:00 | 显示全部楼层
报道~~
发表于 2005-8-10 00:10:00 | 显示全部楼层
收之.                                       
发表于 2005-8-10 00:11:00 | 显示全部楼层
能不能以6688应用程序为例子//标志判断函数
IsFlagTrue proc near                       
                              
        mov     r1, #1
        sub     r2, #1
        shl     r1, r2
        extp    #42h, #1
        mov     r2, 3EFCh ------------------------#42:3FFC   怎么找到一个地址使用呢,与别的菜单能不能使用相同的地址
        ret
IsFlagTrue   endp
头像被屏蔽
发表于 2007-4-2 09:20:52 | 显示全部楼层
虽然不懂,开始狼大的帖子,怎么能不顶呢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员 微信登录

本版积分规则

小黑屋|Archiver|手机版|爱技术 ( 沪ICP备08115260号-3 )

GMT+8, 2024-5-20 20:20

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

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