[Windows Mobile]Windows API 範例 : 登錄表操作、音量操作、播放音樂

  • 21126
  • 0
  • 2013-04-15

在 Windows Mobile 中使用 Windows API,舉三個常用的例子 : 登錄表操作、音量操作、播放音樂

 

1. 簡介

Windows API 是屬於 Windows 作業系統其中一部分的動態連結程式庫 ( DLL )。當您無法自行寫入對等程序時,您就可使用它們來執行工作。

在 Windows Mobile 作業系統中,Coredll.dll 是相當重要且經常使用的 Windows API,以下舉3個範例,分別是登錄表操作、音量操作、播放音樂。

 

*註 : 想了解 Windows API 可以做什麼事情的人,可上 MSDN查詢,或參考此網站 PINVOKE.NET

image

 

 

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 按鈕後,新增與設定新的登錄檔

image

(2) 按下 Get 按鈕後,顯示剛剛新增的登錄檔

image

 

* 註 : 對這方面有興趣的可以參考以下連結

Microsoft Windows 登錄說明

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);
        }
    }
}

 

執行結果

image

 

 

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);
        }

 

執行結果

image

參考

HOW TO:播放音效

 

2.3.2 播放音樂檔

想要在 Windows Mobile 播放 mp3 的話,可以使用 Windows Media Player Lib (WMPLib),參考 bauann 前輩的文章 在裝置(mobile)播放mp3檔案

以下簡單介紹如何使用

 

先將 WMPLib 加入參考,檔名為 C:\WINDOWS\system32\wmp.dll

image image

以下程式碼功能為將 \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();
        }

 

執行結果

image

 

3. 結語

在 Windows Mobile 中,Windows API 的運用與登錄檔的操作是相當重要的,本篇文章希望能給初學者入門指引。

 

4. 附錄 : 檔案下載

WinAPIdemo.rar

 

5. 附錄 : MSDN .NET Compact Framework 中的應用程式開發

image