WinCE中如何调用控制面板程序
要是在Linux里,简单,直接system("/path/filename arg……")就好了,但请注意,这是在winCE中,就比较郁了。
首先要找一个类似system这样的函数(winCE里不支持system()),找到了一个——
LPCWSTR lpszImageName ,
LPCWSTR lpszCmdLine ,
LPSECURITY_ATTRIBUTES lpsaProcess ,
LPSECURITY_ATTRIBUTES lpsaThread ,
BOOL fInheritHandles ,
DWORD fdwCreate ,
LPVOID lpvEnvironment ,
LPWSTR lpszCurDir ,
LPSTARTUPINFOW lpsiStartInfo ,
LPPROCESS_INFORMATION lppiProcInfo );
WinCE的控制面板没有URL,右键也不提供“属性”,这个系统又不是我做的,搜了一圈也没有,估计是被隐藏了,死活想不出查看路径的办法。只好上网搜一下,于是查找到以下有用信息:
WinCE系统中的控制面板和Windows系统中的控制面板原理是一样的,里面就是包含了一些应用程序。WinCE系统的控制面板由 Ctlpnl.exe,Control.exe和一些.cpl文件组成,其中Ctlpnl.exe和Control.exe用于控制控制面板的文件夹显示和架构,而.cpl文件和控制面板中的实际应用程序相对应。from http://ieoqmdce.blog.163.com/blog/static/389399542009913117425/
用脚本实现对WINCE控制面板功能的直接调用
控制面板其实也是个动态链接库,区别只在于后缀名为.cpl
如何调用.cpl
就像PC机中.dll文件不能直接运行,需要借助rundll32.exe来运行一样,WinCE下的.cpl也需要相应的程序来调用,这个程序就是:"ctlpnl.exe".
比如我们需要调用系统自带的cplmain.cpl的"电源管理",只要在开始菜单的运行中输入:"ctlpnl.exe /windows/cplmain.cpl,5".在路径后面紧跟的"5"只是因为"电源管理"在cplmain.cpl中输入第五个Applet而已.
在WINCE实际使用过程中可以使用脚本来做到一机多图中,如脚本RunWait("/Windows/ctlpnl.exe", "cplmain.cpl,6,1")就可直接调用控制面板并进入调整内存
RunWait("/Windows/ctlpnl.exe", "cplmain.cpl,9,1") /可以直接进入校准 (
RunWait("/Windows/ctlpnl.exe", "cplmain.cpl,10")进入调整音量 ";
以下所列就是不同数字对应的功能
0 CPL_Comm 连接属性
1 CPL_Dialing 拨号属性
2 CPL_Keyboard 键盘属性
3 CPL_Password 密码属性 /
4 CPL_Owner 所有者
5 CPL_Power 电源属性
6 CPL_System 系统属性
7 CPL_Screen 显示属性
8 CPL_Mouse 鼠标属性
9 CPL_Stylus 笔针属性 (这里可以校准)
10 CPL_Sounds 音量属性
11 CPL_SIP" 输入面板
12 CPL_Remove 删除程序
13 CPL_DateTime 日期时间
14 CPL_Certs 证书
from http://bbs.manbu.cc/viewthread.php?tid=27484
于是在“运行”里试了一下ctlpnl.exe /windows/cplmain.cpl,5,果然可以!那办法就有了,只要在程序中需要的地方加入:
PROCESS_INFORMATION pi = {0};
CreateProcess(_T("//Windows//ctlpnl.exe"), _T(" cplmain.cpl,9,2"), NULL, NULL, NULL,
0, NULL, NULL, NULL, &pi);
问题就解决了
1.系统启动过程中RTC初始化
在WINCE6.0中,我们知道是通过OALIoCtlHalInitRTC()函数来设置RTC的时间的,但是如何调用到这个函数的呢?
在SystemStartupFunc函数中,通过下面语句来创建一个内核线程RunApps:
hTh = CreateKernelThread (RunApps,0,THREAD_RT_PRIORITY_NORMAL,0);
接着就执行线程RunApps。在线程RunApps中,通过下面语句:
hFilesys = (HMODULE) NKLoadLibraryEx (L"filesys.dll", MAKELONG (LOAD_LIBRARY_IN_KERNEL, LLIB_NO_PAGING), NULL);
来加载filesys.dll,接着通过下面语句:
hTh = CreateKernelThread ((LPTHREAD_START_ROUTINE)pfnMain, hFilesys, THREAD_RT_PRIORITY_NORMAL, 0);
来创建filesys.dll的线程WinMain(),这个线程在/WINCE600/PRIVATE/TEST/BASEOS/FILESYS/GENFILE/genfile.cpp中定义,这样就接着执行这个线程。
Filesys.dll的主要工作是初始化文件系统、对象存储、注册表、CEDB数据库、设备通知以及其它一些工作:
⑴Filesys.dll检测是冷启动还是热启动
如果是冷启动,对象储存内存将被初始化并映射给Filesys.dll;对于热启动,不用初始化而直接映射给Filesys.dll。
⑵Filesys.dll从nandflash中加载OEM的certification DLL。
⑶如果必须他能够必须是冷启动,Filesys.dll调用OAL函数pNotifyForceCleanboot。
⑷对于冷启动,Filesys.dll调用OEMIoControl函数,I/O控制代码为IOCTL_HAL_INIT_RTC,也就是初始化RT。
Filesys.dll还有很多的动作,再这里就不介绍了,我们接下来看看OEMIoControl函数是如何一层层调用到OALIoCtlHalInitRTC的呢?接着往下看。
OEMIoControl():在/WINCE600/PLATFORM/COMMON/SRC/COMMON/IOCTL/ioctl.c下面定义
从上图可以知道OEMIoControl函数通过传递进来的code来和数组g_oalIoCtlTable中的code成员比较,找到吻合的code后便跳出这个for循环,然后往下执行。而数组g_oalIoCtlTable是在/Src/Oal/Oallib/ioctl.c下定义,如下图
接着看ioctl_tab.h的内容
到这里我们还是没有直观看到IOCTL_HAL_INIT_RTC,接着往下看oal_ioctl_tab.h的内容:
在上图的第31行可以看到IOCTL_HAL_INIT_RTC,那么对应于IOCTL_HAL_INIT_RTC的处理函数是如何得到执行的呢?上面提到,OEMIoControl函数通过传递进来的code找到数组g_oalIoCtlTable中吻合的code后,通过下面的处理
会记下i的值,也就是IOCTL_HAL_INIT_RTC所在数组g_oalIoCtlTable的索引值,接着看OEMIoControl函数下面的处理
这段代码就是根据上面确定的i的值,来执行对应的handler,在这里就是调用OALIoCtlHalInitRTC()函数
2.RTC初始化存在的问题
从上面可知,系统启动过程是通过调用函数OALIoCtlHalInitRTC()来初始化RTC的,这个函数体如下
从这个函数体可知是通过调用OEMSetRealTime()来设置RTC的,g_oalRtcResetTime的定义如下:
SYSTEMTIME g_oalRtcResetTime = {2010, 8, 5, 27, 12, 0, 0, 0};
因为我们的系统每次关机后重启都是冷启动,所以每次启动之后都会调用到OALIoCtlHalInitRTC函数,从而不管你之前设置的时间是多少,都会重新初始化为g_oalRtcResetTime中的时间。我把上图的第98行替换为下面的函数就可以解决了这个问题:
3.BOOL OEMSetRealTime(LPSYSTEMTIME pTime)
OEMGetRealTime()用来获得当前的时间。WinCE启动以后,默认情况下,WinCE会每隔一段时间调用OEMGetRealTime()函数来获得系统的时间,这种方式被称为hardware mode。WinCE还有另一种获得系统时间的方法,被称为software mode,就是通过调用GetTickCount()函数跟踪系统的timetick的变化来累加时间。如果要用software mode,那么需要在注册表中做如下的设置:
HKEY_LOCAL_MACHINE/Platform/"SoftRTC" = 1
我来谈谈我的看法,一般都要使用hardware mode,这样获得的系统时间比较准。software mode获得系统时间不会很准的。
4.BOOL OEMGetRealTime(SYSTEMTIME *pTime)
OEMGetRealTime()用来获得当前的时间。WinCE启动以后,默认情况下,WinCE会每隔一段时间调用OEMGetRealTime()函数来获得系统的时间,这种方式被称为hardware mode。WinCE还有另一种获得系统时间的方法,被称为software mode,就是通过调用GetTickCount()函数跟踪系统的timetick的变化来累加时间。如果要用software mode,那么需要在注册表中做如下的设置:
HKEY_LOCAL_MACHINE/Platform/"SoftRTC" = 1
我来谈谈我的看法,一般都要使用hardware mode,这样获得的系统时间比较准。software mode获得系统时间不会很准的。
5.BOOL OEMSetRealTime(LPSYSTEMTIME pTime)
OEMSetRealTime()用来设置当前的时间。当WinCE启动以后,我们会在界面的右下角看到时间显示,我们可以直接在WinCE的界面里面设置时间,这个时候,系统就会调用OEMSetRealTime()把你设置的时间写到RTC模块里面。
6.LPSYSTEMTIME
LPSYSTEMTIME实际上是一个指向SYSTEMTIME结构的指针,关于SYSTEMTIME,定义如下:
typedef struct _SYSTEMTIME
{
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;
RTC测试程序
注:延迟900ms左右,差不多1S显示一次当前时间
注:16进制标志10进制 表示的是0012年 05月 15日,12:00:00