关于嵌入开发(WinCE)的一些经验

本文介绍了Windows CE环境下Unicode与Ansi字符之间的转换方法,包括发送和接收数据时的编码转换实例,适合初学者快速掌握跨平台字符编码处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WindowsCE下Unicode和Ansi字符间互相转换的例子
纵所周知,WindowsCE下编程99%的问题都和Unicode有关.比如文件编辑,一般都保存为Ansi格式;无线通讯中控制Modem需要发送的AT指令,必须是Ansi格式;网络通讯中,PC端一般都是Ansi的,为了和PC上协议兼容,在WindowsCE中必须把要发送的一个指令从Unicode转换成Ansi格式...等等.很多初学者对于这些问题总是感到很麻烦.其实WindowsCE中有标准的API实现了Unicode和Ansi字符间的互转.下面就是网络通讯中的程序片断.
m_psocket是指向一个从CCeSocket派生的类,如果没有连接的话其为NULL;
m_snd是要发送的CString,和一个EDIT相对应.
  //发送函数片断
  void CClient1Dlg::OnButtonSend()
  {
        // TODO: Add your control notification handler code here
        if (!m_psocket) //无Socket连接,退出
        {
                MessageBox(TEXT("无连接!"),TEXT("信息"));
                return;
        }
        UpdateData(TRUE); //保存输入的字符串到m_snd
        unsigned char buf[129]; //发送缓冲区
        ZeroMemory(buf,sizeof(buf)); //缓冲区清零
        CString tmpstr(m_snd); //复制要发送的字符串
        int multibytelen=WideCharToMultiByte( //计算从Unicode转换到Ansi后需要的字节数
        CP_ACP, //根据ANSI code page转换
        WC_COMPOSITECHECK | WC_DEFAULTCHAR, //转换出错用缺省字符代替
        tmpstr.GetBuffer(m_snd.GetLength()), //要转换的字符串地址
                m_snd.GetLength(), //要转换的个数
                0, //转换后字符串放置的地址
                0, //最多转换字符的个数,为0表示返回转换Unicode后需要多少个字节
                0, //缺省的字符:"/0"
                0 //缺省的设置
         );
        WideCharToMultiByte( //转换Unicode到Ansi
                CP_ACP,
                WC_COMPOSITECHECK | WC_DEFAULTCHAR,
                tmpstr.GetBuffer(m_snd.GetLength()),
                m_snd.GetLength(),
                (char *)buf, //转换到缓冲区中
                128, //最多128个字节
                0,
                0
          );
        int sendcount=m_psocket->Send(buf,multibytelen+1); //发送转换后的缓冲区
        CString statusstr;
        statusstr.Format(TEXT("共发送字节数:%d"),sendcount);
        m_status.SetWindowText(statusstr); //更新显示栏
  }
程序接收到的字符串最后保存到CString tmpstr中.
  //接收函数片断
  void MyCeSocket::OnReceive(int nErrorCode)
  {
        // TODO: Add your specialized code here and/or call the base class
        unsigned char p[129]; //接受缓冲区
        ZeroMemory(p,sizeof(p)); //接收缓冲区清零
        this->Receive(p,128); //接收128个字节
        int widecharlen=MultiByteToWideChar( //计算从Ansi转换到Unicode后需要的字节数
                CP_ACP,
                MB_COMPOSITE,
                (char*)p, //要转换的Ansi字符串
                -1, //自动计算长度
                0,
                0
        );
        CString tmpstr;
        tmpstr.GetBuffer(widecharlen); //为转换后保存Unicode字符串分配内存
        MultiByteToWideChar( //从Ansi转换到Unicode字符
                CP_ACP,
                MB_COMPOSITE,
                (char*)p,
                -1,
                tmpstr.GetBuffer(widecharlen), //转换到tmpstr
                widecharlen //最多转换widecharlen个Unicode字符
        );
        m_clientdlg->m_listbox.InsertString(0,tmpstr); //插入到listbox中显示
        CCeSocket::OnReceive(nErrorCode);
  }
