在 Windows Mobile 中使用 Windows API,舉三個常用的例子 : 登錄表操作、音量操作、播放音樂
1. 簡介
Windows API 是屬於 Windows 作業系統其中一部分的動態連結程式庫 ( DLL )。當您無法自行寫入對等程序時,您就可使用它們來執行工作。
在 Windows Mobile 作業系統中,Coredll.dll 是相當重要且經常使用的 Windows API,以下舉3個範例,分別是登錄表操作、音量操作、播放音樂。
*註 : 想了解 Windows API 可以做什麼事情的人,可上 MSDN查詢,或參考此網站 PINVOKE.NET。
2. 範例
2.1 登錄表操作
登錄表是一個龐雜的資料庫,它紀錄了Windows 所必需要的硬體和軟體訊息,其4個主要的根目錄與數個附加目錄如下所示 :
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_PERFORMANCE_DATA
HKEY_PERFORMANCE_TEXT
HKEY_PERFORMANCE_NLSTEXT
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA
在 Windows API 中,對於登錄表操作的部份就在coredll.dll,可參考 MSDN 上的 Registry Functions 列表,幾個常用到的如下所示 :
RegCreateKeyEx : 註冊新的鍵值
RegOpenKeyEx : 開啟鍵值
RegCloseKey : 關閉鍵值
RegSetValueEx : 設定鍵值
RegQueryValueEx : 傳回鍵值的類型和值
以下範例為按下 Set 按鈕後,新增與設定新的登錄檔,以及按下 Get 按鈕後,顯示剛剛新增的登錄檔。
程式碼
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace SmartDeviceProject6
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show( CERegister.RegGetStringValue(RegRoot.HKEY_CURRENT_USER, textBox1.Text, "StringValue") );
}
private void button2_Click(object sender, EventArgs e)
{
CERegister.RegSetStringValue(RegRoot.HKEY_CURRENT_USER, textBox1.Text, "StringValue", textBox2.Text);
}
}
public class CERegister
{
private const uint HKEY_CLASSES_ROOT = 0x8000000;
private const uint HKEY_CURRENT_USER = 0x80000001;
private const uint HKEY_LOCAL_MACHINE = 0x80000002;
private const uint HKEY_USERS = 0x80000003;
private const uint HKEY_PERFORMANCE_DATA = 0x80000004;
private const uint HKEY_PERFORMANCE_TEXT = 0x80000050;
private const uint HKEY_PERFORMANCE_NLSTEXT = 0x80000060;
private const uint HKEY_CURRENT_CONFIG = 0x80000005;
private const uint HKEY_DYN_DATA = 0x80000006;
private const int REG_NONE = 0;
private const int REG_SZ = 1;
private const int REG_EXPAND_SZ = 2;
private const int REG_BINARY = 3;
private const int REG_DWORD_LITTLE_ENDIAN = 4;
private const int REG_DWORD = 4;
private const int REG_DWORD_BIG_ENDIAN = 5;
private const int REG_LINK = 6;
private const int REG_MULTI_SZ = 7;
private const int ERROR_MORE_DATA = 234;
[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int RegCloseKey(uint key);
[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int RegCreateKeyEx(
uint hKey,
string lpSubKey,
uint Reserved,
string lpClass,
uint dwOptions,
uint samDesired,
uint lpSecurityAttributes,
ref uint phkResult,
ref uint lpdwDisposition
);
[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int RegOpenKeyEx(
uint hKey,
string lpSubKey,
uint ulOptions,
uint samDesired,
ref uint phkResult
);
[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int RegSetValueEx(
uint hKey,
string lpValueName,
int Reserved,
int dwType,
byte[] lpData,
int cbData);
[System.Runtime.InteropServices.DllImport("coredll.dll")]
private unsafe static extern int RegQueryValueEx(
uint hKey,
string lpValueName,
uint lpReserved,
out uint lpType,
byte* lpData,
ref uint lpcbData
);
private static uint CreateKey(RegRoot root, string Path)
{
uint nKey = 0;
uint nDisposition = 0;
int rez = RegCreateKeyEx((uint)root, Path, 0, String.Empty, 0, 0, 0, ref nKey, ref nDisposition);
if (rez != 0) throw new Exception("Can't create key");
return nKey;
}
private static uint OpenKey(RegRoot root, string Path)
{
uint nKey = 0;
int rez = RegOpenKeyEx((uint)root, Path, 0, 0, ref nKey);
if (rez != 0) throw new Exception("Can't open key");
return nKey;
}
private static uint SetStringValue(uint Key, string Name, string Value)
{
int rez = RegSetValueEx(Key, Name, 0, (int)RegType.REG_SZ, System.Text.ASCIIEncoding.ASCII.GetBytes(Value), Value.Length);
if (rez != 0) throw new Exception("Can't set value");
return Key;
}
private static string GetStringValue(uint Key, string Name)
{
uint buflen = 0;
uint type = 0;
char[] str = null;
unsafe
{
int r = RegQueryValueEx(Key, Name, 0, out type, null, ref buflen);
if (type != (uint)RegType.REG_SZ) throw new Exception("The key is not of string value");
byte[] rez_buf = new byte[buflen];
fixed (byte* charpointer = &rez_buf[0])
{
int rez = RegQueryValueEx(Key, Name, 0, out type, charpointer, ref buflen);
if (rez != 0) throw new Exception("Can't get value");
}
str = new char[buflen];
for (int i = 0; i < buflen; i++)
str[i] = (char)rez_buf[i];
}
return new string(str);
}
public static string RegGetStringValue(RegRoot root, string Path, string Attr)
{
uint key = OpenKey(root, Path);
string rez = GetStringValue(key, Attr);
RegCloseKey(key);
return rez;
}
public static uint RegSetStringValue(RegRoot root, string Path, string Attr, string Value)
{
uint key = CreateKey(root, Path);
uint rez = SetStringValue(key, Attr, Value);
RegCloseKey(key);
return rez;
}
static CERegister()
{
//
// TODO: Add constructor logic here
//
}
}
public enum RegRoot : uint
{
HKEY_CLASSES_ROOT = 0x8000000,
HKEY_CURRENT_USER = 0x80000001,
HKEY_LOCAL_MACHINE = 0x80000002,
HKEY_USERS = 0x80000003
};
public enum RegType
{
REG_DWORD = 4,
REG_SZ = 1
};
}
執行結果
(1) 按下 Set 按鈕後,新增與設定新的登錄檔
(2) 按下 Get 按鈕後,顯示剛剛新增的登錄檔
* 註 : 對這方面有興趣的可以參考以下連結
Using PocketPC Registry from C# Applications
2.2 音量操作
在 Windows API 中,Coredll.dll 內有許多關於音量操作的函式,最常用的是以下兩個,取得與設定音量。
waveOutGetVolume : 取得波形輸出音源音量設定
waveOutSetVolume : 設定波形輸出音源音量設定
宣告方式
// 取得波形輸出音源音量設定
[DllImport("coredll.dll")]
public static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume);
// 設定波形輸出音源音量設定
[DllImport("coredll.dll")]
public static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
以下範例功能為程式初始化時,取得目前音量顯示於 Track Bar 控制項上,而後使用者可調整 Scroll Bar 控制音量。
程式碼
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace SmartDeviceProject6
{
public partial class Form2 : Form
{
// 取得波形輸出音源音量設定
[DllImport("coredll.dll")]
public static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume);
// 設定波形輸出音源音量設定
[DllImport("coredll.dll")]
public static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
public Form2()
{
InitializeComponent();
// 取得音量
// 設定變數CurrVol用以取得目前音量
uint CurrVol = 0;
// 透過waveOutGetVolume取得目前音量給變數CurrVol
waveOutGetVolume(IntPtr.Zero, out CurrVol);
// 計算音量大小
ushort CalcVol = (ushort)(CurrVol & 0x0000ffff);
// 將音量大小分為10階,並指定給trackWaved控制項
trackWave.Value = CalcVol / (ushort.MaxValue / 10);
}
// 當控制項trackWave的值改變時,設定音量
private void trackWave_ValueChanged(object sender, EventArgs e)
{
// 由trackWave上的值計算要設定的音量大小
int NewVolume = ((ushort.MaxValue / 10) * trackWave.Value);
// 設定相同的數值於左聲道與右聲道
uint NewVolumeAllChannels = (((uint)NewVolume & 0x0000ffff) | ((uint)NewVolume << 16));
// 設定音量
waveOutSetVolume(IntPtr.Zero, NewVolumeAllChannels);
}
}
}
執行結果
2.3 播放音樂檔
2.3.1 播放 wav 音效檔
透過 Windows API 中,Coredll.dll 內的 PlaySound 可以播放一些音效檔。
宣告方式
[DllImport("CoreDll.DLL", EntryPoint="PlaySound", SetLastError=true)]
private extern static int PlaySound(string szSound, IntPtr hMod, int flags);
將以下播放音效的程式碼,整合到 2.2 音量調整 程式中,可以撥音效與調整音量大小。
程式碼
[DllImport("CoreDll.DLL", EntryPoint="PlaySound", SetLastError=true)]
private extern static int PlaySound(string szSound, IntPtr hMod, int flags);
public const int SND_FILENAME = 0x00020000; // file name
public const int SND_SYNC = 0x0000; // play synchronously (default)
private void button1_Click(object sender, EventArgs e)
{
PlaySound("\\windows\\Alarm2.wav", IntPtr.Zero, 0);
}
執行結果
參考
2.3.2 播放音樂檔
想要在 Windows Mobile 播放 mp3 的話,可以使用 Windows Media Player Lib (WMPLib),參考 bauann 前輩的文章 在裝置(mobile)播放mp3檔案,
以下簡單介紹如何使用
先將 WMPLib 加入參考,檔名為 C:\WINDOWS\system32\wmp.dll
以下程式碼功能為將 \Storage Card\Music 的檔案顯示於 ListBox 中,使用者可撥放與停止播放 mp3 音樂檔。
程式碼
WMPLib.WindowsMediaPlayer Player;
private void Form4_Load(object sender, EventArgs e)
{
foreach (string s in System.IO.Directory.GetFiles(@"\Storage Card\Music") )
{
this.listBox1.Items.Add(s);
}
Player = new WMPLib.WindowsMediaPlayer();
Player.settings.volume = 10;
}
private void btnStart_Click(object sender, EventArgs e)
{
// Play music file
if (this.listBox1.SelectedIndex >= 0)
{
Player.URL = this.listBox1.SelectedItem.ToString();
Player.controls.play();
}
}
private void btnStop_Click(object sender, EventArgs e)
{
// Stop music file
Player.controls.stop();
}
執行結果
3. 結語
在 Windows Mobile 中,Windows API 的運用與登錄檔的操作是相當重要的,本篇文章希望能給初學者入門指引。
4. 附錄 : 檔案下載
5. 附錄 : MSDN .NET Compact Framework 中的應用程式開發