这是开这个博客的第一篇文章, 在这里开博客主要是为了写一下以前主要是以后做过的东西,记录一下自己的技术,以便自己以后查找或和朋友们一起探讨. 很遗憾的是这篇文章讲的跟自己的工作用的技术不一样, 工作主要是做Linux下边的驱动或应用程序的开发, 很少做过Windows下边的东西.第一次写技术方面的东西,也不知道该怎么开始,怎么结婚,怎么组织,怎么表述. 不过就按自己心中的想法,尽量把有用的能和大家一起探讨的东西写出来. 也有些未处理或处理效果不太好的东西, 希望大家也能给提示一下. 先在这儿多谢了!~~
这几天帮朋友做了一个Windows Mobile手机的GPS定位信息短信的收取处理"程序"(DLL). 一开始根本没有玩过Windows Mobile这套系统的开发. 主要是为了学习一下Windows Mobile操作系统的软件开发.
项目需求:
1. 能够遍历接收到的短信,挑出有定位信息格式的闰转换成GPS导航软件需要的格式.
2. 具有单次定位的功能
单次定位就是把打开的当前短信进行读并转换成相应的GPS导航软件需要的格式发给导航软件.
3. 具有连续定位的功能
连续定位就是把当前打开的短信以后收到的所有短信都读取并转换成相应导航软件的格式发送给导航软件.
4. 能够结束定位.
5. 当开始单次或多次定位时,能自动打开GPS导航软件.
6. 能够配置GPS导航软件所在的位置.
7. 能够配置需要本软件发送的串口.
项目开发结果
其中: 图 1显示了短信列表的GPS定位菜单的形式, 图 2显示了在打开发短信里菜单的情况. 本来以为这两个菜单函数应该一样, 可后来发现, 还是有一些差别的, 就是Windows Mobile系统在不同的地方传递不同的当前文件信息. 也描述不清楚了,呵呵,就是Windows Mobile在菜单调用时会根据不同的地方(在短信列表或打开的短信里)会传递不同的参数. 找这到参数格式和信息让我头疼了一天.
图 1 图 2 图 3
数据流程:
项目开发遇到的问题.
1. 串口问题
a) 还是首次在应用程序下对串口读写呢,以后只是用过串口调试工具. 所以不免有些担心. 谁知道串口到是没有给我找什么麻烦. 就是在Open的时候,一定要在最后边加上一个”:”分号
b) 例: “COM5:”
c) 代码:
i. 代码主要是三个函数, 我本来写把这些东西组织成一个类, 结果由于时间人仓促,第一次做Windows Mobile, 急急忙忙, 本着能解决问题就行的想法写完了, 等以后有时间整理出来再说吧, 今天先把未整理的贴出来. 也希望能给朋友们一些帮助;
ii. OpenCOMM()
|
iii. CloseCOMM()
|
iv. WriteCOMM()
|
v. ReadCOMM()因为没有涉及到要去读串口,所以这个函数没有实现, 其实如果朋友需要的话可以参考WriteCOMM()或直接MSDN
2. 菜单问题
a) 怎么在短信菜单上加一项菜单
i. Windows 扩展菜单的时候是一个很不错的方式(虽然刚开始的时候我叫它为”变态”). 不过我现在还没有弄通整菜单实现的方式, 不过就我查过的MSDN来说,它可以对短信, 图片, 文件夹等一些功能添加扩展菜单. 包括普通的菜单和上下文菜单(也叫右键菜单 context-menu) . 在本项目里我只实现了普通的菜单, 利用的是Windows Mobile的SDK的 IndoxMenuExtensibility 例子. 上边有扩展普通菜单和添加上下文菜单(Context Menu)的功能. 在本例子中添加一个菜单的流程为:
1. 在InboxMenuExt.cpp文件的最开始的地方定义一个菜单的TEXT文本的变量. 如
const TCHAR cszDeleteAll[] = TEXT("Delete All");
2. 在MenuExtension::GetCommandStringHelper()函数里添加一个if语句, 根据上边例子就可以了,其中: Context表示是一个上下文菜单, softkey表示一个普通的按键菜单.
3. 在MenuExtension::QueryContextMenu()函数里添加两个语句, 给刚定义的菜单申明一个变量(在InboxMenuExt.h的MenuExtension类里: UINT m_idc2; 然后加两个语句:
a) GetCommandStringHelper(m_idc1, szItemName, ARRAYSIZE(szItemName)); 其实就是把刚才的定义的菜单显示的文字Copy到szItemName变量里,然后再生成一个菜单并插入到系统的菜单里.
b) InsertMenuItem(hmenu, indexMenu, m_idc1, szItemName);在hmenu菜单里插入一个m_idc1标识的菜单名为szItemName的菜单. 当时看到这个就郁闷了, 为什么没有给它一个回调函数来处理这个菜单被点击的事件呢. 其实这个函数只负责菜单的显示, 并不处理click处理. 处理函数会通过调用另外一个函数进行的.如下边讲.
4. MenuExtension::InvokeCommand()添加一个菜单被点击时调用哪个函数来处理这个菜单.
a) Context表示上下文菜单(右键菜单)
b) Softkey表示普通的按键菜单
c) if (!_tcscmp(cszMarkAll, (LPCTSTR)lpici->lpVerb)) 就是比较被点击的菜单是否和我们刚刚添加的菜单匹配,如果匹配则调用本菜单的处理函数…汗…晕…NND, 比较一下就O了. 一下子感觉很高深的东西变成了一if的比较语句. 当时直骂Windows变态. 可结果我却发现这种方式非常的方便,如果我再改这个菜单的处理函数, 我只需要在这儿改动一下就行了,无需要关系其它的. ..方便,,呵呵
if (!_tcscmp(cszMarkAll, (LPCTSTR)lpici->lpVerb))
{
hr = MarkAllInFolderAsRead();
CHR(hr);
}
5. 它怎么知道什么时候调用Context和Softkey呢? 其实本程序实现上就是一个 COM组件(其实我不懂COM是一个什么东西), 而Context和softkey是这个组件的两个不同的实例而已. Windows Mobile每当打开一个菜单时,会根据本菜单所在的注册表扩展菜单的地方找出注册的扩展菜单, 然后调用扩展菜单的COM入口函数初始化菜单.生成一个MenuExtsion实例. 所以, 你把本程序的.dll注册到什么地方, 什么地方就有本菜单的菜单项..而每个地方都会有两种形式的菜单: 上下文菜单和普通的按键菜单. 而本程序把.dll文件注册到了: " "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Shell\\Extensions\\ContextMenus\\Inbox\\" Inbox表示短信, 所以我们添加的菜单就自动添加到短信菜单了.
6. 当然了,怎么区分上下文菜单和普通菜单呢? 所以在 HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Shell\\Extensions\\ContextMenus\\Inbox\\" 下边有两个子目录:
a) List_View_Context 表示一个Context 菜单(上下文菜单)
b) List_View 表示一个普通的菜单(普通菜单)
b) 怎么加一个菜单,它有N个子菜单
i. 不说了,直接源码吧,比说什么都好:
|
c) 怎么在打开的短信里加一项菜单
i. List_View_Context 表示一个Context 菜单(上下文菜单)
ii. List_View 表示一个普通的菜单(普通菜单)
iii. Read_View 其实可以用 Read_xxx来, 没有研究透, 一试这个可以, 就懒得往研究了.
3. 线程问题
a) 怎么用线程去发送数据到串口
i. 还真没有在Windows下弄过线程呢, 不过也好整,创建一下就行了, 当然查资料的时候郁闷的地方就是, Wincows下的线程是”发射后不管”的方式, 创建后直接把得到的句给Close了, 但线程照样运行. 当时我那个汗啊…所以我对线程的回收直接是让线程退出方式,不想用了就给它的一个变量做一个FALSE退出了,省得再研究那麻烦的东西了.
ii. 下边是创建代码:
if ((hCommThread = CreateThread (NULL, 0, SendGPSInfoToCommThread, (LPVOID)this, 0,&dwThreadID)) == NULL). 其实this是我自己参数,朋友们可以换成自己的线程参数.
b) 和类的关系
i. 当时我自己实现一个串口类, 我就想把这个线程弄到这个串口类里去,让类管理这个线程,可后来就直接用了一个全局线程函数给解决了, 现在感觉自己弄的这个类还不男不女的, 都不好分层次了, 不过这个项目上就是”能用”就行, 我也不想再多研究了.
4. 弹出窗体问题
a) 实在对VC或VS没着啊, 就为了能打开一个弹出窗体, 死活我整了一天, 整整一天..郁闷的我急上火下的.
b) 在项目的resource