注意:以上代码都是在WindowsCE样板机上运行,PC端发送和接收到的字符均为Ansi格式的.把以上代码稍微修改一下用到自己的产品中,就可以利用以前的协议无缝连接PDA和PC.
以上代码在MicroSoft Embed Visual C++ 3.0 + 联想天玑5100(WindowsCE3.0)
+ Eagle Tec 10M CF卡通过.

 

用eVC编制了一个ActiveX控件,提示需要registered to the desktop,
用vs提供的ActiveX control test container 进行注册,可怎么也注册不上
为什么?应该怎么注册呢?
可以用VC的ActiveX control test container 进行注册,只不过要进行稍微改动。
1.用VC产生一个与EVC相同名字的Active x工程,比如为pocket。
2.把VC工程中的dsp和dsw文件重命名,pocket-win32.dsw和pocket-win32.dsp拷到EVC工程的文件夹中。
3.修改pocket-win32.dsw文件,使他指向pocket-win32.dsp。
 Project: "Pocket"="./Pocket.dsp"
改为Project: "Pocket"="./Pocket_Win32.dsp"
4.修改output 文件的名称,使它指向evc工程的文件夹。
即可


我需要用一种特定的图案填充进度条的条的颜色,不知道能不能实现?
CProgressCtrl mCtrl;
在OnInitDialog()中:
   mCtrl.Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH, CRect(10,10,200,30),
         this, IDC_PROGRESS);
   mCtrl.SetRange(0,10);
   mCtrl.SetPos(0);
   mCtrl.SetStep(1);
在OnPaint()中:
{
 CPaintDC dc(this);
 CRect rect(10,10,200,30);
         CBitmap bmp;
 bmp.LoadBitmap(IDB_PROGRESS);
 CBrush brush(&bmp);
 dc.FillRect(rect,&brush);
}
在OnStep()中(按一下按钮进度条前进一步)
{
 mCtrl.StepIt();
}


(EVC3)启动PPC2002模拟器,在EVC的TOOLS菜单下选择“Remote File Viewer”,启动Windows CE Remote File Viewer。
使Remote File Viewer与PPC2002模拟器连接,选择工具栏上第一个按钮。弹出Select Windows CE Device对话框,选择对应的模拟器或硬件设备---PPC2002后确定。在Remote File Viewer中就可以看到PPC2002中的文件。
在Remote File Viewer中选择菜单FILE下的“Export File”,将想要的文件传输到模拟器的相应的目录中。

“添加/删除硬件向导”----------“添加/排除设备故障”----------“选择一个硬件设备”中选择“Microsoft Loopback Adapter”.


隐藏“开始”栏
HWND lpClassName;
lpClassName = ::FindWindow(TEXT("HHTaskBar"), NULL);
::ShowWindow(lpClassName, SW_HIDE);

只隐藏Taskbar还不行,你得把work area 设为整个屏幕:
int screenx=GetSystemMetrics(SM_CXSCREEN);
int screeny=GetSystemMetrics(SM_CYSCREEN);
CRect rcWorkArea;
rcWorkArea.left = 0;
rcWorkArea.right = screenx;
rcWorkArea.top = 0;
rcWorkArea.bottom = screeny;
::SystemParametersInfo( SPI_SETWORKAREA, 0, &rcWorkArea, SPIF_SENDCHANGE );


 

如何获取 Pocket PC 2002 装置的序列号(以下例程获取的装置的序列号通常是Flash ROM的ID号.)?
--------------------------------------------------------------------------------
   从 Pocket PC 2000 开始, 微软就建议OEM厂商提供一个叫 KernelIoControl 的函数, 以便用户能访问Pocket PC 2002装置内建的序列号; 遗憾的是, 几乎没有厂商提供这个支持.
从 Pocket PC 2002 开始, 微软开始强制OEM厂商提供此函数. 目前市面上所有经过biplip测试的Pocket PC 2002装置都支持这个函数调用.
以下是个调用例子:

