WinCE驅動開發問題精華集錦

WinCE驅動開發問題精華集錦

 

如何讓系統加載自己寫的驅動程序?  
兩種辦法: 
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得到剩餘可用容量。 
 
 三星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×0x02000000,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進程空間的權限,訪問到正確的虛擬地址當然會得到正確的數據了。 
 
 爲什麼WINCE目錄下的例子用build+sysgen能夠編譯成EXE文件,而我添加的例子就不能編譯呢? 
如果這個例子是一個應用程序,那麼肯定包括代碼文件(.h .c .cpp)和資源文件(.rc和其它資源文件),build工具根據source文件內容把代碼文件編譯成lib文件,資源文件編譯成.res文件,sysgen工具根據makefile文件內容將source文件中列出的需要鏈接的各個庫文件合併成一個EXE文件。所以說關鍵在於makefile文件,WINCE目錄下凡是能夠用build+sysgen編譯的都在makefile中有如何鏈接的設置,而我們添加的例子當然沒有在makefile中找到如何鏈接的設置,nmake工具就會提示不知道如何創建。 
 
 pcienum.exe幹什麼用的? 
如果你要開發某一個PCI設備的驅動程序,首先要知道這個PCI設備的信息(如VendorID、DeviceID、BaseClass、SubClass)和PCI總線的信息。運行這個pcienum.exe就能得到相關信息。pcienum.exe提供了源碼,位置/Public/Common/Oak/Drivers/Ceddk/Test/Pcienum。 
 
 wince下如何讓操作系統進入待機模式?又如何把它激活? 
通過註冊表就可以設置,前提是你的驅動和硬件都支持。註冊表項參見標題爲“GWES Suspend Time-outs”的幫助文檔。 
[HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power] 
    "BattPowerOff"=dword:300 
    "ExtPowerOff"=dword:0 
    "WakeupPowerOff"=dword:60 
    "ScreenPowerOff"=dword:0 
 
 現有一個GPRS模塊,如何通過GPRS連接到Internet? 
1、先在內核中加入WAN下面的幾個組件,如RAS/PPP、TAPI。WINCE採用unimodem驅動,所以不必擔心沒有Modem驅動的支持。 
2、WINCE啓動後新建一個撥號連接,比如名稱叫“gprs1”,輸入用戶名、密碼、電話號碼。電話號碼不同,所採用的模式不一樣,例如“*99#”是GPRS模式,“17201”是普通的數據模式,速度差很多,價錢也差很多。 
3、開始連接,連接過程會在對話框中顯示,直到顯示“連接成功”。 
4、打開瀏覽器或者自己開發的通訊軟件測試網絡連接情況。 
5、關閉連接。 
6、保存[HKEY_CURRENT_USER/Comm/RasBook/gprs1]下的所有數據,添加到project.reg中,重新編譯後內核中就有了一個撥號連接“gprs1”。 
7、調用RAS函數可以修改撥號連接“gprs1”的參數,如用戶名、密碼、電話號碼,但是不能修改硬件設置,如波特率、串口、數據位、停止位等。RAS函數還能夠撥號、掛斷。爲了修改波特率可以多保存幾個撥號連接,也可以直接調用TAPI開發撥號軟件,另外WINCE自帶的撥號連接是有源碼的,位置在/PUBLIC/COMMON/OAK/DRIVERS/NETSAMP/CONNMC。 
 
 採用基於HIVE的註冊表如何刪除用戶保存在註冊表中的數據,恢復到出廠時的註冊表? 
用戶修改的數據保存在user.hv文件中,直接刪除一定失敗,所以不能通過刪除文件實現恢復出廠設置。微軟考慮到了這個問題,在WINCE啓動過程中filesys.exe加載註冊表時會調用OEMIoControl函數並傳遞一個IOCTL,這個IOCTL在pkfuncs.h中定義如下: 
#define  IOCTL_HAL_GET_HIVE_CLEAN_FLAG  CTL_CODE(FILE_DEVICE_HAL, 49, METHOD_BUFFERED, FILE_ANY_ACCESS) 
filesys.exe會分別傳遞參數HIVECLEANFLAG_SYSTEM和HIVECLEANFLAG_USERS,如果返回值爲TRUE那麼filesys.exe清除原來的註冊表文件,如果返回值爲FALSE那麼filesys.exe保留原來的註冊表文件。默認WINCE並沒有實現這個IOCTL,所以OEM要刪除註冊表文件就必須先編寫這個IOCTL代碼。代碼的例子可參考標題爲“IOCTL_HAL_GET_HIVE_CLEAN_FLAG”的幫助文檔。另外必須在ioctl.h和ioctl.c兩個文件中編寫該代碼。在ioctl.c文件中找到const OAL_IOCTL_HANDLER g_oalIoCtlTable[],添加IOCTL和對應的處理函數。要進一步瞭解這個全局數組,參見標題爲“IOCTL Library”的幫助文檔。 
 
 如何在不刪除必要組件的前提下減小內核文件長度? 
