-
2005-09-03
BCB中管道应用示例 - [C++Builder技术文档]
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::RunCmd(AnsiString cmd,TStringList *stringlist)
{
TMemoryStream *memstream=new TMemoryStream();
AnsiString rn="\\r\\n";
PROCESS_INFORMATION proc;
STARTUPINFO start;
SECURITY_ATTRIBUTES sa;
long ret;
unsigned long lngBytesread;
HANDLE hReadPipe,hWritePipe;
char *strBuff=(char *)malloc(256);
if(strBuff==NULL)
{
return false;
}
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle=true;
sa.lpSecurityDescriptor=NULL;
ret=CreatePipe(&hReadPipe,&hWritePipe,&sa,0);
if(ret==0)
{
//创建管道失败
ShowMessage("创建管道失败");
return false;
}
memset(&start,0x00,sizeof(STARTUPINFO));
start.cb=sizeof(STARTUPINFO);
start.dwFlags=STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
start.hStdOutput=hWritePipe;
start.hStdError=hWritePipe;
bool retc=CreateProcess(NULL,cmd.c_str(),NULL,NULL,true, 0, 0, NULL, &start, &proc);
if(!retc)
{
return false;
}
CloseHandle(hWritePipe);
unsigned long len;
memstream->Position=0;
while(true)
{
memset(strBuff,0x00,256);
GetFileSize(hReadPipe,&len);
ret = ReadFile(hReadPipe, strBuff, 256, &lngBytesread,NULL);
if(ret==0)
{
break;
}
else
{
memstream->Write(strBuff,lngBytesread);
}
}
CloseHandle(proc.hProcess);
CloseHandle(proc.hThread);
CloseHandle(hReadPipe);
memstream->Position=0;
free(strBuff);
stringlist->LoadFromStream(memstream);
memstream->Clear();
delete memstream;
return true;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringList *StrList=new TStringList;
AnsiString strcmd=Edit1->Text;
RunCmd(strcmd,StrList);
Memo1->Clear();
Memo1->Text=StrList->Text;
}
//---------------------------------------------------------------------------
-
2004-04-24
皮肤技术研究 - [C++Builder技术文档]
做播放器的话,嘿嘿,当然离不开皮肤技术了。。。
[face01]实现皮肤技术有很多种方法,最简单的就是用第三方控件或者皮肤类,但别人的东西终究还是别人的东西,要不就是收费,要不就是有很多限制,所以,好东西呢,还是自己造比较好。。[face07]
自己实现皮肤的话,首先要解决的就是不规则窗体的问题,因为皮肤界面千变万化,所以窗体是必须要适应皮肤变化的,这个实现起来比较容易,用几个API函数就可以实现了
分别是:
CreateRect() //当然还有别的API函数,用来创建多边形等,这个是创建矩形区域的
RgnCombineRgn() //区域运算用的,主要是把不需要的区域删除,留下需要的界面
SetWindowRgn() //用来重新设置窗体区域
比如:现在要根据当前Image里的图片创建不规则窗体
int x,y; HRGN WndRgn,TempRgn;
WndRgn=CreateRectRgn(0,0,Image1->Width,Image1->Height);
for(x=0;x<Width;x++)
for(y=0;y<Height;y++)
if(Image1->Canvas->Pixels[x][y]==clBlack)
{
TempRgn=CreateRectRgn(x,y,x+1,y+1); 创建需要删除的区域,以象素为单位
CombineRgn(WndRgn,WndRgn,TempRgn,RGN_XOR); 剔除不必要的区域
DeleteObject(TempRgn);
}
SetWindowRgn(Handle,WndRgn,true);
就这么简单。。。
至于按钮之类的,原理和这个都一样,不过要先创建一个所以图片,用来确定按钮在界面中的位置 -
2004-04-18
Winamp插件研究[转自CSDN] - [C++Builder技术文档]
近来想做一个播放器,找了很久一直都找不到理想的解码器,不过最后还是想到winamp的插件。。。
[face10]既然winamp基于插件来完成解码,那么它就一定有解码器,只要找到它的接口就可以是使用了
去官方网站下载winamp的SDK,终于得知它的解码工作交给相应的Input插件模块。
在 Pulgin 文件夹中有很多的 DLL(动态链接库)文件,其中的in_mp3.dll就是mp3的解码插件,这个插件可以解码AAC/Mpeg1/mpeg2/mpeg3的音频,还有一个in_wm.dll自然就是解码WMA的了
从SDK文档中得知,每种插件都具有固定的数据结构,如Input模块的数据结构(In_Module ),Output模块的(Out_Module ),同时每种插件的dll都具有约定的入口函数,对于Input插件,其入口函数为
__declspec( dllexport ) In_Module * winampGetInModule2()
其结构体:
typedef struct
{
int nVer; // 模块版本号
char *szDesc; //模块描述信息
HWND hMainWnd; // Winamp的主窗体句柄(由Winamp来填写)
HINSTANCE hDllInstance; // DLL实例句柄(由Winamp来填写)
char *szFileExt; // 扩展名过滤器,格式参见GetOpenFileName
int nIsSeekable; // 是否可索引媒体,是-你可以拖动进度条,否-反之
int UsesOutputPlug; // 是否使用输出插件?你想在这个模块里搞定一切?
// 下面都是函数指针,将被Winamp调用
void (*Config)(HWND hwndParent); // 配置对话框
void (*About)(HWND hwndParent); // 关于对话框
void (*Init)(); // 初始化
void (*Quit)(); // 退出
// szFile - 传入的文件名,szTitle - 传出的标题,nLen - 转出的时间长度,毫秒。
// 如果szFile传NULL,则返回当前播放文件的信息
void (*GetFileInfo)(char *szFile, char *szTitle, int *nLen);
int (*InfoBox)(char *szFile, HWND hwndParent); // 弹出文件信息对话框
int (*IsOurFile)(char *szFile); // 检查文件格式
int (*Play)(char *szFile); // 开始播放文件szFile,返回0正常,-1错误
void (*Pause)(); // 暂停处理
void (*UnPause)(); // 取消暂停
int (*IsPaused)(); // 是否斩停?1是暂停,0不是
void (*Stop)(); // 停止播放
int (*GetLength)(); // 取得长度,毫秒单位
int (*GetOutputTime)(); // 获取当前时间,一般调用out模块的同名函数即可
void (*SetOutputTime)(int nTime); // 索引到某一时刻
void (*SetVolume)(int volume); // 音量调节,从0 - 255
void (*SetPan)(int pan); // 左右声道平衡,从-127 - 127
//下面的函数多和AVS、可视化效果、均衡器等有关,具体咱们用不到,就暂时不讲了。
void (*SAVSAInit)(int maxlatency_in_ms, int srate);
void (*SAVSADeInit)(); // call in Stop()
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
int (*SAGetMode)();
void (*SAAdd)(void *data, int timestamp, int csa);
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
int (*VSAGetMode)(int *specNch, int *waveNch);
void (*VSAAdd)(void *data, int timestamp);
void (*VSASetInfo)(int nch, int srate);
int (*dsp_isactive)();
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
void (*EQSet)(int on, char data[10], int preamp);
void (*SetInfo)(int bitrate, int srate, int stereo, int synched);
Out_Module *outMod; // 看看,Winamp终于露出马脚了吧?
} In_Module;
这样通过这个入口函数,就可以轻易的得到了Input插件的 In_Module结构体,接下来的事情自然也就很容易了,有了这个结构体,插件的所有功能都可以调用了。
不过单凭这个Input插件还是不能放出声音来的,因为Input插件虽然能完成mp3或者WMA的解码,但却没有把他们输出来,所以,就得自己写输出模块。不过,winamp有个OutPut插件可以完成输出功能,这就是Out_Wave.dll,加上这个插件,那么播放mp3就非常容易了。
OutPut插件得入口函数
__declspec( dllexport ) Out_Module * winampGetOutModule()
其结构体为:Out_Module
typedef struct
{
// 下面有些和In_Module一样,就不赘述了。
int nVer;
char *szDesc;
int nId; // 自己给一个ID,不知道有什么用,反正大于65536就行了。
HWND hMainWindow;
HINSTANCE hDllInstance;
void (*Config)(HWND hwndParent);
void (*About)(HWND hwndParent);
void (*Init)();
void (*Quit)();
// nSample - 采样率, nChannels - 声道数,1或2
// nBitPerSamp - 每采样的位率,nBufLen、nPreBufLen - 缓冲长度,咱们用不到
// 返回大于0正常播放,小于0失败
int (*Open)(int nSample, int nChannels, int nBitPerSamp, int nBufLen, int nPreBufLen);
void (*Close)(); // 关闭输出设备
// pBuf - 内存数据块,nLen - 数据块的长度
int (*Write)(char *pBuf, int len); // 返回0成功 -
2004-04-11
LRC格式歌词分解程序 - [C++Builder技术文档]
作为1.12版歌词串串烧的一个模块,主要用来分解LRC格式的歌词,该模块已经完全封装为一个类,方便调用
下面是LRC格式的描述
LRC 歌词是一种包含着“[*:*]”形式的“标签(tag)”的、基于纯文本的歌词专用格式。最早由郭祥祥先生(Djohan)提出并在其程序中得到应用。这种歌词文件既可以用来实现卡拉OK功能(需要专门程序),又能以普通的文字处理软件查看、编辑。当然,实际操作时通常是用专门的LRC歌词编辑软件进行高效编辑的。以下具体介绍LRC格式中的“标签”。
时间标签(Time-tag)
形式为"[mm:ss]"或"[mm:ss.fff]"(分钟数:秒数)。数字须为非负整数,比如"[12:34.5]"是有效的,而"[0x0C:-34.5]"无效。
它可以位于某行歌词中的任意位置。一行歌词可以包含多个时间标签(比如歌词中的迭句部分)。根据这些时间标签,用户端程序会按顺序依次高亮显示歌词,从而实现卡拉OK功能。另外,标签无须排序。
标识标签(ID-tags)
其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。
[ar:艺人名]
[ti:曲名]
[al:专辑名]
[by:编者(指编辑LRC歌词的人)]
[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
样例
[ar:unknown]
[ti:sample]
[al:none]
[by:me]
[01:02.355][00:00]This line should be sung twice
[00:05.7]And this one... once only.
开发标准(供程序员阅读参考)
以下列出了开发支持LRC格式的软件时应遵守的一些标准。
无论是否在行首,行内凡具有“[*:*]”形式的都应认为是标签。(注意:其中的冒号并非全角字符“:”)
凡是标签都不应显示。
凡是标签,且被冒号分隔的两部分都为非负数,则应认为是时间标签。因此,对于非标准形式(非“[mm:ss]”)的时间标签也应能识别(如“[0:0]”)。
凡是标签,且非时间标签的,应认为是标识标签。
标识名中大小写等价。
为了向后兼容,应对未定义的新标签作忽略处理。另应对注释标签([:])后的同一行内容作忽略处理。
应允许一行中存在多个标签,并能正确处理。
应能正确处理未排序的标签。 -
2004-04-11
Unicode编码文件的读取 - [C++Builder技术文档]
Unicode就是宽字符编码,它与ANSI编码最大的不同就是一个ANSI编码的位宽是8位,而Unicode的位宽是16位,比如:一个Unicode编码的字符 ’A’ 其16进制编码为0x0041,而同样的字符用ANSI编码就会表示为0x41;
转入正题,不去管Unicode的编码方式,只要能把它识别出来就可以了。Windows SDK中提供了一个API函数,可以把ASCII编码转换为Unicode编码,那就是WideCharToMultiByte()函数,所以编码转换工作就全部交给这个函数了
看一下WideCharToMultiByte()的原型声明:
int WideCharToMultiByte(
UINT CodePage, // code page
DWORD dwFlags, // performance and mapping flags
LPCWSTR lpWideCharStr, // address of wide-character string
int cchWideChar, // number of characters in string
LPSTR lpMultiByteStr, // address of buffer for new string
int cchMultiByte, // size of buffer
LPCSTR lpDefaultChar, // address of default for unmappable characters
LPBOOL lpUsedDefaultChar // address of flag set when default char. used
);
第一个参数使用CP_ACP,第二个参数设为0,第三个参数就是要转换的Unicode字符串的指针,第四个参数,Unicode字符串长度,第五个参数转换到ANSI字符串的指针,第六个参数ANSI字符串的长度
这样就可以把Unicode转换为ANSI编码了,但是还有一个问题,就是如何判断要读入的文件是Unicode编码的还是ANSI编码的?查了一下资料,发现所有Unicode编码的文本文件,其文件头2个字节一定是"0xff","0xfe",这样就好办了,只要先读出这两个字节,然后就可以判断是不是Unicode编码的了。
if( psFirst[0] == ’\xff’ && psFirst[1] == ’\xfe’ )用这条语句就可以判断了。
下面给出C++的一段文件读取代码,返回的就是AnsiString的字符串,这样就可以读取Unicode编码和非Unicode编码的文件了
AnsiString TForm1::ReadUnicodeFromFile(const AnsiString &FileName)
{
char psFirst[2];
AnsiString str;
int iFileHandle = FileOpen( FileName, fmOpenRead );
int iFileLength = FileSeek( iFileHandle, 0, 2 );
FileSeek(iFileHandle, 0, 0);
FileRead(iFileHandle, psFirst, 2); //读出文件的头2个字节,用来判断是否为Unicode编码
if( psFirst[0] == ’\xff’ && psFirst[1] == ’\xfe’ )
{
wchar_t *wstr=new wchar_t[iFileLength+1];
FileRead(iFileHandle, wstr, iFileLength);
FileClose(iFileHandle);
int nLen = wcslen(wstr)+1;
char *buf = new char[2*nLen];
WideCharToMultiByte(CP_ACP, 0, wstr, nLen, buf, 2*nLen, NULL, NULL);
str = buf;
delete[] buf;
}
else
{
char *pszBuffer = new char[iFileLength+1];
FileSeek(iFileHandle, 0, 0);
FileRead(iFileHandle, pszBuffer, iFileLength);
FileClose(iFileHandle);
str=pszBuffer;
delete []pszBuffer;
}
return str;
}
共1页 1