#include
extern "C" __declspec(dllimport)
BOOL KernelIoControl(
  DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize,
  LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned
);

#define IOCTL_HAL_GET_DEVICEID CTL_CODE(FILE_DEVICE_HAL, 21, METHOD_BUFFERED, FILE_ANY_ACCESS)

CString GetSerialNumberFromKernelIoControl()
{
 DWORD dwOutBytes;
 const int nBuffSize = 256;
 byte arrOutBuff[nBuffSize];

 BOOL bRes = ::KernelIoControl(IOCTL_HAL_GET_DEVICEID,
                                     0, 0, arrOutBuff, nBuffSize, &dwOutBytes);

 if (bRes) {
  CString strDeviceInfo;
  for (unsigned int i = 0; i   CString strNextChar;
   strNextChar.Format(TEXT("%02X"), arrOutBuff[i]);
   strDeviceInfo += strNextChar;
  }
  CString strDeviceId =
   strDeviceInfo.Mid(40,2) +
   strDeviceInfo.Mid(45,9) +
   strDeviceInfo.Mid(70,6);

  return strDeviceId;
 } else {
  return _T("");
 }
}
=====================================================================================

我用以下代码成功禁止任务栏被点击,但不知怎样才能解除,特此请教,谢谢。
LONG lOldWindowStyle;
RECT rectOldTaskBarRect;

HWND hOldhTaskBar = ::FindWindow(_T("HHTaskBar"),NULL);
 
while( hOldhTaskBar == NULL )
{
 hOldhTaskBar = ::FindWindow(_T("HHTaskBar"),NULL);
 Sleep( 1000 );
}

