⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 9937.txt

📁 关于编程技术技巧的文章
💻 TXT
📖 第 1 页 / 共 4 页
字号:
似,可以播放100K 以上的文件。 

低级Wave音频设备。用这些设备可以运行完全控制Wave数据的应用文
件。
---- 二、 WAV文件播放控制 

---- 因为同样使用MCI,与上一章相同,只列出不同的部分。 

---- 1. 打开设备 

---- 将MIDI的MCI_DEVTYPE_SEQUENCER 改为"waveaudio" 

---- 2. 录音 

MCI_RECORD_PARMS RecordParms;
mciSendCommand (m_wDeviceID, MCI_RECORD, 
NULL, (DWORD)(LPVOID) 
&RecordParms);
---- 3. 保存录音 

MCI_SAVE_PARMS SaveParms;
SaveParms.lpfilename = (LPCSTR) Filename;
mciSendCommand (m_wDeviceID, MCI_SAVE,
 MCI_SAVE_FILE | MCI_WAIT, 
(DWORD)(LPVOID) &SaveParms);
第三部分 CD的播放 
---- CD的独特优势在于,它由作曲家设计,并由音乐厂家生产。不
同的计算机播放MIDI 文件时,声音效果也不一样,但是CD的声音效
果总是相同的。高品质的音频对计算机用户产生的效果会使你感到吃
惊。我们依然采用MCI播放CD,大部分的播放控制与前两部分相同,
只列出不同的部分 
---- 1. 开光驱门 

mciSendCommand (m_wDeviceID, MCI_SET,
 MCI_SET_DOOR_OPEN, NULL);
---- 2. 关光驱门 

mciSendCommand (m_wDeviceID, MCI_SET, 
MCI_SET_DOOR_CLOSED, NULL);
---- 3. 打开设备 

将MIDI的MCI_DEVTYPE_SEQUENCER 改为MCI_DEVTYPE_CD_AUDIO
---- 4. 播放 

---- 指定播放起点必须经过MCI_MAKE_TMSF(Track,Minute,Second,
Frame)转化 

---- 5. 查询当前信息 

MCI_STATUS_CURRENT_TRACK	  得到当前曲目
MCI_STATUS_LENGTH  得到CD或指定曲目长度
MCI_STATUS_MODE  得到驱动器的当前状态
MCI_STATUS_NUMBER_OF_TRACKS  得到CD曲目的数目
MCI_STATUS_POSITION	  得到当前格式下的位置
MCI_STATUS_READY	  检查设备是否就绪
MCI_STATUS_TIME_FORMAT  得到当前时间格式
MCI_STATUS_MEDIA_PRESENT  检查以确认CD是否在驱动器内
MCI_CDA_STATUS_TYPE_TRACK 检查已确认某曲目是否为音频曲目
---- 注意: 

使用MCI_STATUS_LENGTH参数查询CD 及曲目长度,返回值通过调用
MCI_MSF_MINUTE(),MCI_MSF_SECOND()转换为分、秒。 

MCI_STATUS_POSITION参数返回值调用MCI_TMSF_TRACK(), MCI_TMSF_MINUTE(), 
MCI_TMSF_SECOND(),MCI_TMSF_FRAME才能得到当前的位置的道、分、秒、帧。
---- 6. 跳跃 

---- 跳转的目标必须经过MCI_MAKE_TMSF(Track,Minute,Second,Frame)
转化最好将上述三种格式分开建类,或做成动态连接库。在
Project-- >Setting-- >Link-- >Object/library modules中加入winmm.lib,
源程序中包含< mmsystem.h >。 

---- MCI调用简单,功能强大,可以满足日常多媒体编程的基本需要。但
是,MCI一次只能播放一个文件,使用DirectSound技术可以实现八个以上
WAV文件的同时播放。 

****************************************************************

                     WINDOWS9x的后台进程 

             上海仙霞路山特公司软件中心  黄飞 

---- 1. 后 台 进 程 

---- 在WINDOWS NT中有一个功能强大的SERVICE管理器,它管理着一部分实现重要功能的后台进程, 例如FTP.HTTP.RAS. 网络Message等等,这些后台进程被称之为Service, 他们可以在系统启动时就加载,可以运行在较高的优先级,可以说是非常靠近系统核心的设备驱动程序中的一种.在WINDOWS95下,Microsoft没有提供这样一个高度集中化了的管,不过我们通过VC自带的PVIEW可以看到,在桌面背后同样有秘密的后台进程存在, 例如:SysTray,电源管理等.其实, 这些就是WINDOWS95管理的后台进程,WINDOWS95没有提供SERVICE管理器,取而代之是一个简单的登记接口,可以类似的称之为WINDOWS95下的Service(不过严格的讲,WINDOWS95下是没有Service的),同样的,通过这个登记接口,我们可以使自己的程序随系统启动而最先运行,随系统关闭而最后停止,和操作系统结合在一起,实现许多独特的功能.我在实际工作中,仔细的分析了这个Windows95的接口, 并且测试后发现,在WINDOWS97和最新的WINDOWS98中它一样有效.并通过这个机制,成功的实现了WINDOWS95.98下的无人职守监控.下面是关于这个接口的分析结果和一些准备知识.

