【专题文章】手机中的窗体
手机中的窗体(我的例子中的函数都是以6688V55的地址为准,其他机型请大家参照查找响应函数,函数肯能有所差别)
一、浅谈手机中的窗体机制
在西门子的手机中使用了消息驱动的窗体机制,非常类似于windows中的机制。因为我对其运行机制并不是完全了解,所以在这里只说一下我的了解。
在西门子的手机中一个窗体的基本元素有标题,图标,滚动条,菜单项(菜单项图标,类似于List的Image),软键(按钮?)这些元素在具体的窗体中并不是全部出现的。我的理解是有一个基本的窗体,而其他的各种窗体只不过是这个窗体的实例化时的结果。而窗体的行为也类似于用windows的WindowsProc函数,响应具体的事件(类似的也有一个消息驱动的机制,很抱歉,我不能全部了解),比如大家经常看到这样的形式:
mov [-r0], r9
mov [-r0], r8
mov r9, r13
mov r8, r12
extp r15, #1
mov r12,
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,
mov r12,
jmps seg(UpdateMenu),sof(UpdateMenu) //更新菜单项信息,这里主要是图片
OnSelect endp
三、其他的窗体函数
前面我做过猜测,就是所有的窗体都是一个基本的函数创建出来,在我在解读FireWare的过程中,发现这样的函数是确实存在的,我就以6688为例说一下这些函数的关系。
A、)
以下的窗体虽然各有不同,但是他们都是由一个函数0xF3:E9FACreateWnd(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,
0xD1:AD72 mov r9,
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,
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,
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编辑过]
待续。。。。
最近一直很忙,每天只是匆忙来看一下,很是过意不去。
这个关于窗体的,一直想写了(好像是在进阶的计划里面的),赶在这个周末,把它写完!
大家如果有兴趣和问题,不妨一起讨论,把Unknown变成specific! 必然签到 :) 窗体一直只有个模糊的理解,这样能比较详细的了解一下了。 我也来签到!回去慢慢学习。 怎能不支持呢?
宝贵的经验可以造福不少SPGCer啊! 支持呀!
终于出来了,太好了。
支持!感谢! 签到! 学习中…… 报道~~ 收之. 能不能以6688应用程序为例子//标志判断函数
IsFlagTrue proc near
mov r1, #1
sub r2, #1
shl r1, r2
extp #42h, #1
mov r2, 3EFCh ------------------------#42:3FFC 怎么找到一个地址使用呢,与别的菜单能不能使用相同的地址
ret
IsFlagTrue endp
虽然不懂,开始狼大的帖子,怎么能不顶呢
页:
[1]