::GetWindowRect( hOldhTaskBar, &rectOldTaskBarRect );
::SetWindowPos( hOldhTaskBar, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
lOldWindowStyle = GetWindowLong(hOldhTaskBar, GWL_STYLE);
::SetWindowLong( hOldhTaskBar, GWL_STYLE, lOldWindowStyle|WS_DISABLED );


比如控制打开一个jpg文件。
我用的是ShellExecute,好像有点问题:
ExecuteFile(LPCTSTR filename)
{
 SHELLEXECUTEINFO info; 
 info.cbSize=sizeof(SHELLEXECUTEINFO);
 info.fMask=SEE_MASK_NOCLOSEPROCESS;
 info.hwnd=this->GetSafeHwnd();
 info.lpVerb=L"open";
 info.lpFile=filename;
 info.lpParameters=NULL;
 info.lpDirectory=NULL;
 info.nShow=SW_SHOW;
 return ShellExecuteEx(&info);
}
这会用IE来打开jpg
每次总是第一次的时候对,以后调用的时候总是自动调原来的东西,没有更新。还有其他更好用的api吗?

Microsoft® eMbedded Visual C++ 4.0
http://download.microsoft.com/download/WindowsCENETPlatformBuilder/Install/4.0/NT5XP/EN-US/eVC4.exe

eMbedded Visual C++ 4.0 SP1 ENU
http://download.microsoft.com/download/WinCENET41PlatBuilder/SP/4.0/NT5XP/EN-US/eVC4SP1.exe

eMbedded Visual Tools 3.0
http://download.microsoft.com/download/9/d/2/9d2f6ee8-4c75-4749-86df-2dd5189e6081/evt2002web_min.exe

OK" 按钮隐掉
SHDoneButton(AfxGetMainWnd()->m_hWnd,SHDB_HIDE);
"X" 按钮隐掉
ModifyStyle(AfxGetMainWnd()->m_hWnd,WS_CAPTION,WS_MINIMIZEBOX,SWP_NOSIZE);


ftp://ftp.wy.hziee.edu.cn/winsoft

单步调试是完全可以的。
首先安装微软的同步软件在PC机上;其次在PC机上运行该同步软件的同时,在小机上运行/Windows/repllog.exe文件;如果同步成功,在PC机上会出现一个盘符(Mobile device)。在其中可以看到小机的文件。这样同步即完成。
在选择了该目标机后,在开始调试前会出现同步提示框。同步成功后即可单步调试;我是通过这样的方法来调试CE系统的,单步不成问题!

如果您是在硬件上运行您的程序,除了SDK外还需要装同步软件,一般是Microsoft ActiveSync。可以在微软的网站上下载到。

全球第一款中文Windows手机,dopod具有强大的功能:配备Intel SA-1110 CPU,主频为206MHz,运算能力相当于PII。内存采用32兆/64兆SDRAM,32兆/64兆闪存。配备SD卡接口,可以用SD卡实现存储扩容。显示屏规格为3.5" 240x320 pixels, 4096彩色反射式TFT。内置GSM/GPRS模块,分别支持900/1800 MHz的GSM和GPRS无线通信功能。在基本应用程序方面,dopod686类似其他采用Pocket PC操作系统的高端掌上电脑,具有Pocket Word、Pocket Excel、Pocket TV以及Windows Media Player等功能。支持中文连笔手写识别,并可以做到中英文混合识别。通过Microsoft ActiveSync可以与PC同步进行数据传输。也可以通过红外接口与笔记本、其他掌上设备以及手机进行数据交换。通过类似Outlook式的联系人功能管理移动电话、电子邮件、短信等通信功能,可以方便地进行短信群发等操作。传统PDA的各种功能在dopod中仅仅能算是最为基本的功能,其最大亮点在于其强大的多媒体功能,可以非常流畅地播放音频和视频文件。

1.好像没有其它方法,为什么不用__FILE__ 中取?
2.fopen,您可以加上全路径。
3.wince2.11没有用过,但我想是支持的。在CE帮助中,一般均说明此函数从那个版本开始支持,但fopen中却没有。
4.下面是CE帮助中的一段:
    CWinApp::WriteProfileString
This method writes the specified string into the specified section of the .ini file in the application.

BOOL WriteProfileString(
LPCTSTR lpszSection,
LPCTSTR lpszEntry,
LPCTSTR lpszValue );
5.不知您所用的CE版本为多少。CE3.0不支持中文,如果您所用的是3.0,那一定是OEM商汉化了CE。可能只支持一种字体;最新版.Net支持中文,有多种字体供选择。

PC与掌上电脑的串口是不是一样,这很难说。因为嵌入式开发是针对不同硬件平台进行的!
有的掌上电脑用的是标准的RS232,有的不是。
您用EVT(EVC和EVB)写的串口操作程序,可以下载到开发板上进行测试。当然开发板上需有串口硬件。

大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功能呢?答案是肯定的,大家可以通过C#中的DllImport直接调用这些功能。 DllImport所在的名字空间 using System.Runtime.InteropServices; MSDN中对DllImportAttribute的解释是这样的:可将该属性应用于方法。DllImportAttribute 属性提供对从非托管 DLL 导出的函数进行调用所必需的信息。作为最低要求,必须提供包含入口点的 DLL 的名称。 DllImport 属性定义如下: namespace System.Runtime.InteropServices {   [AttributeUsage(AttributeTargets.Method)]   public class DllImportAttribute: System.Attribute   {    public DllImportAttribute(string dllName) {...}    public CallingConvention CallingConvention;    public CharSet CharSet;    public string EntryPoint;    public bool ExactSpelling;    public bool PreserveSig;    public bool SetLastError;    public string Value { get {...} }   } }   说明:   1、DllImport只能放置在方法声明上。   2、DllImport具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。   3、DllImport具有五个命名参数:    a、CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值 CallingConvention.Winapi。    b、CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。    c、EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint,则使用方法本身的名称。    d、ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定 ExactSpelling,则使用默认值 false。    e、PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时,它被转换为一个具有 HRESULT 返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定 PreserveSig,则使用默认值 true。    f、SetLastError 参数指示方法是否保留 Win32"上一错误"。如果未指定 SetLastError,则使用默认值 false。   4、它是一次性属性类。   5、此外,用 DllImport 属性修饰的方法必须具有 extern 修饰符。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值