---- 2. 进 程 数 据 库(PDB) 介 绍 

---- 在Windows 的 核 心 数 据 结 构 中, 有 一 个 重 要 的 进 
程 管 理 结 构 叫 进 程 数 据 库, 它 位 于Kernel32 的 公 用 
内 存 堆 中, 可 以 通 过GetCurrentProcessID(...)  得 到 指 
向 该 结 构 的 指 针, 以 下 是 部 分PDB 的 组 成, 与 本 文 
直 接 相 关 的 是PDB 偏 移21h 处 的Service 标 志 字 节, 通 
过 后 面 的 伪 码 分 析, 我 们 可 以 清 楚 的 看 到 所 谓 登 
记 为Windows95 或Windows98 下 的Service 进 程, 只 不 过 是 
把 它 相 应 的PDB 中 该 标 志 字 节 置 为1 而 已. 

偏移量长度      说明
============================================
+00h  DWORD   Type // Kernel32对象的类型
+04h  DWORD   CReference //参考计数
+08h  DWORD   Un1 //未知
+0ch  DWORD   pSomeEvent //指向K32OBJ_EVENT指针
+10h  DWORD   TerminationStatus //活动标志或返回值
+14h  DWORD   Un2 //未知
....
+21h  BYTE    Flags1 // Service标记,
             // "1"是Service进程,
             // "0"普通进程
....
+24h  DWORD   pPSP // DOS PSP指针
....
============================================
---- 3. 实 现 接 口 

---- (1) Windows95 中 提 供 的 简 单 的Service 接 口 是 一 个
32 位 的API: RegisterServiceProcess, 由 于 在VC++ 的Online help
中 得 不 到 关 于 这 个API 的 确 切 解 释, 笔 者 不 得 不 针 
对 此API 进 行 了 逆 向 分 析, 以 下 是 在Windows95 的Kernel32.dll 
中 该API 的 伪 码. 我 们 可 以 清 楚 的 看 到Window95 内 部 到 
底 是 怎 样 做 的, 其 实 处 理 的 非 常 简 单. 

