吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4568|回复: 7
收起左侧

[其他转载] 【WP8.1开发】用手机来控制电脑的多媒体播放

  [复制链接]
王旭东 发表于 2015-1-7 21:34
本帖最后由 王旭东 于 2015-1-7 21:35 编辑


为了用电脑看电影时方便控制,我就突发其想,做一个手机app来通过无线网络远程调节电脑上的音量。后来进行尝试成功后,我就想,光是调音量似乎单调了些,就把播放/暂停,上一首,下一首,等多媒体控制功能也加上,这样好玩一点。
下面向大家简单介绍一下原理,整个解决方案的源代码我会共享给大家,以作参考。

先说服务器,因为控制命令比较简单,我直接用一个WPF应用程序来完成,这样方便运行,用socket来通信比较麻烦,我就用WCF来做服务,使用WebServiceHoset,让WP手机客户端用HTTP-POST的方式来调用。
这个相信大家都会,还有一个核心,就是如何控制系统的多媒体功能? 其实大家应该发现在你的笔记本键盘上,有一排功能按钮,可以通过按这些键来调整音量,控制播放、上一首歌曲等,还有各种功能开关,比如打开/关闭无线功能等。
也就是说,只要代码能够模拟发出这些按键就可以实现控制了,这就要用到Win32 API中的SendInput函数。在最初尝试时,我将SendInput函数导进托管代码中,但调用没有反应,不知道是不是我Import不对。
后来,我干脆用C++来写一个dll,把各个控制操作都用独立的导出函数来包装,再把自己写的dll中的导出函数在托管项目中DllImport。
自己编写的dll的头文件如下:

复制代码
#pragma once
#include "stdafx.h"
/* 增大音量 */
extern "C" __declspec(dllexport) void volume_up();
/* 减小音量 */
extern "C" __declspec(dllexport) void volume_down();
/* 静音/恢复 */
extern "C" __declspec(dllexport) void volume_mute();
/* 下一首 */
extern "C" __declspec(dllexport) void media_next_track();
/* 上一首 */
extern "C" __declspec(dllexport) void media_prev_track();
/* 播放/暂停 */
extern "C" __declspec(dllexport) void media_play_pause();
/* 停止 */
extern "C" __declspec(dllexport) void media_stop();
void send_input_core(WORD vkey);
复制代码
__declspec(dllexport)注明的函数为导出函数,即可以在其他代码中使用,而最后的send_input_core函数只供dll内部使用,就不再导出了。
注意要加上extern "C",让函数以C语言的规范进行导出,由于C语言不支持函数重载,在编译时编译器不会改变函数的名字,所以加上extern "C"让托管代码在Dll Import时可以直接使用函数的原名,这样就不需要编写复杂的模块定义文件来重命名符号了,这种方法写dll是最方便的。
下面在cpp文件中实现send_input_core函数:

复制代码
void send_input_core(WORD vkey) {
    INPUT input;
    input.type = INPUT_KEYBOARD;
    input.ki.dwFlags = NULL;
    input.ki.wVk = vkey;
    SendInput(1, &input, sizeof(INPUT));
}
复制代码
用vkey参数来接收要模拟的按键,这样就不用重复写SendInput的调用代码了,其余的函数可以直接调用该函数,然后传递按键值就可以了。

复制代码
void volume_up() {
    send_input_core(VK_VOLUME_UP);
}
void volume_down()
{
    send_input_core(VK_VOLUME_DOWN);
}
void volume_mute() {
    send_input_core(VK_VOLUME_MUTE);
}
void media_next_track()
{
    send_input_core(VK_MEDIA_NEXT_TRACK);
}
void media_prev_track() {
    send_input_core(VK_MEDIA_PREV_TRACK);
}
void media_play_pause() {
    send_input_core(VK_MEDIA_PLAY_PAUSE);
}
void media_stop()
{
    send_input_core(VK_MEDIA_STOP);
}
复制代码

完成dll后,就导入到C#托管代码中:

