EVC开发技巧
来源:互联网 发布:一个小游戏的java语言 编辑:程序博客网 时间:2024/05/14 10:12
//Hard Reset!
#include <winioctl.h>
#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern "C" __declspec(dllimport)void SetCleanRebootFlag(void);
extern "C" __declspec(dllimport) BOOL KernelIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned);
BOOL HardResetPocketPC()
{
SetCleanRebootFlag();
return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
}
////////////////////////////////////////////////////
//全屏
void FullScreen(HWND hDlg)
{
RECT rc;
GetWindowRect(hDlg, &rc);
SHFullScreen(hDlg, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON);
MoveWindow( hDlg, rc.left, rc.top, rc.right, rc.bottom, TRUE);
}
//类似参数要注意SHFS_HIDETASKBAR HIDE为隐藏、SHOW为显示
////////////////////////////////////////////////////
//WinSDK编程 显示隐藏光标
int nWaitCursorCount; //光标记数器
/******************************************************
*显示隐藏光标nCode=1为显示,-1为隐藏
*****************************************************/
void SHCursor(int nCode)
{
static HCURSOR cur;
static BOOL bo=true;
if (bo)
{
cur = ::LoadCursor(NULL, IDC_WAIT);
bo = false;
}
m_nWaitCursorCount += nCode;
if (m_nWaitCursorCount > 0)
{
HCURSOR hcurPrev = ::SetCursor(cur);
if (nCode > 0 && m_nWaitCursorCount == 1)
m_hcurWaitCursorRestore = hcurPrev;
}
else
{
// turn everything off
m_nWaitCursorCount = 0; // prevent underflow
::SetCursor(m_hcurWaitCursorRestore);
}
}
/******************************************************
*开始显示光标
*****************************************************/
void BeginCursor()
{
m_nWaitCursorCount = 0;
SHCursor(1);
}
/******************************************************
*结束显示光标
*****************************************************/
void EndCursor()
{
m_nWaitCursorCount = 0;
SHCursor(-1);
}
//////////////////////////////////////////////////////////
//调用其它程序
/******************************************************
*打开其它应用程序
*****************************************************/
void Shell(HWND hWnd,LPTSTR ProPath)
{
int ret;
LPTSTR exec = (LPTSTR)malloc(MAX_PATH);
SHELLEXECUTEINFO shi;
exec = ProPath;
shi.cbSize = sizeof(SHELLEXECUTEINFO);
shi.lpVerb = TEXT("open");
shi.lpFile = exec;
shi.nShow = SW_SHOWNORMAL;
ret = ShellExecuteEx(&shi);
}
////////////////////////////////////////////////////////
//WINSDK 弹出式菜单
/******************************************************
*弹出菜单
*****************************************************/
VOID APIENTRY PopupMenu ( HWND hWnd, POINT point, int IDM)
{
HMENU hMenu;
HMENU hMenuTrackPopup;
// 得到弹出菜单资源
hMenu = LoadMenu (ghInst, MAKEINTRESOURCE(IDM));
if (!hMenu)
return;
hMenuTrackPopup = GetSubMenu (hMenu, 0);
ClientToScreen (hWnd, (LPPOINT)&point);
TrackPopupMenu (hMenuTrackPopup, 0, point.x, point.y, 0, hWnd, NULL);
DestroyMenu (hMenu);
}
网络设置保存在注册表中,位置[HKEY_LOCAL_MACHINE\\Comm\\网卡名称\\Parms\\TcpIp],例如常见的CS8900网卡设置:
[HKEY_LOCAL_MACHINE\\Comm\\CS89001\\Parms\\TcpIp]
"EnableDHCP"=dword:0
"DefaultGateway"="192.168.0.1"
"DNS"="111.111.111.111"
"UseZeroBroadcast"=dword:0
"IpAddress"="192.168.0.2"
"Subnetmask"="255.255.255.0"
设 置之后要生效有两种办法:一种热启动,调用KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL),热启动时间很短暂;另外一种调用DevieceIoControl API,传递IOCTL= IOCTL_NDIS_REBIND_ADAPTER。
如何向控制面板中那样,修改系统声音的音量
调用API waveOutSetVolume(HWAVEOUT, dwVolume ),一般参数1为0。在[HKEY_CURRENT_USER\\ControlPanel\\Volume]下是系统声音的注册表设置。
在应用程序中如何实现jpg、gif图片的显示
有几种办法:
1、 在MSDN中搜索标题为“Windows CE .NET Technical Frequently Asked Questions”的文档,其中有一个问题“How can I display JPEG, GIF, and other graphics files?”,下面就是答案。
2、如果安装了Windows CE 5.0,一个例子源码位于WINCE500\\PUBLIC\\GDIEX\\SDK\\SAMPLES\\SIMPLE。
3、用IWebBrowser组件实现。
在应用程序中如何实现系统待机
void GwesPowerOffSystem(void);
在WINCE下如何实现键盘钩子
我写了一个简单的例子,把其中主要部分截取出来放到了我的FTP里。用户名以及密码均为winceuser,地址是ftp://211.95.73.26/fllsoft@sina.com/SourceCode/ 用钩子禁止系统键.rar。
在WINCE中如何得到网卡MAC地址
事 实证明,获得物理网卡的MAC地址并没有被统一成一个API或者IOCTL,如果网卡驱动程序没有提供接口的话只能直接访问寄存器获得。读者可以参考目录 WINCE500\\PUBLIC\\COMMON\\OAK\\DRIVERS\\NETCARD里的一些驱动源码。
Windows XP Embedded 和Windows CE有何区别
简 单地说Windows XP Embedded采用Windows XP内核,只能运行在x86处理器上,优点是能够运行PC上现有的应用软件,缺点是授权费太高,标价¥900元;Windows CE采用Windows CE内核,能够运行在多种处理器上,如x86、ARM、SHX、MIPS等,优点是授权费低,最低Core版标价¥30元。缺点是需要单独开发应用软件、 定制内核,甚至开发BSP、Driver。
wince下只是把调制解调器的驱动挂接在了com1,如何将器驱动挂接在com2上?
1、 在HLM\\drivers\\buildin\\com2\\unimodem下复制和com1一样的数据 2、在HLM\\ExtModems\\ HayesCompat下改写Port为COM2:,再改写FriendlyName为"Hayes Compatible 在 COM2:"。
如何定制自己的外壳
1、先开发一个外壳软件,假设名称为MyShell.exe
2、删除注册表[HKEY_LOCAL_MACHINE\\init]下如下一行:
"Launch50"="explorer.exe"
3、在注册表[HKEY_LOCAL_MACHINE\\init]下添加如下一行:
"Launch50"="MyShell.exe"
上述的“LaunchXX”中的XX为序列数,内核依据这个序列数按由小到大的顺序来分别执行所有子键列出的应用程序,具体数值应该为多少请参考帮助文档的说明。
如果原来的内核中添加了标准外壳(standard shell)组件,或者添加了其它组件而这些组件需要依赖标准外壳,那么在PB中是无法删除标准外壳组件的,解决办法一是保留explorer.exe在内核中,二是删除依赖标准外壳的组件。
我原来的工程是x86版本的,编译选项只有x86,我如何能够编译ARM版本的
两种办法:
1、用EVC新建一个工程的时候,建议复选“CPUs”列表,这样发生了这种事情也能够轻易通过选择“WCE Configuration”工具栏中的CPU列表来编译不同CPU版本的软件
2、如果打开工程后CPU列表中只有x86,而此时已经安装了ARM版本的SDK,那么单击EVC菜单“build”-“configurations”,然后单击“add”按钮来添加CPU。
通常情况下WINCE采用串口1作为调试时输出信息用途,要正式出产品前如何去掉串口1的调试功能
正 常情况下串口1只有在编译debug版本的内核时才在BootLoader中初始化串口1用于输出信息,而编译release版本会跳过此代码。而有些 BSP设计成没有宏定义,也就是说无论什么版本都会在BootLoader中初始化串口1,这样造成WINCE启动后串口1无法被应用程序使用。对于这种 情况只能在BootLoader源码中删除初始化代码,如OEMInitDebugSerial。
我怎么能在PB左边的定制平台加进我的驱动呢?
两种办法:
1、在platform.bib或者project.bib的MODULES部分添加一条语句,例如:
MyDriver.dll C:\\Driver\\MyDriver.dll NK SH
这样编译内核的时候就会把你的驱动DLL文件添加到内核中,如果有注册表需要设置,在platform.reg或者project.reg中添加注册表内容。
2、通过制作.cec文件来添加驱动,制作.cec文件的优点是只需制作一次,以后就可以通过将.cec文件导入到PB的Catalog中,象PB自带的feature一样通过菜单“Add to OS Design”添加到左边的内核工程中。
WINCE有没有相对路径概念?如果没有如何得到当前模块的路径?
1、WINCE没有相对路径概念,只有绝对路径,所以凡是涉及到路径均为绝对路径。
2、调用API GetModuleFileName,传递一个模块的实例句柄就能够得到模块的绝对路径。
怎样让 POCKET WORD打开*.dat格式(里面都是数据)的文件?
两种办法:
1、调用API ShellExecuteEx,在结构体SHELLEXECUTEINFO中添加.dat文件的路径。
2、调用API CreateProcess,在第二个参数中设置.dat文件的路径。
GWES组件的功能有哪些?
GWES不仅负责GDI、窗口、消息,还负责管理本机设备驱动程序,负责加载显示、键盘鼠标、触摸屏驱动程序,而且GWES本身包含电源、LED驱动程序。
如何在PB中预先设定好存储内存和程序内存的大小,我想多划分一些空间给程序内存?
两种办法:
1、在定制内核时在config.bib文件中设置FSRAMPERCENT = number,具体number可参考标题为“FSRAMPERCENT ”的帮助文档。这种办法是修改内核的设置,所有一直有效。
2、在应用程序中调用API SetSystemMemoryDivision,如果函数返回SYSMEM_CHANGED表示成功,如果返回SYSMEM_MUSTREBOOT表示需要热启动才能有效。这种办法需要每次启动后调用API才有效。
如何取消鼠标光标?
通过取消SYS变量来实现此目的,在PB命令行下键入“set SYSGEN_CURSOR=”,然后回车确认。
EVC下调用TextOut如何编译会出错?
类 似这样的问题很多,这是因为EVC的帮助文档内容有错误。可能EVC的帮助文档内容是从桌面Windows帮助文档复制过来的,所以很多API函数还有例 子代码都有错误,例如帮助文档中包含一个API函数的说明,但是实际编译的时候提示没有这个API,有的例子代码采用ANSI字符串,而WINCE的 API都是宽字符版本,造成直接复制过来编译失败。
因为MFC for WINCE的CDC类中没有TextOut成员函数,所以编译会出错,可以用其它类成员函数ExtTextOut或者DrawText替换。
我如何将我的dll软件让现有的ce系统认可?尽管我也知道应该使用signfile.exe程序进行签名,但是我并不知道那个ce系统认可的签名应该是啥
如果你说的WINCE系统内核已经加入了签名认证机制,那么没有私钥对你的DLL文件签名肯定是无法运行在此内核中的,一般签名密钥的密钥长度都是1024位,很难破解。
如果查看WINCE注册表中的内容?
两种办法:
1、建立同步后,用EVC自带的工具“Remote Registry Editor”打开查看。
2、从网上下载注册表查看工具,放到WINCE设备中。
调用directshow出现链接错误,如何解决?
player.obj : error LNK2001: unresolved external symbol _IID_IVideoWindow
player.obj : error LNK2001: unresolved external symbol _IID_IMediaControl
这是因为链接器没有找到合适的.lib文件。两种办法:
1、 在EVC菜单Tools—options—directories 里把library files的路径重新调整一下。如果你只安装了EVC自带的 Standard SDK而没有其它SDK,可以指定WINCE目录中的.lib文件路径,例如D:\\WINCE500\\PUBLIC\\DIRECTX\\ OAK\\LIB\\X86\\RETAIL。注意CPU的类型。
2、安装SDK,前提是导出SDK的PB内核工程必须包括DirectShow或者其它组件。
在PB的config.bib文件中,“IMGFLASH”表示什么意思呢?
表示能够刷NK到ROM中,具体请查看标题为“IMG Environment Variables”的帮助文档。
驱动程序如何发通知给应用程序?
这里介绍一下常见的两种办法。
1、 驱动程序调用API SendNotifyMessage,发送特定的消息给应用程序,这就要求应用程序要有消息循环机制并且要事先做好消息的处理。参数 1为窗口句柄,可以设置HWND_BROADCAST表示广播消息。要注意的是不要在参数中传递指针(虚拟地址),因为执行驱动程序的线程和应用程序并不 在同一个进程空间中。解决办法可以利用内存映射文件技术,比如在驱动程序中创建一个内存映射文件对象,申请一块物理内存,然后把对象名称和内存长度传递给 应用程序,应用程序打开同名的内存映射文件对象,读取里面的数据。对象名称可以事先协定好,也可以通过注册表来传递,内存长度是32位值,通过消息参数就 可以传递,也可以通过注册表来传递。另外一种解决办法是在定制内核时候预留一块物理内存,这样驱动程序和应用程序都可以通过VirtualAlloc和 VirtualCopy来映射到同一块物理内存,其原理同内存映射文件技术一样,但是这块物理内存不具备通用性。最后一个办法是应用程序事先将一个缓冲区 地址传递给驱动程序,驱动程序调用MapPtrToProcess映射应用程序传递过来的地址,当驱动程序调用SendNotifyMessage后应用 程序可以直接到该地址中读取数据。
设备管理器就是调用此函数广播WM_DEVICECHANGE消息的。另外WINCE的一个例子程序RNAApp在拨号连接建立的时候也是调用这个函数广播WM_NETCONNECT消息的。
2、 驱动程序调用API CeEventHasOccurred指明一个事件A发生,在此之前应用程序调用API CeRunAppAtEvent将驱动程序指明的A事件和一个应用程序名称相关联,或者和一个事件B相关联。这样当A事件发生时,如果指明和一个应用程序 名称关联,那这个应用程序就会被启动。如果指明了和一个事件B相关联,那么等待事件B的线程将被激活。如果想了解当前系统内部所有驱动程序支持哪些类似事 件A的事件,调用 API CeNotifyPublic_FilterEvent,在该API的帮助文档里也列举了常见的事件,例如 NOTIFICATION_EVENT_NET_CONNECT和 NOTIFICATION_EVENT_NET_DISCONNECT。
如何让系统加载自己写的驱动程序?
两种办法:
1、在[HKEY_LOCAL_MACHINE\\Drivers\\BuiltIn]下添加注册键。
2、在应用程序中调用ActivateDeviceEx。
在一些文件中用分号来表示注释,例如下面的内容
; @CESYSGEN IF SERVERS_MODULES_HTTPD
; @CESYSGEN ENDIF
在“CESYSGEN...”前加了“@”,有没有什么特别的含义?
在WINCE的一些文件中,用“;”作为注释并在注释文字中用@CESYSGEN作为标记,后面接条件语句。Cefilter.exe工具负责按照条件来筛选文件内容,所以不要轻易地删除包含@CESYSGEN的注释语句。
通过串口建立ActiveSync联接,串口线用三线的可以吗?
不可以,因为用串口同步时要用到其余口的状态。
WINCE是否支持MAPI?
不支持。WINCE自带的pmail.exe软件也不是很好用。建议自开发邮件收发软件。如果需要购买WINCE下邮件收发软件可以联系我。
如何旋转屏幕显示的内容?
例子代码如下(前提是显示驱动程序支持旋转):
DEVMODE devmode = {0};
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDisplayOrientation = DMDO_90; ///垂直模式
devmode.dmFields = DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0, NULL); ///改变显示的设置
CRect rcWorkArea(0, 0, 320, 240); ///整个屏幕尺寸
///设置客户区大小并广播消息,这样所有软件也就随之更改显示
SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea, SPIF_SENDCHANGE);
请问如何修改字形缓存的容量?
[HKEY_LOCAL_MACHINE\\System\\GDI\\GLYPHCACHE]
"limit"=dword:0400
如何得到从WINCE启动开始到现在的时间?
调用API GetTickCount,得到的值为32位整数,单位为毫秒。
如何调用WINCE的软键盘?
调用API SipShowIM(SIPF_ON),前提是内核加入了软键盘组件。
基于HIVE的注册表,如何在系统关闭前保存注册表的数据到文件system.hv?
调用API RegFlushKey函数。
使用VirtualAlloc和VirtualCopy的时候需要注意哪些事项?
1、 VirtualAlloc的作用是申请虚拟地址空间,这肯定不是最终的目的,最终目的可能是申请物理内存、映射寄存器、提交文件等。没有一个目的会在意虚 拟地址空间的位置,所以尽量传递参数1为0,也就是让WINCE自动分配虚拟地址空间。VirtualAlloc分配地址空间实际上是以64KB为单位, 所以要指定申请的虚拟空间的首地址的话,参数1应该为64KB的整数倍,申请的长度也应该为64KB的整数倍,即使你不需要那么大。
2、 VirtualCopy的主要作用是映射物理地址空间,如果参数2为物理地址,那么最后一个参数要添加PAGE_PHYSICAL,参数2必须是256的 整数倍。如果参数2为虚拟地址(0x80000000以上),那么最后一个参数就不要添加PAGE_PHYSICAL,WINCE内核会根据这个虚拟地址 找到对应的物理地址。
驱动程序和应用程序之间传递数据时何时调用MapPtrToProcess?
因为设备管理器负 责加载驱动程序DLL,这意味着当应用程序调用驱动程序接口函数的时候,WINCE内核会将调用驱动程序接口函数的线程转移到设备管理器的进程空间然后执 行具体的驱动程序代码,应用程序和设备管理器处于两个进程空间,这就造成设备管理器无法访问应用程序传递的指针(虚拟地址),所以当我们在应用程序中传递 指针给流驱动程序接口函数时,WINCE内核从中作了一个地址映射,例如ReadFile、WriteFile、DeviceIoControl函数的参 数凡是指针都经过了映射才传递给驱动程序,所以很多驱动程序开发者并不了解其中的奥秘就可以编程了。但是如果参数是一个指向一个结构体的指针,而结构体里 包括一个或多个指针,那么WINCE内核并不负责映射,所以就需要开发者在驱动程序接口函数中调用API函数MapPtrToProcess来映射地址。 例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());
如何判断可插拔的设备是否存在?
1、 通过查找注册表的值。凡是由API ActivateDeviceEx加载的驱动程序都在[HKEY_LOCAL_MACHINE\\Drivers\\Active]键下有注册键,通过查 找“name”或者其它键值就能够找到。设备管理器就调用这个API。如果是PCI设备,在注册表[HLM\\Drivers\\BuiltIn \\PCI\\Instance]下查找关键字,例如[HLM\\ Drivers\\BuiltIn\\PCI\\Instance\\WaveDev1],说明音频驱动已经加载。
2、调用驱动程序接口函数,根据返回值或者执行结果来判断。
如何做到通过串口过来的一个信号启动自己开发的应用程序?
创 建一个线程负责等待串口过来的信号,调用API SetCommMask设置要等待的信号种类,具体可以等待的信号种类参见参数2的说明。然后再调用 API WaitCommEvent函数等待这个信号,接收之后再调用API CreateProcess启动应用程序。
在WINCE中如何只能启动应用程序的一个实例?
常用的两种办法:
1、如果应用程序实例创建了窗口,可通过API FindWindow函数通过窗口类名和窗口标题名称来查找,前提是系统内不会出现窗口名称重复的情况。
2、应用程序初始化的时候创建一个事件或互斥等内核对象,因为内核对象是由内核创建,名称在系统内唯一。
能不能自己编辑一个数字签名文件导入到手机上,这样就可以用这个签名签自己的程序了?
WINCE的内核签名机制的用途是限制非法的可执行模块EXE、DLL等在设备上运行。要求内核的加载模块用公钥验证请求加载的EXE、DLL的签名是否合法,而这个公钥是在定制内核的时候加进去的,所以除内核的定制者以外的人无法修改这个验证机制。
我按照版主的文章《加密WINCE系统》里操作,提示错误如下:
Error 80090016 during CryptSignHash 1!
Error signing hash
这 是因为传递了无效的钥容器名称,使CryptoAPI调用失败。应该在使用signfile工具之前创建一个钥容器,在桌面Windows中调用 API CryptAcquireContext创建一个指定名称的钥容器,接着再创建一个签名密钥对,这时再使用signfile工具就可以了。我在文章里写成 -kfulinlin是因为我创建钥容器的时候没有指定名称,系统就采用当前登录的用户名为容器名。
编译错误:CVTRES : fatal error CVT1102: out of memory; 42 bytes required ?
多 数情况下出现这种错误是因EVC的bug而起,应该在安装EVC之后就立刻安装EVC的SP补丁。另外为了避开BUG,使用EVC编程应该养成一些习惯, 比如定期备份工程所有文件,每次编译时采用Clean + Rebuild All,正调试时不要关闭模拟器等等。
在WINCE下是否能够得到某一进程使用的物理内存总量?
目前没发现有这样一个API能够得到指定进程使用的物理内存总量。只有GlobalMemoryStatus能够得到整个系统使用的物理内存总量。
应用程序如何控制lcd的亮度?如何获得电池的电量?
从 常见的平台如Geode、三星ARM系列来看,的确在驱动方面没有统一的控制LCD或者其它种类屏幕亮度的接口函数,所以只能根据具体平台提供的接口来 做。从帮助文档来看微软的带有DirectDraw功能的显示驱动程序的确有标准的增加亮度的接口函数,关于背景光参见标题为 “Enabling a Backlight”的帮助文档。
获得电池电量有标准的接口函数GetSystemPowerStatusEx,前提是驱动程序和硬件都要支持。
WINCE的socket函数好像不支持发送/接收超时?
是的,最早版本的WINCE支持选项SO_RCVTIMEO、SO_SNDTIMEO,后来却不支持了。
WINCE下如何设置窗口最大化和最小化?
WINCE 的帮助文档在介绍API ShowWindow函数的参数时指出SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE都不被支持,但实际上并不完全是这样,具体来说:
SW_MAXIMIZE 比原来窗口大,但不是最大化
SW_MINIMIZE 编译成功,但是不起作用
SW_SHOWMAXIMIZED 最大化
SW_SHOWMINIMIZED 编译出错
SW_RESTORE 能恢复
SW_SHOWDEFAULT 编译出错
SW_SHOWMINNOACTIVE 编译出错
SW_HIDE 能够隐藏
如何用程序调用控制面板的触摸屏校对程序?
两种办法:
1、调用API TouchCalibrate函数
2、调用CreateProcess,参数1为L"\\\\windows\\\\ctlpnl.exe",参数2为L"cplmain.cpl,9"。
如何获得U盘或者其它类型的存储器总容量和剩余可用容量?
调用API GetStoreInfo得到扇区数、每扇区字节数,相乘即是总容量。调用API GetDiskFreeSpaceEx得到剩余可用容量。
基于RAM的注册表如何保存数据?
调用API RegCopyFile备份注册表。调用API RegRestoreFile恢复注册表,然后调用KernelIoControl热启动使恢复生效。
如何隐藏和显示winCE下标准外壳的任务栏?
HANDLE hTaskBar = FindWindow(L"HHTaskBar", NULL);
ShowWindow(hTaskBar, SW_HIDE);
ShowWindow(hTaskBar, SW_SHOWNORMAL);
wince下如何让操作系统进入待机模式?又如何把它激活?
通过注册表就可以设置,前提是你的驱动和硬件都支持。注册表项参见标题为“GWES Suspend Time-outs”的帮助文档。
[HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Power]
"BattPowerOff"=dword:300
"ExtPowerOff"=dword:0
"WakeupPowerOff"=dword:60
"ScreenPowerOff"=dword:0
在WINCE中如何只能启动应用程序的一个实例? 常用的两种办法: 1、如果应用程序实例创建了窗口,可通过API FindWindow函数通过窗口类名和窗口标题名称来查找,前提是系统内不会出现窗口名称重复的情况。 2、应用程序初始化的时候创建一个事件或互斥等内核对象,因为内核对象是由内核创建,名称在系统内唯一。 能不能自己编辑一个数字签名文件导入到手机上,这样就可以用这个签名签自己的程序了? WINCE的内核签名机制的用途是限制非法的可执行模块EXE、DLL等在设备上运行。要求内核的加载模块用公钥验证请求加载的EXE、DLL的签名是否 合法,而这个公钥是在定制内核的时候加进去的,所以除内核的定制者以外的人无法修改这个验证机制。 我按照版主的文章《加密WINCE系统》里操作,提示错误如下: Error 80090016 during CryptSignHash 1! Error signing hash 这是因为传递了无效的钥容器名称,使CryptoAPI调用失败。应该在使用signfile工具之前创建一个钥容器,在桌面Windows中调用API CryptAcquireContext创建一个指定名称的钥容器,接着再创建一个签名密钥对,这时再使用signfile工具就可以了。我在文章里写成 -kfulinlin是因为我创建钥容器的时候没有指定名称,系统就采用当前登录的用户名为容器名。 编译错误:CVTRES : fatal error CVT1102: out of memory; 42 bytes required ? 多数情况下出现这种错误是因EVC的bug而起,应该在安装EVC之后就立刻安装EVC的SP补丁。另外为了避开BUG,使用EVC编程应该养成一些习 惯,比如定期备份工程所有文件,每次编译时采用Clean + Rebuild All,正调试时不要关闭模拟器等等。 在WINCE下是否能够得到某一进程使用的物理内存总量? 目前没发现有这样一个API能够得到指定进程使用的物理内存总量。只有GlobalMemoryStatus能够得到整个系统使用的物理内存总量。 应用程序如何控制lcd的亮度?如何获得电池的电量? 从常见的平台如Geode、三星ARM系列来看,的确在驱动方面没有统一的控制LCD或者其它种类屏幕亮度的接口函数,所以只能根据具体平台提供的接口来 做。从帮助文档来看微软的带有DirectDraw功能的显示驱动程序的确有标准的增加亮度的接口函数,关于背景光参见标题为“Enabling a Backlight”的帮助文档。 获得电池电量有标准的接口函数GetSystemPowerStatusEx,前提是驱动程序和硬件都要支持。 WINCE的socket函数好像不支持发送/接收超时? 是的,最早版本的WINCE支持选项SO_RCVTIMEO、SO_SNDTIMEO,后来却不支持了。 WINCE下如何设置窗口最大化和最小化? WINCE的帮助文档在介绍API ShowWindow函数的参数时指出SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE都不被支持,但实际上并不完全是这样,具体来说: SW_MAXIMIZE 比原来窗口大,但不是最大化 SW_MINIMIZE 编译成功,但是不起作用 SW_SHOWMAXIMIZED 最大化 SW_SHOWMINIMIZED 编译出错 SW_RESTORE 能恢复 SW_SHOWDEFAULT 编译出错 SW_SHOWMINNOACTIVE 编译出错 SW_HIDE 能够隐藏 如何用程序调用控制面板的触摸屏校对程序? 两种办法: 1、调用API TouchCalibrate函数 2、调用CreateProcess,参数1为L"\\\\windows\\\\ctlpnl.exe ", 参数2为L"cplmain.cpl,9"。 如何获得U盘或者其它类型的存储器总容量和剩余可用容量? 调用API GetStoreInfo得到扇区数、每扇区字节数,相乘即是总容量。调用API GetDiskFreeSpaceEx得到剩余可用容量。 三星2440头文件定义#define IIC_BASE 0xB1400000 // 54000000,datasheet是54000000,那么怎么转成0xB1400000? 物理地址映射方法分为两种,一种静态映射另一种为动态映射。在OEMAddressTable中定义了物理地址与虚拟地址的映射关系属于静态映射,用 VirtualCopy映射属于动态映射,采用哪种办法都可以。问题中提到的属于静态映射,2440的BSP在map.a文件中定义了IIC控制寄存器的 物理起始地址和对应的虚拟地址如下: DCD 0x91400000, 0x54000000, 1 ; 在OEMAddressTable中定义的虚拟地址范围在0x8000 0000—0x9FFF FFFF,这部分可缓存,适合内核程序和应用程序使用,同时WINCE内核在0xA000 0000—0xBFFF FFFF中映射了另一份,指向了同样的物理地址,这部分不可缓存,适合驱动程序使用。三星ARM处理器带有L1级高速缓存,可缓存会提高执行效率。对于特 殊的设备寄存器适合映射到不可缓存的虚拟地址。 当驱动程序调用VirtualCopy对0xB1400000地址读写时,WINCE自动将这个地址减去0x2000 0000,也就是0x91400000,对应的物理地址就是0x54000000,也就是IIC控制寄存器的物理起始地址。 基于RAM的注册表如何保存数据? 调用API RegCopyFile备份注册表。调用API RegRestoreFile恢复注册表,然后调用KernelIoControl热启动使恢复生效。 如何隐藏和显示winCE下标准外壳的任务栏? HANDLE hTaskBar = FindWindow(L"HHTaskBar", NULL); ShowWindow(hTaskBar, SW_HIDE); ShowWindow(hTaskBar, SW_SHOWNORMAL); 如果能让WINCE的IE浏览器播放flash动画? 播放flash需要Macromedia Flash Player SDK,参见http://www.adobe.com/products/flashplayer_sdk/。这和real player相似,都需要WINCE平台的SDK,都需要申请。 WINCE下内核模式和用户模式有什么区别? 为了使读者能够详细了解WINCE的地址映射原理还有两种模式,在这里我分几个部分说明: 1、WINCE内核nk.exe的任务是管理操作系统核心功能。按照OEMAddressTable的映射要求,所有物理地址都映射到 0x80000000以上,所以对于内核程序nk.exe和内核模式下的线程来说,只要访问0x80000000以上的有效虚拟地址经MMU就能够访问物 理地址,无需再映射是内核模式的一个特点。内核模式的第二个特点是没有地址访问限制,内核模式线程可以访问任何有效虚拟地址,所谓有效虚拟地址是指有实际 事物对应。 2、用户模式线程只能访问0x80000000以下的虚拟地址空间,WINCE6.0之前版本的内核为每个进程划分32MB的地址空间,在不调用特殊函数 的情况下不能相互访问,这样的设计使得WINCE系统更安全、更稳定,限制访问地址是用户模式的第一个特点。第二个特点就是需要多一层映射,如果线程要访 问物理内存的话需要先映射到0x80000000以上,再经MMU访问物理内存地址。 WINCE的线程具有转移性(参考API GetCallerProcess的说明,有一个很好的例子),当应用程序的线程调用API或者调用驱动程序接口函数时,该线程会转移到 gwes.exe、device.exe、filesys.exe等进程中执行,转移是由WINCE内核操作的,它会修改线程的上下文,记录线程的当前进 程、调用者进程、拥有者进程三个值。 3、如果在定制内核的时候选择了“Full Kernel Mode”,那么在这个内核上运行的所有线程都处于内核模式,即使调用SetKMode(FALSE)后线程仍然具有内核模式的特点,能够访问任何有效的 虚拟地址。假设现有一个64MB RAM的WINCE产品,RAM映射从0x80000000到0x84000000,如果线程处于内核模式,它就直接可以访问这个范围的虚拟地址: 在OnButton1()中编写 代码: DWORD oldMode = SetKMode(FALSE); volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000) *piTemp = 12345; 在OnButton2()中编写 DWORD oldMode = SetKMode(FALSE); volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000) int iTemp = *piTemp; 先只执行OnButton1()然后关闭程序,再重启程序然后执行OnButton2(),iTemp仍然等于12345。结果说明了两点:内核模式线程 可以直接访问0x80000000以上的有效虚拟地址;我们写到RAM中的数据没有丢失,说明虚拟地址有效。 如果在定制内核的时候没有选择“Full Kernel Mode”,那么在这个内核上运行的所有线程都处于用户模式。可以调用SetKMode(TRUE)使调用线程暂时处于内核模式,还是原来的假设环境,我 再举个例子: 在OnButton1()中编写 DWORD oldMode = SetKMode(TRUE); volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000) *piTemp = 12345; 在用户模式下,如果不调用SetKMode(TRUE),那么执行*piTemp = 12345一定会弹出对话框,提示地址访问非法,如果调用SetKMode(TRUE)就不会提示地址访问非法,而且在OnButton2()中仍然能得 到12345这个值。 通过这两个例子我相信读者能够完全了解两种模式的区别了。 4、WINCE提供了两个函数SetKMode和SetProcPermissions,其中SetKMode能够把调用线程切换到内核模式,还可以切换 回用户模式。SetProcPermissions + GetCurrentPermissions添加当前进程访问权限给调用线程,SetProcPermissions (0xFFFFFFFF)能让调用线程访问所有进程空间,但是调用线程仍然处于用户模式。SetKMode和SetProcPermissions函数使 得用户模式的特点不那么明晰。 如上所说一个应用程序的线程可能转移到其它两个进程地址空间中读写数据,而每一个线程在被创建的时候只有访问创建它的进程地址空间的权限,所以驱动程序开 发者必须在驱动程序读写数据前调用SetKMode或者SetProcPermissions增加调用此函数的线程访问其它进程空间的权限。如果一个应用 程序的线程只转移到一个进程地址空间,一般为设备管理器进程device.exe,这种情况下不必增加线程访问其它进程空间的权限,但如果驱动程序本身创 建了一个线程,那还是要调用SetKMode或者SetProcPermissions增加新的线程访问其它进程的权限的,因为驱动程序创建线程时,当前 进程为设备管理器,所以新线程只具有访问设备管理器进程空间的权限,而不具备访问应用程序进程空间的权限。 5、可能一个编写过简单的流驱动的初学者会很疑惑,因为开发一个简单的流驱动程序根本不需要调用这些函数,也没有调用过MapPtrToProcess, 那是因为如果标准流驱动接口函数的参数为指针(ReadFile、WriteFile、DeviceIoControl参数都有指针),WINCE内核会 自动映射指针包含的地址,但仅此而已,其余任何情况都要求开发者自行处理,比如流接口函数的参数是一个指向结构体的指针PA,而结构体中包括指针 PB,PB指针就必须在流接口函数中映射,映射后才能访问,否则就会造成地址访问非法。所以结构体中每个指针都要映射。 为了让读者能了解其中的原因,我举个例子: 假设设备管理器被加载到Slot4,应用程序A被加载到Slot 8,A只有一个主线程T,T开始执行,按照WINCE的规定,正获得CPU的进程必须映射到Slot0,那么在执行代码的时候A的所有虚拟地址都被减去一 个偏移值,也就是8×0x0200oooo,A调用DeviceIoControl,传递一个指向一个结构体的指针B,而这个结构体中包含一个指针C,指 针C包含的地址假设为0x00030000,当执行DeviceIoControl时WINCE把设备管理器的进程地址空间映射到Slot0,因为放在注 册表[HKLM\\Drivers\\BuiltIn]下的驱动程序是由设备管理器加载的,自然驱动程序的代码段被加载到设备管理器进程空间,但是线程仍 然是T,此时T的当前所在进程为设备管理器(CurrentProcess),A变成了T的调用者进程(CallerProcess),T自动具有了访问 调用者进程空间的权限。这时访问Slot0中的虚拟地址其实质就是访问设备管理器的进程地址空间,要把地址加上一个偏移值,也就是 4×0x02000000,所以DeviceIoControl访问指针C包含的地址时本应该加上8×0x02000000,却加上 4×0x02000000,结果地址并不是设备管理器的合法区域,系统就会提示地址访问非法。而如果做了一个映射,指针C包含的地址就会被加一个正确的偏 移值,使地址处于A的地址空间Slot 8中,T此时具有访问A进程空间的权限,访问到正确的虚拟地址当然会得到正确的数据了。
- EVC开发技巧
- 转载:PocketPC - EVC开发技巧大集合
- PocketPC - EVC开发技巧大集合
- EVC技巧
- EVC的小技巧
- EVC编程技巧集合
- EVC技巧二
- EVC开发每一天
- eVC++开发实例
- EVC开发概述
- evc+mapxmobile 开发
- EVC开发二三点
- EVC开发概述
- EVC一些常用的技巧
- EVC中常用技巧大全
- 学习evc/pb移动开发
- EVC开发MapXMobile 环境搭建
- EVC /PB /WinCE开发问题
- 走到人生最精彩的部分
- EVC开发的一般问题解答(转)
- Cron Quartz
- 如何在WebView中建立Android Apps
- new动态分配内存(在堆上)
- EVC开发技巧
- windows xp,windows 7电源管理总结
- 安装TestDirector8.0报错:Access violation at address 005FB5DB in module ‘setup.exe’ 解决方法
- 三线圈电感传感器口径与灵敏度的关系
- Domino JVM异常
- FLEX-Bindable
- RAD Studio XE2全球发布会(北京、深圳)圆满结束
- linux 常见的命令(转)
- 关于Arrays.asList()