这段时间在使用MFC做媒体播放器项目,查询了不少资料,用到的技术主要有ADO、多线程、DirectShow、MFC相关控件包括ActiveX控件(Windows Media Player、Active Movie3)的使用等等一些东西。用的主要参考文档有Windows Media Player相关的开发文档、MSDN。
先谈一下这段时间的收获吧,这将近一个月的时间内,通过媒体播放器项目,我熟悉了使用ADO操作Access数据库、SQL语句的运用(虽然用的语句比较简单,无非增删改查)、Window Media Player对应的17个类的使用、MFC的列表框CListBox、树控件CTreeCtrl、CListCtrl等控件、多线程的使用等。接下来把自己查询搜集到的资料做一个整理吧(主要是通过查询csdn、博客园、百度文库找到的)。
1、VC获取一个菜单的状态,并打钩 做记事本的时候,遇到这么个问题,就是:如何获取菜单项当前是否被选中(打勾),如果选中,点击菜单后取消选中,如果未选中,点击菜单后选中,具体实现代码如下: void CMyNotePadDlg::OnStatus() //菜单的Command消息映射函数 { // TODO: Add your command handler code here if (AfxGetMainWnd()->GetMenu()->GetMenuState(ID_STATUS,MF_CHECKED)) { AfxGetMainWnd()->GetMenu()->CheckMenuItem(ID_STATUS,MF_UNCHECKED); } else { AfxGetMainWnd()->GetMenu()->CheckMenuItem(ID_STATUS,MF_CHECKED); } }
2、VC中隐藏窗口的一部分,比如说查询数据库的左右侧窗口、播放列表显示部分等。 代码如下: void CMyMediaPlayerDlg::OnButtonHide() { // TODO: Add your control notification handler code here CString str; if (GetDlgItemText(IDC_BUTTON_HIDE,str),str=="<<") { SetDlgItemText(IDC_BUTTON_HIDE,">>"); } else { SetDlgItemText(IDC_BUTTON_HIDE,"<<"); } static CRect rectLarge; static CRect rectSmall; if(rectLarge.IsRectNull()) { CRect rectSeparator; GetWindowRect(&rectLarge); GetDlgItem(IDC_SEPARATOR)->GetWindowRect(&rectSeparator); rectSmall.left=rectLarge.left; rectSmall.top=rectLarge.top; rectSmall.right=rectSeparator.right; rectSmall.bottom=rectLarge.bottom; } if (str=="<<") { SetWindowPos(NULL,0,0,rectSmall.Width(),rectSmall.Height(),SWP_NOMOVE | SWP_NOZORDER); } else { SetWindowPos(NULL,0,0,rectLarge.Width(),rectLarge.Height(),SWP_NOMOVE | SWP_NOZORDER); } }
3、如何给指定的对话框添加菜单? 犯法1:静态加载菜单,即不通过代码而是通过编辑资源。
转至对话框资源,在需要添加菜单的对话框资源IDD_MYMEDIAPLAYER_DIALOG中,选中该对话框资源,右键选择【Properties】属性,再在【General】选项卡的Menu中选择需要添加的菜单,比如IDR_MAINFRAME_MENU,这样的话就可以在该对话框类对象创建时使用时就可以显示该菜单了。 这样就将菜单和对话框关联起来了。
方法2:直接通过代码加载菜单
在的对话框类的OnInitDialog()函数中加这么几行代码就搞定了。
//加载菜单 CMenu menu; menu.LoadMenu(IDR_MENU1); SetMenu(&menu);
4、MFC中各种指针的获取 VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决。一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,无论是多文档还是单文档,都存在指针获取和操作问题。下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先一般获得本类(视,文档,对话框都支持)实例指针this,用this的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的 功能。 目录:
1) 在View中获得Doc指针 2) 在App中获得MainFrame指针 3) 在View中获得MainFrame指针 4) 获得View(已建立)指针 5) 获得当前文档指针 6) 获得状态栏与工具栏指针 7) 获得状态栏与工具栏变量 8) 在Mainframe获得菜单指针 9) 在任何类中获得应用程序类 10) 从文档类取得视图类的指针
1) 在View中获得Doc指针
CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文档。
2) 在App中获得MainFrame指针 CWinApp 中的 m_pMainWnd变量就是MainFrame的指针
也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
3) 在View中获得MainFrame指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
4) 获得View(已建立)指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; CyouView *pView=(CyouView *)pMain->GetActiveView();
5) 获得当前文档指针
CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();
6) 获得状态栏与工具栏指针
CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
7) 如果框架中加入工具栏和状态栏变量还可以这样 (CMainFrame *)GetParent()->m_wndToolBar; (CMainFrame *)GetParent()->m_wndStatusBar;
8) 在Mainframe获得菜单指针
CMenu *pMenu=m_pMainWnd->GetMenu();
9) 在任何类中获得应用程序类 用MFC全局函数AfxGetApp()获得。
10) 从文档类取得视图类的指针 从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。 CDocument类提供了两个函数用于视图类的定位: GetFirstViewPosition()和GetNextView() virtual POSITION GetFirstViewPosition() const; virtual CView* GetNextView(POSITION& rPosition) const;
5、MFC的文件操作 文件打开对话框类CFileDialoag和CFile文件类的使用
(1)、创建打开文件对话框: CFileDialog dlg(TRUE,//TRUE是创建打开文件对话框,FALSE则创建的是保存文件对话框 ".txt",//默认的打开文件的类型 NULL,//默认打开的文件名 OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,//打开只读文件 "文本文件(*.txt)|*.txt|所有文件 (*.*)|*.*||");//所有可以打开的文件类型 (2).点打开文件对话框上面的确定键后 if(dlg.DoModal()==IDOK) { CString m_FilePath = dlg.GetPathName();////////取出文件路径 CString m_path; m_path=m_FilePath;//将文件的路径放入m_path UpdateData(FALSE); } (3).打开文件: CFile File; File.Open(m_path,CFile::modeRead);
(4).逐行读取文件: CStdioFile File;///可以逐行读文件的类 CString strLine; while(File.ReadString(strLine)) //////将每行都放进strLine字符串里 { AfxMessgeBox(strLine); } (5)、判断读出来的字: strLine=“1|2|3|”;//要判断的字符串 int strIndex1 = strLine.Find('|');//在字符串中寻找“|” CString a[11]; if(-1 != strIndex1)//只要找到“|”就不会返回-1 { int i=0; while( -1 != strIndex1)// { strIndex1 = strLine.Find('|'); a[i] = strLine.Left(strIndex1); strLine = strLine.Right(strLine.GetLength() - strIndex1-1) ; i ; if (i > 10)//退出循环 break; } } }
6、VC获取本地当前时间 (1).自定义函数:void MyGetDateTime ( char * buff ) { WORD sYear,sMonth,sDay,sHour,sMinute,sSecond; SYSTEMTIME CurTime;/////定义SYSTEMTIME类的对象 GetLocalTime(&CurTime);////获取本地时间 sYear=CurTime.wYear;////获得年 sM.wMonth;//获得月 sDay=CurTime.wDay; sHour=CurTime.wHour; sMinute=CurTime.wMinute; sSec.wSecond; sprintf(buff,"%d,%d,%d,%d,%d,%d",sYear,sMonth,sDay,sHour,sMinute,sSecond);///将年月日时分秒放进buff里 } (2).调用时: char b[20]; MyGetDateTime(b);////数组名字其实就是指针
7、MFC文件对话框 打开多个文件 try { CString str("",10000);//这是做为存放打开文件名和路径的字符串空间10000这个值的设置就觉得有些不妥当 CFileDialog openfile(true,NULL,NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,"All Files(*.*)|*.*|",AfxGetMainWnd()); openfile.m_ofn.lpstrFile=str.GetBuffer(10000); openfile.m_ofn.nMaxFile=10000; openfile.m_ofn.lStructSize=sizeof(openfile.m_ofn); CString pathname("",MAX_PATH); CFileStatus status; openfile.DoModal();
POSITION mPos=openfile.GetStartPosition(); while(mPos!=NULL){ pathname=openfile.GetNextPathName(mPos); CFile::GetStatus(pathname,status); this->m_listresult.InsertItem(count ,pathname); //把包括路径在内的文件名写到一个list控件里 } } catch (CException* e) { AfxMessageBox(_T("打开文件出错了!")); e->Delete(); }
if (fileDialog.DoModal() == IDOK) { CString fileName;//=fileDialog.GetPathName(); //m_MediaPlayer.put_URL(fileName);
int m_countitem = m_ListCtrl.GetItemCount(); POSITION pos = fileDialog.GetStartPosition(); for (;pos != NULL;) { //CString m_FileName = fileDialog.GetFileName(); fileName = fileDialog.GetNextPathName(pos); //CString str="C:C:MyProjectmy.exe"; int npos=fileName.ReverseFind(''); CString m_FileName=fileName.Mid(npos 1); }
8、VS2005以上版本中CString转换成char数组的一个有效方法 使用API函数WideCharToMultiByte 例程如下: CString fileName; char strfileName[200] = {0};
WideCharToMultiByte(CP_ACP,0,(LPCTSTR)fileName,-1,strfileName,200,NULL,NULL);
9、遍历文件夹及其子文件夹 使用MFC提供的FileFind类FindFile/FileNextFile()等成员函数。 代码如下: void ScanFile(CString Dir) { CFileFind finder; CString Add=L"*"; CString DirSpec=Dir Add; //补全要遍历的文件夹的目录 BOOL bWorking = finder.FindFile(DirSpec);
while (bWorking) { bWorking = finder.FindNextFile(); if(!finder.IsDots()) //扫描到的不是节点 { if(finder.IsDirectory()) //扫描到的是文件夹 { CString strDirectory = finder.GetFilePath(); ScanFile(strDirectory); //递归调用ScanFile() } else //扫描到的是文件 { //CString strFile = finder.GetFilePath(); 得到文件的全路径 //进行一系列自定义操作 } } } finder.Close(); }
最后特别要感谢那些前辈们,谢谢你们的文章和代码,这让我学到了不少东西。
再推荐几个IT网站吧,我经常逛的。
CSDN:这个就不用我多说了吧。传说中最大的IT中文社区,资源和文章都不错,就是代码质量上可能差了点。
程序员联合开发网:http://www.pudn.com,最大的源码下载中文网站,唯一的难点就是要上传源代码或者资料后才能成为会员,代码质量总体来说比csdn要好。
如鹏网:http://www.rupeng.com,虽说是针对在校大学生的,但是有些东西还是比较好,注重基础。
http://www.codeforge.com:一个英文开放源代码分享网站,听说下载代码不要积分,注册即可。
http://www.codeproject.com/:一个英文网站,包括代码、问题解答之类的,个人感觉还不错。
http://www.javaeye.com/:一个Java学习的网站。
http://bbs.chinaunix.net:ChinaUnix学习社区 http://my.oschina.net:开源中国社区
但愿以上的网站对大家有帮助吧。