一、编辑框输入时,如何让Windows发出无法输入非法字符的提示音
MessageBeep(MB_ICONEXCLAMATION);
二、互斥量的创建与清除
HANDLE hMutex;
hMutex = CreateMutex(NULL,FALSE,"互斥量的名称,名称应该是唯一的");
退出应用程序时,调用:
CloseHandle();
三、得到运行时屏幕分辨率等相关信息
int iFullWidth=GetSystemMetrics(SM_CXSCREEN);
int iFullHeight=GetSystemMetrics(SM_CYSCREEN);
四、如何更改窗口类名称
1、如果是框架窗口:
在窗口的PreCreateWindow(CREATESTRUCT& cs)里写下:
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetInstanceHandle();
if (!(::GetClassInfo(hInst, "你要改的名称", &wndcls)))
{
// get default MFC class settings
if (::GetClassInfo(hInst, cs.lpszClass, &wndcls))
{
wndcls.lpszClassName = "你要改的名称";
//wndcls.hbrBackground = NULL;
if (!AfxRegisterClass(&wndcls))
{
AfxThrowResourceException();
}
}
else
{
AfxThrowResourceException();
}
}
cs.lpszClass ="你要改的名称";
bRtn = CDialog::PreCreateWindow(cs);
2、如果是对话框窗口
首先:
修改对话框资源
在工作区的资源标签上右键点击最上边的那个“xx resources”
在弹出的对话框中,去掉“Enable MFC feature”复选项
再打开对话框资源的属性对话框,在右下角的class name输入你要修改的类名。比如”xxx”
再加上“Enable MFC feature”复选项
然后:
在应用程序类的InitInstance里写下:
WNDCLASS wc = {0};
::GetClassInfo(AfxGetInstanceHandle(),"#32770",&wc);
wc.lpszClassName="你要改的类名";
AfxRegisterClass(&wc);
五、编辑框的OnChar事件里,要根据用户选择和输入的键,先获取输入后的结果,再来判断是否接受该输入,此时,需要一个输入键后预算结果的函数,如下(iStartPos是选择的开始位置,iEndPos是选择的结束位置,可用GetSel获取):
void getPartStr(CString strOriginValue,int iStartPos,int iEndPos,CString *pStrResult,UINT uChar)
{
*pStrResult = "";
int i;
strOriginValue.ReleaseBuffer();
if(0 == strOriginValue.GetLength() && (uChar!=0x08)) //08是backspace键
{
pStrResult->Format("%c",uChar);
}
else
{
for(i=0;i<strOriginValue.GetLength();i++)
{
if(iStartPos == iEndPos)
{
if(i == (iStartPos -1))
{
if(uChar!=0x08)
{
*pStrResult = *pStrResult + strOriginValue.GetAt(i);
pStrResult->Format(*pStrResult + "%c",uChar);
}
continue;
}
if((0 == iStartPos) && (0 == i))
{
pStrResult->Format(*pStrResult + "%c",uChar);
}
*pStrResult = *pStrResult + strOriginValue.GetAt(i);
}
else
{
if((i<iStartPos)||(i>=iEndPos))
{
*pStrResult = *pStrResult + strOriginValue.GetAt(i);
}
if(i == (iStartPos) && (uChar!=0x08) )
{
pStrResult->Format(*pStrResult + "%c",uChar);
}
}
}
}
}
六、在USB插出插入时,系统应给应用程序消息,如果响应呢?
首先,窗口增加响应宣告:ON_WM_DEVICECHANGE
增加响应函数:
afx_msg BOOL OnDeviceChange(WPARAM nEventType, LPARAM dwData);
在“DBT_DEVNODES_CHANGED”响应宏中写下你要做的处理
七、TCHAR类型的trim函数
LPTSTR _tcstrim(const LPTSTR lpszStr)
{
ASSERT(lpszStr != NULL);
LPTSTR lpStrEnd;
lpStrEnd = lpszStr + _tcslen(lpszStr);
while(lpStrEnd > lpszStr)
{
lpStrEnd --;
if((*lpStrEnd) == _T(' '))
{
(*lpStrEnd)=0;
}
else
{
break;
}
}
lpStrEnd = lpszStr + _tcslen(lpszStr);
LPTSTR lpszDest = lpszStr;
LPTSTR lpszSrc = lpszStr;
while((lpszSrc < lpStrEnd) && (*lpszSrc) == _T(' '))
{
lpszSrc++;
};
if(lpszDest != lpszSrc)
{
while(lpszSrc<=lpStrEnd)
{
(*lpszDest) = (*lpszSrc);
lpszDest++;
lpszSrc++;
}
}
return lpszStr;
}
八、ON_UPDATE_COMMAND_UI宏
ON_COMMAND响应类型的对象,如菜单或界面控件(CheckBox、RatioButton)等界面资源可定义该宏。
宏响应函数以CCmdUI的指针类型做为函数参数。
此宏用于命令级控件需要刷新时调用,可以由操作系统完成,也可以由程序调用完成;如用户点击了相关Command类对象响应其处理时会OS会自动触发,也可由用户调用:
SendMessage(WM_COMMAND, CN_UPDATE_COMMAND_UI);
九、OnIdleUpdateCmdUI 函数
用于响应WM_IDLEUPDATECMDUI消息,在消息队列空闲时发送,用于更新ON_COMMAND响应类型的控件。
此函数在CFrameWnd及其子类中调用,CControlBar类型的控件中该函数响应刷新。
OnUpdateCmdUI一般是Bar类型的界面控件成员函数,函数第一个参数是Bar的父窗口,从该窗口中分发对应Bar对象的更新控件状态消息,父框架窗口会在Idle时调用子控件该函数。
十、对参数求和取平均的函数,参数个数不定
double Aveg(int iFirst,...)
{
double sum=0;
int iCount=0;
int i=iFirst;
int iTemp;
va_list vl;
va_start(vl,iFirst);
while(i!=NULL)
{
sum+=i;
iTemp=i;
iCount++;
i = va_arg( vl, int);
}
sum-=iTemp;
iCount--;
va_end(vl);
return( sum ? (sum / iCount) : 0 );
}
这里函数调用有个原则,就是最后一个参数必须为0,表结束,不然程序会出现错误。
十一、弹出选择音乐类型对话框,显示音乐文件播放长度,并播放的代码:
voidCMp3PlayerDlg::OnOpen()//点击打开按钮,选择音乐文件。可以多选
{
m_MusicList.ResetContent();
m_MusicAry.RemoveAll();
m_Music.Close();//m_Music是CCOMMCI对象
Init();
m_Pause.SetWindowText("暂停");
//
CStringfilter="媒体文件(所有类型)|*.cda;*.mid;*.rmi;*.midi;*.asf;*.wm;*.wma;*.asx;*.wax;*.m3u;*.wvx;*.mpeg;*.mpg;*.m1v;*.mp3;*.avi;*.wmv;*.wav;*.snd;*.au;*.aif;*.aifc|";
filter=filter+"CD音乐曲目(*.cda)|*.cda|"+
"MIDI文件(*.mid;*.rmi;*.midi)|*.mid;*.rmi;*.midi|"+
"WindowsMedia文件(*.asf;*.wm;*.wma;*.wa?)|*.asf;*.wm;*.wma;|"+
"媒体播放表(*.asx;*.wax;*.m3u;*.wvx)|*.asx;*.wax;*.m3u;*.wvx|"+
"电影文件(*.mpeg;*.mpg;*.m1v;*.mp3)|*.mpeg;*.mpg;*.m1v;*.mp3|"+
"视频文件(*.avi;*.wmv)|*.avi;*.wmv)|"+
"音频文件(*.wav;*.snd;*.au;*.aif;*.aifc)|*.wav;*.snd;*.au;*.aif;*.aifc|"+
"所有文件(*.*)|*.*|";
CFileDialogmusic(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT,filter);
if(music.DoModal()==IDOK)
{
POSITIONpos=music.GetStartPosition();
while(pos!=NULL)
{
CStringstr=music.GetNextPathName(pos);
m_MusicAry.Add(str);
intindex=str.ReverseFind('//');
if(index==-1)
m_MusicList.AddString(str);
else
{
CStringname=str.Mid(index+1);
m_MusicList.AddString(name);
}
}
}
}
============================
voidCMp3PlayerDlg::Play(intindex)//播放函数,index为曲目的序号
{
m_Music.Close();
m_MusicList.SetCurSel(index);
CStringsPath=m_MusicAry.GetAt(index);
m_Music.Open(sPath);
m_Status.SetWindowText(sPath+_T("正在播放..."));//在状态条中显示提示信息
m_nLength=m_Music.GetLength();//获取音乐长度
m_nPos=0;
m_nTime=m_nLength/1000;//除以1000即为播放时间
//
m_sMusicLen.Format("%d分%d秒",m_nTime/60,m_nTime%60);//显示播放时间
m_sMusicPos.Format("%d分%d秒",m_nPos/60,m_nPos%60);//显示当前播放位置
//
UpdateData(false);
m_MPBar.SetScrollRange(0,m_nTime);//设置音乐播放的进度条范围
//
m_Volume.SetRange(0,1000);//设置音量调节范围
m_Volume.SetPos(m_nVolume);
//
m_Music.Play(this->m_hWnd);//开始播放
SetTimer(2,1000,NULL);//启动2号定时器
}
十二、如何广播消息到所有应用程序集:
PostMessage时发送的窗口对象用HWND_BROADCAST宏代替,则消息会发到所有程序。
十三、通过HBITMAP句柄保存GDI设备上下文
int SaveBitmapToFile(HBITMAP hBitmap,LPCWSTR lpFileName)
//hBitmap为屏幕位图句柄lpFileName为位图文件名
{
HDC hDC;//设备描述表
int iBits;//当前显示分辨率下每个像素所占字节数
WORD wBitCount;//位图中每个像素所占字节数
//定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAP Bitmap;//位图属性结构
BITMAPFILEHEADER bmfHdr;//位图文件头结构
BITMAPINFOHEADER bi;//位图信息头结构
LPBITMAPINFOHEADER lpbi;//指向位图信息头结构
HANDLE fh, hDib, hPal,hOldPal=NULL;//定义文件,分配内存句柄,调色板句柄
//计算位图文件每个像素所占字节数
hDC=CreateDC(_T("DISPLAY"),NULL,NULL,NULL);
iBits=GetDeviceCaps(hDC,BITSPIXEL)*GetDeviceCaps(hDC,PLANES);
DeleteDC(hDC);
if(iBits<=1)
{
wBitCount = 1;
}
else if(iBits<= 4)
{
wBitCount=4;
}
else if(iBits<=8)
{
wBitCount=8;
}
else if(iBits<=24)
{
wBitCount=24;
}
else if(iBits<=32)
{
wBitCount=32;
}
//计算调色板大小
if (wBitCount<=8)
dwPaletteSize=(1<<wBitCount)*sizeof(RGBQUAD);
//设置位图信息头结构
GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&Bitmap);
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=Bitmap.bmWidth;
bi.biHeight=Bitmap.bmHeight;
bi.biPlanes=1;
bi.biBitCount=wBitCount;
bi.biCompression=BI_RGB;
bi.biSizeImage=0;
bi.biXPelsPerMeter=0;
bi.biYPelsPerMeter=0;
bi.biClrUsed=0;
bi.biClrImportant=0;
dwBmBitsSize=((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
//为位图内容分配内存
hDib=GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi=bi;
//处理调色板
hPal=GetStockObject(DEFAULT_PALETTE);
if(hPal)
{
hDC=GetDC(NULL);
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,
(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(BITMAPINFO*)lpbi,DIB_RGB_COLORS);//恢复调色板
if(hOldPal)
{
SelectPalette(hDC,(HPALETTE)hOldPal,TRUE);
RealizePalette(hDC);
ReleaseDC(NULL,hDC);
}
//创建位图文件
fh=CreateFile(lpFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(fh==INVALID_HANDLE_VALUE)
return FALSE;
//设置位图文件头
bmfHdr.bfType=0x4D42;//"BM"
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
+dwPaletteSize+dwBmBitsSize;
bmfHdr.bfSize=dwDIBSize;
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)
+dwPaletteSize;
//写入位图文件头
WriteFile(fh,(LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
//写入位图文件其余内容
WriteFile(fh,(LPSTR)lpbi,dwDIBSize,&dwWritten,NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return true;
}
十四、AVI、Wave文件播放时间的计算方法
根据.wav文件头中文件长度和WAVEFORMATEX结构中nAvgBytesPerSec值算出播放时间:
(stream size-head size)/ 采样率 / 比特率 / 声道数 * 8
从wav头你可以得到采样率samplerate和样品个数samplenumber.
time = (1/samplerate) * samplenumber
下面是wav格式头的描述:
名称 字节 描述
ckid 4 ascii字符串“fmt ”。注意串中最后一个字符为空格,
所有的块的id必须是4字符,这样最后的空格用于补充
小于4字符的串。
nchunksize 4 这是一个32位的无符号整型值,它保存的是以字节计的
整个“fmt ”块的长度。注意wav文件中所有多字节整
型值都是低字节在前的方式表示的。例如,如果一个
wav文件的块尺寸为16,它在文件中的16进制表示为:
10 00 00 00。
wformattag 2 它定义了wav文件中的音频数据是怎样编码的。此值常为
1,表示pulse code modulation(pcm)。其它值常常为
压缩方式编码,需要更复杂的算法。
nchannels 2 这是wav文件中音频表现的通道数。单声道声音只有1个
通道;立体声有两个通道。多于2个通道是可能的,但很少见。
nsamplespersec 4 采样速率用每秒的采样数或hz表示。此值的倒数两个采
样间的以秒计的时间值。典型值为11025,
22050,44100。几乎没有小于
8000hz大于48000hz的采样速率。
navgbytespersec 4 播放程序实时处理播放音频数据平均每秒字节数。对于
pcm音频这是多余的,因为你可以通过采样速率、通道
数、每个采样的字节数相乘得到。
nblockalign 2 这个数字告诉你一次输出的字节数。在pcm中,此值等于
每次采样的字节数乘以通道数。
nbitspersample 2 此值仅在pcm录音中出现。它定义了每次采样的音频幅度
的位数。通常为8或16。8位音频文件仅有256级不同的
幅度,因此质量较低且有附带的被称为量化失真的嘶音。
16位的音频文件的声音质量较好但是尺寸是前者的两倍
。
AVI文件:
1. #include <vfw.h>
引入 vfw32.lib
2. AVIFileInit(); 只要调用到有关AVI的函数,必须保证已调用(只要一次)过这个函数。
3.PAVIFILE pfileWave;
HRESULT hr;
hr = AVIFileOpen(&pfileWave, m_strWaveFile,0,0L);
if(hr!=0)
AfxMessageBox("Failed to open AVI");
PAVISTREAM paviWave;
if (AVIFileGetStream(pfileWave, &paviWave, 0L, 0) != AVIERR_OK)
AfxMessageBox("Failed to get stream!");
4. LONG timeEnd;
LONG timeStart;
timeStart=AVIStreamStartTime(paviWave);
timeEnd=AVIStreamEndTime(paviWave);
LONG timeTotal=timeEnd-timeStart+1; //注意是毫秒级,除以1000就可以了。
5. if(psWave)
AVIStreamClose(psWave);
if(pfileWave)
AVIFileClose(pfileWave);
6. AVIFileExit();