要減小內核文件長度首先要在使用PB的定製內核嚮導中選擇自定義,也就是說對於每個組件都由自己來選擇,而不是選擇PB的標準配置。但減小內核文件長度最有效最直接的辦法是縮小字體,尤其對於東亞字體,採用字體壓縮技術並且選擇合理的字庫文件將明顯縮小文件長度。 
1、在定製內核時選擇AGFA AC3 Font Compression組件。SYSGEN變量爲SYSGEN_AGFA_FONT。 
2、參考標題爲“East Asian Font Versions”的幫助文檔,從中選擇你需要的字庫文件加到內核中,從文檔可以看出加AC3壓縮比不加壓縮在文件長度方面差距很大。 
 
 如何得到WAV文件播放的總時間? 
1、直接讀取wav文件頭信息,從文件起始地址偏移28個字節長度爲4個字節保存的是每秒鐘播放的字節數,從文件起始地址偏移40個字節長度爲4個字節保存的是聲音數據的總的字節數,相除就是播放時間。 
2、調用IGraphBuilder::RenderFile打開一個wav文件,然後通過IGraphBuilder得到IMediaSeeking指針,再調用IMediaSeeking::GetDuration得到總的時間(結果要除以10000000),IMediaSeeking::GetCurrentPosition得到當前播放時間。 
 
 如何在Dialog-Based程序中加入menubar? 
先調用CommandBar_Create再調用CommandBar_InsertMenubar。 
 
 請問MultiByteToWideChar與_T、L、TEXT的區別? 
MultiByteToWideChar函數轉換的對象可以是常量也可以是變量。其它只能轉換常量。_T和TEXT會根據當前系統是否定義_UNICODE宏來決定是否轉換,而L就是轉換成寬字符,當然也包括其他類型常量的轉換。 
 
 在用UBS線纜通過ActiveSync同步有效的情況下,如何插上USB線纜後WINCE自動與PC同步? 
1、新建一個撥號連接,假設名稱爲“usb1”,選擇連接類型爲“直接連接”,並在連接設備裏選擇通過USB線纜連接。 
2、將註冊表[HKEY_CURRENT_USER/Comm/RasBook/usb1]下的數據添加到project.reg或者platform.reg中。 
3、在[HKEY_CURRENT_USER/ControlPanel/Comm]下添加如下: 
"AutoCnct"=dword:1  ///直接連接 
"Cnct"="usb1"       ///連接名稱 
4、重新編譯內核。爲了節省編譯時間也可以在內核工程下搜索*.reg文件,將2、3步驟中的註冊表數據添加其中,然後直接make image。 
 
 如何通過進程句柄來獲得該進程的主窗口句柄? 
好像沒有API能夠通過進程句柄直接獲得主窗口的句柄,因爲並非每個應用程序都帶UI。但是可以反過來,先枚舉當前系統所有主窗口,然後根據每個窗口的句柄調用GetWindowThreadProcessId函數得到進程的ID,再調用OpenProcess得到進程句柄,與現有的進程句柄比較。 
 
 我做的顯示驅動DLL已經編譯成功了,但是在加載顯示驅動的過程中彈出話框,提示如下: 
unhandled exception  in  gwes.exe  (0xc0000005 access violation) 
提示的錯誤——地址訪問非法,表明你的驅動程序代碼並沒有在讀寫數據前添加SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數讓線程能夠訪問任何進程的地址空間。你可以調用 IsBadReadPtr和IsBadWritePtr函數檢測地址是否能夠合法訪問。編寫和gwes有關的驅動程序應該首先調用SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數,這是一個好習慣。 
 
 請問在嵌入式系統中如何設置GPRS拔號用的APN? 
對一個撥號連接比如“我的連接”單擊鼠標右鍵,在彈出的菜單中選擇“屬性”,然後單擊“配置”—“撥號選項”,在“附加設置”中添加AT命令如“+cgdcont=1,"ip","cmnet"”。“cmnet”位置即爲APN。 
 
 WINCE的IP Phone功能如何? 
WINCE的voip需要c-s-c結構,既需要服務器的中轉,而skype採用第三代p2p技術就不需要中轉,但是在gprs下也做不到語音流暢。skype有pocket pc版本,但是無線方面需要wlan或者cdma。 
 
 三星ARM平臺如何定義自己的中斷ID? 
以S3C2410爲例,在oalintr.h文件中定義中斷ID,也稱SYSINTR,例如 #define SYSINTR_MYINT  (SYSINTR_FIRMWARE+20),最大值不能超過SYSINTR_FIRMWARE+23。然後在armint.c文件中找到OEMInterruptHandler函數,用if (IntPendVal == INTSRC_XXX) 判斷當前發生的中斷源號,然後返回SYSINTR_MYINT。內核分別調用OEMInterruptDisable(禁止當前中斷)、OEMInterruptDone(中斷處理結束)、OEMInterruptEnable(當前中斷有效)三個函數,參數都爲中斷ID,在這三個函數中用 case SYSINTR_MYINT判斷當前要處理的中斷。 
 
 如何開發軟件從PC端複製文件到基於WINCE的設備? 
