版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、音乐播放器音乐播放器1 问题定义和可行性研究 2( 1) 问题定义 2( 2)可行性研究 32 需求分析 31 功能需求 31.1 功能描述 32 性能需求 43 将来可能提出的要求 44 项目描述 54.1 编写目的 54.2 项目背景 54.3 开发工具及环境简介 63 概要设计和详细设计 63.1 概要设计 63.2 详细设计 73.3 音乐编码设计 75 主界面界面介绍 86 系统的实现 11一、主要的对话框 11二、全局变量 12三、初始化函数 12三、播放、暂停功能 15四、添加文件到播放列表 18五、下一首 上一首 20六、停止播放 21七、播放模式 21八、显示时间和播放进度
2、22九、删除歌曲 235.2 单元测试 25266.总结1 问题定义和可行性研究本章分为两部分, 问题定义和可行性研究。 问题定义阶段主要研究我们所学的知识能做 什么项目,而可行性研究给出了制作音乐播放器的可行性。( 1) 问题定义通过开发音乐播放器,来练习本学期软件工程课程所学知识。熟 悉软件开发的各个阶段, 将书本上的知识与实践性的开发活动联系起 来。实现音乐播放器基本的功能。2)可行性研究大一的时候已经学过了基本的 C+ 编程的知识,在这个基础上, 有三个星期的时间来学习 MFC 编程,学习文件的读写操作,以及系 统 API 函数调用等知识。边学边用,具备开发软件的能力。2 需求分析本章
3、给出了音乐播放器应该具备的功能, 并给出了功能示意图, 最后提出了实现该播放 器应该具备的条件。1 功能需求1.1 功能描述本播放器主要有如下功能: 1.对文件进行操作。 2.对按钮的处理1. 对文件的操作通过文件的读写知识, 实现浏览目录以选择文件, 添加歌曲到播 放列表,删除播放列表中的歌曲, 对已经选中的文件进行播放、 暂停, 以及通过双击播放列表中的歌曲来播放文件。2. 对控件的处理 对各种按钮添加了事件响应函数,可以处理基本的播放,暂停, 上一首 /下一首,删除,选择播放模式等操作。功能如下图:音乐播放器HIT控件文件操作进度条?s放暂停上下-首播放模式列疵框文件打JF文件添加2性能
4、需求本项目是一个普通的音乐播放器,运行环境为VS2010,项目运行速率正常,可以满足用户需求。1. 时间性能要求:越低越好。2. 便捷性:运用了可视化编程,更有助于人机交互,更人性化。程序的运行,符合正常的操作习惯,程序功能明了简洁!3将来可能提出的要求(1) 歌曲列表的保存(2) 菜单操作(3) 更换背景图片(4) 提供网络下载功能:支持通过歌名和歌手名进行歌曲检索和下载功能;(5) 支持歌词显示和同步播放;(6) 支持歌曲在线播放;(7) 支持更友好的歌曲检索和下载功能;(8) 提供更良好的操作界面。4 项目描述4.1 编写目的设计一个基于 windows 平台的音乐点播系统, 实现音乐库
5、的管理 以及播放功能。音乐播放器能够满足音乐的播放功能, 实现一款播放器的基本功 能。4.2 项目背景本项目作为软件课程设计课程的训练项目提出,在基本的设 计实现基础上, 将不断对已有的设计进行进一步的修改和完善, 最终 完成整个软件开发过程。 本次项目的旨在通过不同软件工程设计方法 与技术的实践,了解和掌握各种技术、工具平台的特点与局限性,体 会协同开发方式。第 1 阶段:主要目的是通过对项目需求的分析和理解, 通过面向对象 的设计方式完成项目前期的准备工作。第 2 阶段:我们会根据既定需求,完善设计模式。第3阶段:在设计文档和需求分析的文档下,完成音乐点播系统原型 的开发,并完成整个开发流
6、程的测试报告第4阶段:通过音乐点播系统软件的设计开发,了解软件文档的编写 原则,训练掌握软件各类文档写作的技巧, 同时在文档的编写过程中 提高和增加C+开发的能力和经验。4.3开发工具及环境简介操作系统:windows xp或以上版本C+ 6.0: Visual C+是一个功能强大的可视化软件开发工具。自1993 年Microsoft公司推出Visual C+1.0后,随着其新版本的不断问世, Visual C+已成为专业程序员进行软件开发的首选工具。Microsoft Office Word 2003 :经典办公软件,本项目中用于编写文档。3概要设计和详细设计3.1概要设计通过这个阶段的工作
7、将划分出组成系统的物理元素程序,文件和文档等,但是每个物理元素仍然处于黑盒子级,这些黑盒子里的具体内容将在以后仔细设计。总体设计的另一项重要任务是设计软件 的结构,也就是要确定该软件由哪些模块组成的,以及这些模块之间的关系。运用传统软件工程方法学的知识将音乐播放器软件的开发分成:一、MFC 的使用以及实现方法二、文件的读写操作三、系统 API 函数的调用3.2 详细设计根据概要设计所划分的四个模块, 该阶段应详细地完成这四个模 块的任务:一、MFC 的实现通过 MFC 窗口以及函数的使用,创建出播放器的主界面,主界 面应包括文件的打开、添加、播放以及线程按键。另外,还要各种函 数应该实现相应组
8、件上的各种事件。二、文件读写操作的实现通过以前的学过的文件读写操作知识, 实现对音乐文件的读以及 写操作。三、系统 API 函数的调用通过调用系统媒体控制接口函数实现对 mp3,wav,wma 等格式的 音乐的播放的功能。3.3 音乐编码设计一、编码原理1. 音乐的十二平均率规定(1) 每两个八度音之间的频率相差一倍。(2) 两个八度音之间又可以分为十二个伴音,每两个伴音的频率比为 1.059463。低音6 (音名A)的频率是440Hz,音名B到C之间、E到F之 间为伴音,其余为全音。2. 乐谱编码选取 65536Hz 为基准频率,以此频率分频得到简谱高音各音调的分 频比。计算公式为 N=65
9、536/f。二、编码参照为了让 ROM 能够识别各音频的分频系数, 需将个音频分频系数 按照一定格式转换成十六进制格式。我们采用 8 位的 ROM , D6D5 位表示高中低音,如表 1-2所示, 11为高音, 10为中音, 01为低音; 用 D4D3D2D1D0 位表示分频系数,将表 1-1 的分频系数转换成二进 制格式表示; ROM 的高位全部补 0。然后转换成十六进制如表 1-2 所示。之所以采用高音分频比的二分之一为基准分频系数,是因为 ROM 的位宽限制,而每两个八度音频率相差一倍,所以我们后面用 译码器译成各音频的分频系数输出给分频器, 这样由分频器输出到扬 声器,扬声器就可发声了
10、。5 主界面界面介绍1、界面图:X2添加歌曲按钮添加歌曲3、删除歌曲按钮mPToTA>4、音量的变大变小按钮6、下一首歌按钮8停止播放按钮9、播放按钮10、单曲播放/随机播放/顺序播放按钮11、空白部分为歌曲的菜单列表6 系统的实现一、主要的对话框class CMCIPlayerDlg : public CDialogEx/ 构造public:CMCIPlayerDlg(CWnd* pParent = NULL); / 标准构造函数 / 对话框数据enum IDD = IDD_MCIPLAYER_DIALOG ;protected:virtual void DoDataExchange(
11、CDataExchange* pDX);/DDX/DDV 支持/ 实现protected:HICON m_hIcon;/ 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()public:/ 列表CListBox m_list;afx_msg void OnBnClickedOnstart();afx_msg voi
12、d OnBnClickedOnloadmusic();void load(music a);int isplay;int index;CSliderCtrl volume;afx_msg void OnNMCustomdrawVolun(NMHDR *pNMHDR, LRESULT*pResult);afx_msg void OnBnClickedOnnext();afx_msg void OnBnClickedOnper();afx_msg void OnBnClickedOnstop();LRESULT OnMciNotify(WPARAM wParam, LPARAM lParam);/
13、 设置播放模式 afx_msg void OnBnClickedOrder(); afx_msg void OnLbnDblClk(); void OnTimer(UINT nIDEvent);/ 进度条 CSliderCtrl m_progress; afx_msg DWORD getinfo(DWORD item); afx_msg void OnBnClickedDeletemusic();二、全局变量struct musicstring name; string mPath;int m_max;/ 进度条的最大位置变量int hour,minute,second; / 时间变量:小时、
14、分钟、秒钟 DWORD cdlen;/ 某个音频文件的总时间长度 DWORD m_count;/ 设备型号DWORD cdfrom,cdto;/ 歌曲的起点和终点 DWORD DeviceID;list<music> mus;/ 全局歌曲链表 vector<CString> allpath;/ 保存已有的歌三、初始化函数BOOL CMCIPlayerDlg:OnInitDialog() CDialogEx:OnInitDialog();/ 将“关于 .”菜单项添加到系统菜单中。 /volume.SetBkColor(RGB(37,38,37);HBITMAPhBitma
15、p;hBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP4);(CButton *)GetDlgItem(IDC_ONSTART)->SetBitmap(hBitmap);hBitmap = LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP1);(CButton *)GetDlgItem(IDC_ONPER)->SetBitmap(hBitmap);hBitmap = LoadBitmap(AfxGetInstanceHa
16、ndle(), MAKEINTRESOURCE(IDB_BITMAP2);(CButton *)GetDlgItem(IDC_ONNEXT)->SetBitmap(hBitmap);hBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP5);(CButton *)GetDlgItem(IDC_ONSTOP)->SetBitmap(hBitmap);hBitmap = LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP7);(C
17、Button *)GetDlgItem(IDC_ORDER)->SetBitmap(hBitmap);SetBackgroundImage(IDB_BITMAP6,BACKGR_TILE,NULL);isplay=0;/ 未播放状态index=-1;m_list.SetCurSel(0);/ 设置初始选择位置 volume.SetRange(0,1000);/ 滑块的移动范围 01000volume.SetPos(500);滑块指针的初始位置设为500代表初始音量为 50ifstream rin;/导入原先数据rin.open("Mylist.txt");/int r
18、ere;string str2; if(rin>>setw(50)>>str0>>setw(150)>>str1) while(!rin.eof()music mu;=str0;mu.mPath=str1;CString name;for(int i=0;i<.length();i+)if(i='/') i=' 'name=.c_str();CString mPath;for(int i=0;i<mu.mPath.length();i
19、+)if(mu.mPathi='/') mu.mPathi=' 'mPath=mu.mPath.c_str();int j=m_list.GetCount(); / 把名字和地址插入到 list 控件m_list.InsertString(j,name);/CString *p=&mPath;allpath.push_back(mPath);rin>>str0>>str1;rin.close();/ IDM_ABOUTBOX 必须在系统命令范围内。ASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_AB
20、OUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL)BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid);if (!strAboutMenu.IsEmpty() pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu
21、(MF_STRING ,IDM_ABOUTBOX, strAboutMenu);/ 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将 自动/ 执行此操作SetIcon(m_hIcon, TRUE); / 设置大图标SetIcon(m_hIcon, FALSE); / 设置小图标/ TODO: 在此添加额外的初始化代码return TRUE; / 除非将焦点设置到控件,否则返回 TRUE三、播放、暂停功能void CMCIPlayerDlg:OnBnClickedOnstart()/ 开始播放/ TODO: 在此添加控件通知处理程序代码if(isplay=0)/ TODO: 在此添加控件
22、通知处理程序代码 if(m_list.GetCurSel()=-1)/ 判断有没有歌曲被选中 ,若没有,则从第一首开始播放 -1 代表没有被选中 m_list.SetCurSel(0);if(m_list.GetCurSel()=index)SetTimer(0,1000,NULL); mciSendCommand(DeviceID,MCI_RESUME,0,0); HBITMAP hBitmap;hBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP3);(CButton *)GetDlgItem(IDC
23、_ONSTART)->SetBitmap(hBitmap); SetDlgItemText(IDC_ONSTART," 暂停 ");isplay=1;elseindex = m_list.GetCurSel();CString data;/m_list.GetDlgItemTextA(index,data);/CString c=datMCI_OPEN_PARMS mciopenparms;/ 打开 MCI_PLAY_PARMS mciplayparms;/ 播放 second=0;minute=0;hour=0;mciopenparms.lpstrElementNa
24、me=allpathindex;/ 将音乐文件路径传给设备DWORD dwReturn; if(dwReturn=mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_ELEMENT|MCI_WAIT,(DWORD)(LPVOID)&mciopenparms) /如果打开文件失败,则将出错信息储存在buffer ,并显示出错警告char buffer256; mciGetErrorString(dwReturn,buffer,256);MessageBox(buffer," 出错警告 !",MB_ICONHAND|MB_ICONERROR|MB
25、_ICONSTOP);DeviceID=mciopenparms.wDeviceID;mciopenparms.lpstrDeviceType=NULL;/ 文件类型 m_count=mciopenparms.wDeviceID;/ 多媒体设备类型编号mciplayparms.dwFrom=0;/ 每次播放都是从 0 开始播放HWND hwnd = GetSafeHwnd(); mciplayparms.dwCallback = (DWORD)hwnd; cdlen=getinfo(MCI_STA TUS_LENGTH);CString stime;CClientDC dc(this); dc
26、.SetBkColor(RGB(255,255,255);/ 设置放置计数器区域的外观 dc.SetTextColor(RGB(95,180,66);stime.Format("%02d:%02d:%02d",cdlen/3600000,(cdlen%3600000)/60000,(cdlen%3600000)%60000)/1000);/ 显示时间进度 dc.TextOut(328,13,stime);mciSendCommand(DeviceID,MCI_PLAY ,/*MCI_FROM|*/MCI_NOTIFY,(DWORD)(LPVOID)&mciplayp
27、arms);SetTimer(0,1000,NULL);/ 设置系统计数器,显示歌曲播放的进度HBITMAP hBitmap; hBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP3);(CButton *)GetDlgItem(IDC_ONSTART)->SetBitmap(hBitmap);SetDlgItemText(IDC_ONSTART," 暂停 "); isplay=1;elseKillTimer(0); mciSendCommand(DeviceID,MCI_PAU
28、SE,0,0);HBITMAP hBitmap; hBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP4);(CButton *)GetDlgItem(IDC_ONSTART)->SetBitmap(hBitmap);SetDlgItemText(IDC_ONSTART," 播放 "); isplay=0;四、添加文件到播放列表void CMCIPlayerDlg:OnBnClickedOnloadmusic()/ 导入歌曲 / TODO: 在此添加控件通知处理程序代码CFile
29、Dialog dlg(TRUE, _T("*.*"), NULL,OFN_FILEMUSTEXIST | OFN_PA THMUSTEXIST | OFN_HIDEREADONL Y,_T("mp3 文件 (*.mp3)|*.mp3|""wma 文件 (*.wma)|*.wma|""wav 文件 (*.wav)|*.wav|""所有文件 (*.*)|*.*|"), NULL );/ 选项图片的约定dlg.m_ofn.lpstrTitle = _T(" 打开音乐文件 ");/
30、打开文件对话框的标题名if( dlg.DoModal() != IDOK )/ 判断是否获得图片return;CString mPath = dlg.GetPathName(); / 获取音乐路径 CString mmpath=mPath;allpath.push_back(mPath);int i = mPath.ReverseFind(''); / 从磁盘地址中获取歌曲名字CString name;name = mPath.Right(mPath.GetLength()-1-mPath.ReverseFind('');int j=m_list.GetCoun
31、t(); / 把名字和地址插入到 list 控件 m_list.InsertString(j,name);/m_shelllist.SetItemText(j,0,name);music mu;=name.GetBuffer();mu.mPath=mPath.GetBuffer(); load(mu);void CMCIPlayerDlg:load(music a)list<music> mus;ifstream rin;rin.open("Mylist.txt");/int rere;string str2;if(rin>>str0&
32、gt;>str1) while(!rin.eof()music mu;=str0;mu.mPath=str1;if(!=) mus.push_back(mu);elseMessageBox(" 已经有该歌曲 "); return;rin>>str0>>str1;rin.close();for(int i=0;i<.length();i+)/ 把名字里面的空格变为 '_'if(i=' ')i='/'for(int i=
33、0;i<a.mPath.length();i+)/把地址里面的空格变为 '*'if(a.mPathi=' ')a.mPathi='/'mus.push_back(a);ofstream out("Mylist.txt"); list<music>:iterator it=mus.begin();while(it!=mus.end()out<<left<<setw(50)<<(*it).name<<" "<<setw(150)<
34、;< (*it).mPath<<endl;it+;out.close();五、下一首 上一首void CMCIPlayerDlg:OnBnClickedOnnext()/ 下一首/ TODO: 在此添加控件通知处理程序代码KillTimer(0); second=0;minute=0;hour=0;mciSendCommand(DeviceID,MCI_CLOSE,0,0);/ 在加载文件前先清空 上一次播放的设备isplay=0;index = m_list.GetCurSel();if(index+1=m_list.GetCount()m_list.SetCurSel(0
35、);elsem_list.SetCurSel(index+1);OnBnClickedOnstart();isplay=1;void CMCIPlayerDlg:OnBnClickedOnper()/ 上一首/ TODO: 在此添加控件通知处理程序代码KillTimer(0); second=0;minute=0;hour=0;mciSendCommand(DeviceID,MCI_CLOSE,0,0);/ 在加载文件前先清空 上一次播放的设备isplay=0;index = m_list.GetCurSel(); if(index=0) m_list.SetCurSel(m_list.Get
36、Count()-1);else m_list.SetCurSel(index-1);OnBnClickedOnstart();isplay=1;六、停止播放void CMCIPlayerDlg:OnBnClickedOnstop()/ 停止/ TODO: 在此添加控件通知处理程序代码KillTimer(0); second=0;minute=0;hour=0;mciSendCommand(DeviceID,MCI_CLOSE,0,0);/ 在加载文件前先清空 上一次播放的设备isplay=0;SetDlgItemText(IDC_ONSTART," 播放 ");HBITMA
37、P hBitmap; hBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP4);(CButton *)GetDlgItem(IDC_ONSTART)->SetBitmap(hBitmap);index=-1; UpdateData(false);七、播放模式void CMCIPlayerDlg:OnBnClickedOrder()/ 设置播放模式/ TODO: 在此添加控件通知处理程序代码CString pattern;GetDlgItemText(IDC_ORDER,pattern);if(pat
38、tern=" 顺序 ")SetDlgItemText(IDC_ORDER," 随机 ");HBITMAP hBitmap;hBitmap = LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP8);(CButton *)GetDlgItem(IDC_ORDER)->SetBitmap(hBitmap); if(pattern=" 随机 ")SetDlgItemText(IDC_ORDER," 单曲 ");HBITMAP hBitmap;hB
39、itmap = LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP9);(CButton *)GetDlgItem(IDC_ORDER)->SetBitmap(hBitmap); if(pattern=" 单曲 ")SetDlgItemText(IDC_ORDER," 顺序 ");HBITMAP hBitmap;hBitmap = LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP7);(CButton *)G
40、etDlgItem(IDC_ORDER)->SetBitmap(hBitmap); 八、显示时间和播放进度void CMCIPlayerDlg:OnTimer(UINT nIDEvent) CString stime;second+;CClientDC dc(this);dc.SetBkColor(RGB(255,255,255);/ 设置放置计数器区域的外观 dc.SetTextColor(RGB(95,180,66);if(second=60)/ 设置钟表的显示minute+;second=0;if(minute=60)hour+;minute=0; if(hour=24) hour
41、=0;stime.Format("%02d:%02d:%02d",hour,minute,second);/ 显示时间 进度dc.TextOut(68,13,stime);m_progress.SetRa nge(O,cdle n);使进度条的范围与歌曲时间一致UpdateData(false);m_max=cdfrom;保存歌曲的当前位置信息if(m_max!=cdlen)/ 如果歌曲结束,则进度条重新置 0 m_progress.SetPos(cdfrom); else m_progress.SetPos(0);m_max=0;OnBnClickedOnstop();D
42、WORD cdf=getinfo(MCI_STA TUS_POSITION);cdfrom=MCI_MAKE_MSF(MCI_MSF_MINUTE(cdf),MCI_MSF_SECOND(cdf),MCI_MSF_FRAME(cdf);/ 获取当前播放文件的信息UpdateData(false);CDialog:OnTimer(nIDEvent);九、删除歌曲void CMCIPlayerDlg:OnBnClickedDeletemusic()/ 删除歌曲/ TODO: 在此添加控件通知处理程序代码if(m_list.GetCurSel()=-1)MessageBox("请选中要删除的歌曲”);elseCString na;int i=m_list.GetCurSel();na=allpathi;allpath.erase(allpath.begin()+i);m_list.DeleteString(i); UpdateData(false);string pa=na.G
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024全球教育改革:跨文化交流与合作
- 2024年《大小多少》课件:解读数字与尺寸的奥秘
- 学习PCCAD教程打造2024年工程高手之路
- 风力发电设备可靠性及安全运行问题分析
- 《证券投资实务》第7章教案
- 白公鹅音乐表演:2024年跨界艺术合作案例
- 小学英语口语训练材料
- 2024年《先进制造技术》教案:课程思政与创新创业教育融合
- 11.4串联电路和并联电路-【新教材】人教版(2019)人教版高中物理必修第三册练习
- 2教案创新:2024年海洋化学资源的教学活动设计
- 音乐教师述职报告
- 英语语法入门笔记(崔荣容-)(共43页)
- LS风险矩阵评价准则(3页)
- 机房维护表格-运维部
- 安全标识中英文可直接打印
- 小学四年级上册音乐-第8课《龙里格龙》--人音版(简谱)(19张)ppt课件
- 1π到100π表比较全
- 高中常用不规则动词表(含音标)
- 初中知识结构图
- 中医医疗技术操作规范
- ASTM_A29/A29M热锻及冷加工碳素钢和合金钢棒
评论
0/150
提交评论