复制代码
namespace DllAPIs
{
    using System;
    using System.Runtime.InteropServices;
    public sealed class MediaControlAPIs
    {
        // dll文件的名字
        const string DLL_NAME = "mediactrllib.dll";
        #region 从dll导入的API
        [DllImport(DLL_NAME)]
        extern static void volume_up();
        [DllImport(DLL_NAME)]
        extern static void volume_down();
        [DllImport(DLL_NAME)]
        extern static void volume_mute();
        [DllImport(DLL_NAME)]
        extern static void media_next_track();
        [DllImport(DLL_NAME)]
        extern static void media_prev_track();
        [DllImport(DLL_NAME)]
        extern static void media_play_pause();
        [DllImport(DLL_NAME)]
        extern static void media_stop();
        #endregion
        #region 公共方法
        /// <summary>
        /// 增大音量
        /// </summary>
        public static void VolumeUp()
        {
            volume_up();
        }
        /// <summary>
        /// 减小音量
        /// </summary>
        public static void VolumeDown()
        {
            volume_down();
        }
        /// <summary>
        /// 静音/恢复
        /// </summary>
        public static void VolumeMute()
        {
            volume_mute();
        }
        /// <summary>
        /// 下一曲目
        /// </summary>
        public static void MediaNextTrack()
        {
            media_next_track();
        }
        /// <summary>
        /// 上一曲目
        /// </summary>
        public static void MediaPrevTrack()
        {
            media_prev_track();
        }
        /// <summary>
        /// 播放/暂停
        /// </summary>
        public static void MediaPlayPause()
        {
            media_play_pause();
        }
        /// <summary>
        /// 停止播放
        /// </summary>
        public static void MediaStop()
        {
            media_stop();
        }
        #endregion
    }
}
复制代码
我想,这样导入要比直接导入Win32 API要简便得多。
接着,完成WCF服务。

复制代码
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "invoke?action={act}")]
        void Invoke(string act);
    }

    public class WcfService : IService
    {
        public void Invoke(string act)
        {
            switch (act)
            {
                case "vu": //增大音量
                    DllAPIs.MediaControlAPIs.VolumeUp();
                    break;
                case "vd": //减小音量
                    DllAPIs.MediaControlAPIs.VolumeDown();
                    break;
                case "vm": //静音/恢复
                    DllAPIs.MediaControlAPIs.VolumeMute();
                    break;
                case "mn": //下一首
                    DllAPIs.MediaControlAPIs.MediaNextTrack();
                    break;
                case "mp": //上一首
                    DllAPIs.MediaControlAPIs.MediaPrevTrack();
                    break;
                case "mpp": //播放/暂停
                    DllAPIs.MediaControlAPIs.MediaPlayPause();
                    break;
                case "ms": //停止
                    DllAPIs.MediaControlAPIs.MediaStop();
                    break;
            }
        }
    }
复制代码

其他代码就不介绍了,大家看源码吧。
最后是实现手机客户端,其实就是用HTTP-POST向刚才的WCF服务发数据即可。

复制代码
        private async Task PostActionAsync(string action)
        {
            string postUri = string.Format("http://{0}:{1}/invoke?action={2}", HostName, Port, action);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUri);
            request.Method = "POST";
            var rep = await request.GetResponseAsync();
        }
复制代码

最后看看结果:


源代码下载:http://files.cnblogs.com/tcjiaan/RemoteMediaControlSlsn.zip

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

巴斯光年丶 发表于 2015-1-7 21:45
..你应该直接做好..在发出来我更喜欢~
泪河之缘 发表于 2015-1-7 21:39
SherlockHolmes 发表于 2015-1-8 09:03 来自手机
GA゛木子 发表于 2015-1-8 16:14 来自手机
感谢楼主分享
manbajie 发表于 2015-1-8 20:23
好象很不错哦
chanzheweixian 发表于 2015-2-4 20:47
感谢楼主分享
风逝998 发表于 2015-2-5 23:15
谢谢楼主分享,
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 08:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表