調用RAPI(Remote Application Programming Interface)函數,此函數集由桌面計算機調用,由基於WINCE的設備執行。一旦連接上就可以在桌面計算機端調用RAPI。通過註冊表還可以限制RAPI能夠訪問目錄的範圍。具體參考RAPI和RDP(遠程桌面協議)。 
 
 請問如何對NandFlash分區、格式化? 
你看看WINCE420/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp,在Eboot中先要調用BP_LowLevelFormat( 
DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)再flash的一個區域建立空的MBR,然後連續兩次調用BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)函數來建立BINFS和FAT分區。建好後,將nk.bin燒入binfs分區中。 
 
  要做個彈出對話框具有 always on top 屬性,如何實現? 
調用SetWindowPos(.. , HWND_TOPMOST, ...., SWP_NOACTIVATE)。 
 
 s3c2410+WINCE下網絡PING一會就斷,如何解決? 
原因在於中斷處理程序把已經產生的中斷標誌清除掉了,這樣就丟失一次中斷。因爲原驅動裏配置中斷爲上升沿觸發,一次中斷丟失就導致不會再產生中斷信號跳變,因爲只有在中斷服務中讀取了cs8900的 Interrupt status queue寄存器後,纔會產生下一次中斷!解決辦法: 
1、在cfw.c文件中全局定義BOOL Inited = FALSE 
2、修改OEMInterruptEnable()中case SYSINTR_ETHER: 下面的語句爲: 
if(Inited == FALSE)  
{  
s2410IOP->rEINTPEND = 0x200;  
s2410INT->rSRCPND = BIT_EINT8_23;  
if (s2410INT->rINTPND & BIT_EINT8_23)  
s2410INT->rINTPND = BIT_EINT8_23;  
Inited = TRUE;  
}  
s2410IOP->rEINTMASK &= ~0x200;  
s2410INT->rINTMSK &= ~BIT_EINT8_23;  
break;  
注:本解決辦法轉載於http://stoned.blogchina.com/stoned/3083045.html,非我本人研究成果。 
 
 已經搜索到文件,如何用CListBox以圖標形式顯示出來? 
CListCtrl        ListCtrl; 
CImageList      ImageList; 
ImageList.Create(IDB_BITMAP, 48, 2, RGB(0,0,0)); 
ListCtrl.SetImageList(&ImageList, LVSIL_NORMAL); 
ListCtrl.InsertItem(iListIndex, strItem, 1);  
 
 如何改變控制面板中電源屬性對話框的尺寸?  
1、需要修改對話框的尺寸是因爲對話框是以資源方式加載的,不會根據當前系統顯示分辨率而自我調節尺寸。 
2、安裝WINCE後有一些組件(feature)的資源文件*.res就已經有了,如果你不改變,那麼build內核的時候PB只是把這些.res複製到工程目錄下,然後與*.obj合併成EXE、DLL、CPL。所以修改了.rc文件裏面的對話框尺寸後要重新編譯.rc文件爲.res文件,然後再覆蓋原來WINCE自帶的.res文件。 
3、改變對話框尺寸有兩種辦法:一種方法是更改系統字體字號,系統字體的字號變化會影響對話框的尺寸,但是缺點是所有系統字體有關的UI都會改變。另一種是在.rc文件中調整對話框尺寸,然後編譯成.res文件,再將.res複製到對應的語言目錄裏,比如目錄名爲0804(中文),再執行Rebuild命令重新編譯內核,或者執行sysgen+build。在研究中我發現.res文件雖然能夠直接用EVC打開、修改、保存,但是和其它Obj鏈接成EXE、DLL、CPL後並不能運行,所以還是建議讀者用CE自帶的rc工具編譯最好。讀者可在PB的命令行中鍵入“rc /?”瞭解rc.exe工具的用途和參數。 
 
 使用EVC build之後連接模擬器的時候,提示download file等了一會又出現download failed? 
一般這樣的問題從下面幾個步驟解決: 
1、如果之前能啓動模擬器而現在不能,那麼先clean然後重啓計算機再build。 
2、如果開發的主機爲WINXP+SP2,可能存在與EVC模擬器不兼容的情況,檢查C:/boot.ini,將/noexecute=optin改爲/execute=optin。 
3、檢查你的模擬器是否能運行,假設你正用的SDK名稱爲MYSDK,單擊菜單tools—configure platform manager,選擇MYSDK—MYSDK emulator,再單擊properties—test,看看模擬器是否能夠啓動,如果能啓動那問題就不大。 
4、單擊菜單build—update remote output files,看看模擬器是否能夠啓動。 
5、如果上述辦法均不行,關閉EVC然後重新建立一個新的工程,編譯,看看模擬器是否能夠啓動,如果能啓動說明原來工程出了問題,最好恢復原工程的備份。 
 
 如何設置能夠自動撥號、禁止自動撥號? 
在[HKEY_LOCAL_MACHINE/Comm/Autodial]下是自動撥號的註冊表設置。 
Enabled=DWORD:1          ///是否能夠自動撥號 
FailRetryWaitMS=DWORD    ///如果失敗再次撥號的等待時間 
RasEntryName1= REG_SZ     ///自動撥號採用的撥號連接名稱 
更多細節請參考標題爲“Auto Dial Registry Settings”的幫助文檔。   

發佈了10 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章