MFC编程小技巧

一、编辑框输入时,如何让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();  

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值