BOOL RegisterServiceProcess
( DWORD dwProcessID, DWORD dwType )
{
 HANDLE dwPID;
 if( dwProcessID == NULL )
   dwPID = dwCurrentProcessID; 
   // Get global kernel32 variable
 else
   // Call some kernel functions
   if( ( dwPID = CheckPID( dwProcessID ) == NULL )
     return FALSE;
 if( dwType == 1 )
 {
   *(BYTE *)( dwPID + 0x21 ) | = 0x01;
   return TRUE;
 }
 if( dwType == 0 )
 {
   *(BYTE *)( dwPID + 0x21 ) & = 0xFE;
   return TRUE;
 }
 return FALSE;
}
  以下为函数原形:
BOOL  RegisterServiceProcess( DWORD dwPID, DWORD dwType )
参数:  dwPID:进程ID, NULL代表当前进程
    dwType: RSP_SIMPLE_SERVICE为登记
        RSP_UNREGISTER_SERVICE为取消登记
返回值: TRUE: 调用成功
    FALSE: 调用失败
---- (2) 另 外, 为 了 让Service 进 程 有 机 会 在BOOT 后 就 
启 动,Windows95 的Registry 中 提 供 了 加 载 方 法: 在KEY 
" MyComputer \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
\CurrentVersion \RunServices " 加 入 自 己 的 应 用 程 序 命 
令 行, 即 可 实 现 开 机 自 动 加 载. 当 然, 如 果 你 得 机 
器 中 没 有 这 个Key, 自 己 建 一 个 也 是 可 以 的. 

---- 4. 例 程 

---- 下 面 是 实 现 例 程, 所 有 代 码 经 过 了WINDOWS95. 
WINDOWS98 BETA3 的 测 试, 可 以 方 便 的 加 入 到 自 己 的 项 
目 文 件 中. 

---- 头 文 件: 

// File:      service.h
// The head file of "service.cpp"
// Note: 1. You must use C++ compiler
//   2. The platform is WIN32 (WINNT & WIN95)

#ifndef _SERVICE_H
#define _SERVICE_H

/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
// Micros
#define RSP_SIMPLE_SERVICE      1
#define RSP_UNREGISTER_SERVICE    0

// Function types for GetProcAddress
#define RegisterServiceProcess_PROFILE 
(DWORD (__stdcall *) (DWORD, DWORD))

// Service Fuctions in Win95
BOOL  W95ServiceRegister(DWORD dwType);
BOOL  W95StartService( DWORD dwType );

#endif

CPP 文 件:
// File:    service.cpp --- implement the service

#include "service.h"
/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
 登 记 为Service 子 程 序:
/////////////////////////////////////////
////////////////////////////////////////
// Define:       BOOL 
    W95ServiceRegister(DWORD dwType)
// Parameters: dwType --- Flag to 
register or unregister the service
//      RSP_SIMPLE_SERVICE   means register
//      RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success; 
    FALSE --- call failer

BOOL  W95ServiceRegister( DWORD dwType )
{
    // Function address defination
    DWORD  (__stdcall * hookRegisterServiceProcess)
          ( DWORD dwProcessId, DWORD dwType ); 

    // Get address of function
    hookRegisterServiceProcess = 
    RegisterServiceProcess_PROFILE
               GetProcAddress
              (GetModuleHandle("KERNEL32"),
               TEXT("RegisterServiceProcess"));

    // Register the WIN95 service
    if(hookRegisterServiceProcess(NULL,dwType)==0)
        return FALSE;
    return TRUE;
}
---- 加 入 注 册 表 子 程 序: 

#define SERVICE_NAME  TEXT("SERVICE")
// Define:   BOOL  W95StartService( DWORD dwType )
// Parameters: dwType --- Flag to
 register or unregister the service
//      RSP_SIMPLE_SERVICE   means register
//      RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success; FALSE --- call failer

BOOL W95StartService( DWORD dwType )
{
    // Local Variables
    TCHAR  lpszBuff[256];
    LPTSTR lpszStr = lpszBuff +128;
    LPTSTR lpszName    = lpszBuff;
    HANDLE hKey      = NULL;
    DWORD  dwStrCb     = 0;
    DWORD  dwValueType   = 0;

    // Get service name currently
    lpszName = GetCommandLine();
    for( int i = _tcslen(lpszName)-1; I >=0; i-- )
    {
     if( ( lpszName[i] != '"' )&&( lpszName[i]!=' ') )
            break;
        else if( lpszName[i] == '"' )
            lpszName[i] = '\0';
    }
    if( lpszName[0] == '"' )
        lpszName = lpszName +1;

    // Registe as start up service
    if( RegOpenKeyEx (HKEY_LOCAL_MACHINE,
    TEXT( "SOFTWARE\\Microsoft\\Windows\\
     CurrentVersion\\RunServices"),
           0,
           KEY_QUERY_VALUE | KEY_SET_VALUE,
           &hKey ) != ERROR_SUCCESS )
    {
        if( RegCreateKey( HKEY_LOCAL_MACHINE,
           TEXT( "SOFTWARE\\Microsoft\\
           Windows\\CurrentVersion\\RunServices"),
           &hKey ) != ERROR_SUCCESS )
        {
            //DebugOut( "RegCreateKey() error!");
            return FALSE;
        }
    }

    dwValueType   = REG_SZ;
    dwStrCb     = 128;

    // Take value
    if( RegQueryValueEx(hKey, 
         SERVICE_NAME,
         0,
         &dwValueType,
         (LPBYTE)lpszStr,
         &dwStrCb ) == ERROR_SUCCESS )
    
    {
        // Find this key value
        if( _tcscmp( lpszStr, lpszName )==0 )
        {
            // Remove the service
            if( dwType == RSP_UNREGISTER_SERVICE )
            {
             if(RegDeleteValue( hKey, SERVICE_NAME ) 
              == ERROR_SUCCESS )
                {
                    RegCloseKey ( hKey );
                    return TRUE;
                }
                RegCloseKey( hKey );
                return FALSE;
            }
            // Already exist service
            if( dwType == RSP_SIMPLE_SERVICE )
            {
                //DebugOut("Already registed!");
                RegCloseKey( hKey );
                return TRUE;
            }
        }
        // Not find it
    } // No this value

    // Unregiste return
    if( dwType == RSP_UNREGISTER_SERVICE )
    {
        RegCloseKey( hKey );
        return TRUE;
    }

    // No this value then create it
    if( dwType == RSP_SIMPLE_SERVICE )
    {
        dwStrCb = 128;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -