您是本帖第 121555 个阅读者     Refresh
论坛首页 - 汇编语言专区 - 用API写的录音机(C的代码改写)
 *贴子主题: 用API写的录音机(C的代码改写)保存该页为文件 显示可打印的版本 把本贴加入IE收藏夹
该用户目前不在线 pmason_rose::版主::
等级: 金牌会员
贴数: 84
积分: 202
来自: pmason_rose
头像:
查看pmason_rose的个人信息 pmason_rose的OICQ是332779423pmason_rose的OICQ是332779423
该贴包含一个附件但还在上传中,或者该附件已被用户中断上传请稍后...

;recode.asm
DEBUG equ 0
.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include masm32.inc
include winmm.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
includelib masm32.lib
includelib winmm.lib
;includelib lib.lib
;include lib.inc
;includelib libc.lib
include Comdlg32.inc
includelib Comdlg32.lib
;includelib MSVCRT.lib
include macros.inc
.data?
hInstance dd ?
dwDataLength dd ?
dwRepetitions dd ?
hWaveIn dd ?
hWaveOut dd ?
pBuffer1 dd ?
pBuffer2 dd ?
pSaveBuffer dd ?
pNewBuffer dd ?
pWaveHdr1 dd ?
pWaveHdr2 dd ?
h_File dd ?
waveform WAVEFORMATEX <>
bRecording db ?
bPlaying db ?
bReverse db ?
bPaused db ?
bEnding db ?
bTerminating db ?
szFileName         db        MAX_PATH dup (?)
.DATA
szOpenError db "Error opening waveform audio!",0
szMemError db "Error allocating memory!",0
szSave db "record1.wav",0
szNull db 0
szFilter           db      'Text Files(*.wav)',0,'*.wav',0
                   db      'All Files(*.*)',0,'*.*',0,0
szExtFilter db 'All Files(*.*)',0,'*.*',0,0,0,0
szDefExt           db      'wav',0
szDebug db "测试!",0
szbuffer db 100 dup (?)
szFormat db "%d",0
.const
ID_RECORD equ 101
IDC_RECORD_BEG                   equ 1000
IDC_RECORD_END                   equ 1001
IDC_RECORD_SAV equ 1002
IDC_PLAY_BEG                     equ 1003
IDC_PLAY_PAUSE                   equ 1004
IDC_PLAY_END                     equ 1005
IDC_PLAY_REV                     equ 1006
IDC_PLAY_REP                     equ 1007
IDC_PLAY_SPEED                   equ 1008
INP_BUFFER_SIZE equ 16384
.code
if DEBUG
include \masm32\debug\Debug.asm
endif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 创建保存文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SaveMemPCM proc uses ebx edi esi hwnd:HWND
LOCAL @waveformat:PCMWAVEFORMAT
LOCAL WaveHeaderSize,WaveFormatSize,AudioDataSize,WrittenBytes
LOCAL @NumToWrite,@dwNumber,@tmp
local  @stOF:OPENFILENAME
invoke RtlZeroMemory,addr @stOF,sizeof @stOF
mov    @stOF.lStructSize,sizeof @stOF
push   hwnd
pop    @stOF.hwndOwner
mov    @stOF.lpstrFilter,offset szFilter
mov    @stOF.lpstrFile,offset szFileName
mov    @stOF.nMaxFile,MAX_PATH
mov    @stOF.Flags,OFN_PATHMUSTEXIST
mov    @stOF.lpstrDefExt,offset szDefExt
mov    @stOF.lpstrTitle,offset szNull
invoke GetSaveFileName,addr @stOF
invoke CreateFile,addr szFileName,GENERIC_WRITE,\
FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
.if !eax
invoke MessageBox ,NULL,CTXT("哈,创建文件失败"),addr szNull,MB_OK
ret
.endif
mov h_File,eax
invoke WriteFile,h_File,CTXT("RIFF"),4,addr @NumToWrite,0
mov eax,dwDataLength
add eax,38
mov @tmp,eax
invoke WriteFile,h_File,addr @tmp,4,ADDR @NumToWrite,0
;一开始的八个字节是一个结构, 第一个 四字节 是标志,刚好等于 ascii 的 "RIFF" ,第二个四字节是总的文件长度减去8。
invoke WriteFile,h_File,CTXT("WAVE"),4,addr @NumToWrite,0
invoke WriteFile,h_File,CTXT("fmt "),4,addr @NumToWrite,0
mov eax,sizeof(WAVEFORMATEX )
MOV @tmp,eax
invoke WriteFile,h_File,addr @tmp,4,addr @NumToWrite,0
;跟着是第二个数据结构,占12个字节。如果你是标准的 wave 格式的文件,那么就是紧接着两个标志,第一个四字节的标志是 ascii 的 "WAVE" ,第二个 四字节的标志就是 ascii 的 "fmt "(注意,有一个空格),然后剩下的四字节里面藏的是 WAVEFORMATEX 结构的大小(参照MSDN),应该是18个字节。 
m2m @waveformat.wf.wFormatTag,waveform.wFormatTag
m2m @waveformat.wf.nChannels,waveform.nChannels
m2m @waveformat.wf.nSamplesPerSec,waveform.nSamplesPerSec
m2m @waveformat.wf.nAvgBytesPerSec,waveform.nAvgBytesPerSec
m2m @waveformat.wf.nBlockAlign,waveform.nBlockAlign
m2m @waveformat.wBitsPerSample,waveform.wBitsPerSample
invoke WriteFile,h_File,addr @waveformat,sizeof(WAVEFORMATEX),addr @NumToWrite,0
;然后,当然就是 18个字节的 WAVEFORMATEX 结构里面的值。详细的就不说了,自己查一下 MSDN。 (需要注意的是,这个 WAVEFORMATEXEX 的末一个成员,讲了可能的长度扩充) 
invoke WriteFile,h_File,CTXT("data"),4,addr @NumToWrite,0
m2m @dwNumber ,dwDataLength
invoke WriteFile,h_File,addr @dwNumber ,4,addr @NumToWrite,0
;在这 18 个字节后面 (按照旧时候的方法),应该是跟着一个8字节的结构的,然后就是 "裸数据" 的开始地址了,这八字节结构的开始四字节是标志,应该等于 ascii 的 "data",然后紧跟着的四字节就是裸数据的大小了,也就是最重要的部分。
invoke WriteFile,h_File,pSaveBuffer,dwDataLength,addr @NumToWrite,0
invoke SetEndOfFile,h_File 
invoke CloseHandle,h_File
ret
_SaveMemPCM endp
_ReverseMemory proc pBuffer, iLength

ret
_ReverseMemory endp
DlgProc proc uses ebx edi esi hwnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

mov eax,uMsg
.if eax==WM_INITDIALOG
mov dwRepetitions,1
invoke GlobalAlloc,GMEM_ZEROINIT,sizeof (WAVEHDR)
mov pWaveHdr1,eax
invoke GlobalAlloc,GMEM_ZEROINIT,sizeof (WAVEHDR)
mov pWaveHdr2,eax
invoke GlobalAlloc,GMEM_ZEROINIT,1
mov pSaveBuffer,eax
.elseif eax==WM_COMMAND
mov eax,wParam
.if ax==IDC_RECORD_BEG
invoke GlobalAlloc,GMEM_ZEROINIT,INP_BUFFER_SIZE
mov pBuffer1,eax
invoke GlobalAlloc,GMEM_ZEROINIT,INP_BUFFER_SIZE
mov pBuffer2,eax
.if (!pBuffer1 || !pBuffer2)
.if (pBuffer1)
invoke GlobalFree,pBuffer1
.endif
.if (pBuffer2)
invoke GlobalFree,pBuffer2
.endif
invoke MessageBeep,MB_ICONEXCLAMATION
invoke MessageBox ,hwnd,addr szMemError,addr szNull,MB_OK
.endif
mov waveform.wFormatTag,WAVE_FORMAT_PCM
mov waveform.nChannels,1
mov waveform.nSamplesPerSec,11025
mov waveform.nAvgBytesPerSec,11025
mov waveform.nBlockAlign,1
mov waveform.wBitsPerSample,8
mov waveform.cbSize,0
invoke waveInOpen,addr hWaveIn,WAVE_MAPPER,addr waveform,hwnd,0,CALLBACK_WINDOW
.if eax
invoke GlobalFree,pBuffer1
invoke GlobalFree,pBuffer2
invoke MessageBox,hwnd,addr szOpenError,addr szNull, MB_OK
.endif
assume edi:ptr WAVEHDR
mov edi ,pWaveHdr1
mov eax ,pBuffer1 
mov [edi].lpData ,eax
mov eax,INP_BUFFER_SIZE
mov [edi].dwBufferLength ,eax 
mov [edi].dwBytesRecorded ,0 ;
mov [edi].dwUser ,0 ;
mov [edi].dwFlags  ,0 ;
mov [edi].dwLoops ,1 ;
mov [edi].lpNext ,NULL ;
mov [edi].Reserved ,0 ;
invoke waveInPrepareHeader,hWaveIn,pWaveHdr1, sizeof (WAVEHDR)
mov edi ,pWaveHdr2
mov eax ,pBuffer2
mov [edi].lpData ,eax
mov eax,INP_BUFFER_SIZE
mov [edi].dwBufferLength ,eax 
mov [edi].dwBytesRecorded ,0 ;
mov [edi].dwUser ,0 ;
mov [edi].dwFlags  ,0 ;
mov [edi].dwLoops ,1 ;
mov [edi].lpNext ,NULL ;
mov [edi].Reserved ,0 ;
invoke waveInPrepareHeader,hWaveIn,pWaveHdr2, sizeof (WAVEHDR)
assume edi: nothing 
.elseif ax==IDC_RECORD_END
mov bEnding,TRUE
invoke waveInReset,hWaveIn
.elseif ax==IDC_PLAY_BEG
mov waveform.wFormatTag,WAVE_FORMAT_PCM
mov waveform.nChannels,1
mov waveform.nSamplesPerSec,11025
mov waveform.nAvgBytesPerSec,11025
mov waveform.nBlockAlign,1
mov waveform.wBitsPerSample,8
mov waveform.cbSize,0
invoke waveOutOpen,addr hWaveOut,WAVE_MAPPER,addr waveform,hwnd,0,CALLBACK_WINDOW
.if eax
invoke GlobalFree,pBuffer1
invoke GlobalFree,pBuffer2
invoke MessageBox,hwnd,addr szOpenError,addr szNull, MB_OK
.endif
.elseif ax==IDC_PLAY_PAUSE
.if (!bPaused)
invoke waveOutPause,hWaveOut ;
invoke SetDlgItemText,hwnd, IDC_PLAY_PAUSE, CTXT ("Resume") ;
mov bPaused,TRUE
.else
invoke waveOutRestart,hWaveOut;
invoke SetDlgItemText,hwnd, IDC_PLAY_PAUSE, CTXT ("Pause");
mov bPaused,FALSE ;
.endif
.elseif ax==IDC_PLAY_END
mov bEnding,TRUE ;
invoke waveOutReset,hWaveOut;
.elseif ax==IDC_PLAY_REV
mov bReverse , TRUE ;
                invoke _ReverseMemory,pSaveBuffer, dwDataLength;
invoke SendMessage,hwnd, WM_COMMAND, IDC_PLAY_BEG, 0
.elseif ax==IDC_PLAY_REP
mov dwRepetitions,-1 ;
invoke SendMessage,hwnd, WM_COMMAND, IDC_PLAY_BEG, 0;
.elseif ax==IDC_PLAY_SPEED
mov waveform.wFormatTag,WAVE_FORMAT_PCM
mov waveform.nChannels,1
mov waveform.nSamplesPerSec,22050
mov waveform.nAvgBytesPerSec,22050
mov waveform.nBlockAlign,1
mov waveform.wBitsPerSample,8
mov waveform.cbSize,0
invoke waveOutOpen,addr hWaveOut,WAVE_MAPPER,addr waveform,hwnd,0,CALLBACK_WINDOW
.if eax
invoke MessageBox ,hwnd,addr szOpenError,addr szNull,MB_OK
.endif
.elseif ax==IDC_RECORD_SAV
invoke _SaveMemPCM,hwnd
.endif
.elseif eax==MM_WIM_OPEN
invoke GlobalReAlloc,pSaveBuffer,1,GMEM_MOVEABLE
invoke GetDlgItem ,hwnd, IDC_RECORD_BEG
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_RECORD_END
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_BEG
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_PAUSE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_END
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_REV
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_REP
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_SPEED
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_RECORD_SAV
invoke EnableWindow,eax,FALSE

invoke GetDlgItem ,hwnd, IDC_RECORD_END
invoke SetFocus,eax
invoke waveInAddBuffer,hWaveIn, pWaveHdr1, sizeof (WAVEHDR)
invoke waveInAddBuffer,hWaveIn, pWaveHdr2, sizeof (WAVEHDR)
            mov bRecording, TRUE ;
mov bEnding,FALSE ;
mov dwDataLength,0 ;
invoke waveInStart,hWaveIn
  .elseif eax==MM_WIM_DATA
assume edi : ptr WAVEHDR
mov edi,lParam
mov eax,[edi].dwBytesRecorded
add eax,dwDataLength 
invoke GlobalReAlloc,pSaveBuffer,eax,GMEM_MOVEABLE
mov pNewBuffer,eax
.if (pNewBuffer == NULL)
invoke waveInClose,hWaveIn
invoke MessageBox,NULL,addr szMemError, addr szNull,MB_OK
mov eax,TRUE
ret
.endif
push pNewBuffer
pop pSaveBuffer
mov edi,lParam
mov eax,pSaveBuffer
add eax,dwDataLength
;MemCopy proc public uses esi edi Source:PTR BYTE,Dest:PTR BYTE,ln:DWORD
invoke MemCopy,[edi].lpData,eax,[edi].dwBytesRecorded
mov eax,dwDataLength
mov ecx,[edi].dwBytesRecorded
add eax,ecx
mov dwDataLength,eax
.if (bEnding)
invoke waveInClose,hWaveIn
mov eax,TRUE
ret
.endif
invoke waveInAddBuffer,hWaveIn,lParam, sizeof (WAVEHDR) ;
assume edi : nothing
.elseif eax==MM_WIM_CLOSE
invoke waveInUnprepareHeader,hWaveIn, pWaveHdr1, sizeof (WAVEHDR)
invoke waveInUnprepareHeader ,hWaveIn, pWaveHdr2, sizeof (WAVEHDR);
invoke GlobalFree ,pBuffer1
invoke GlobalFree ,pBuffer2
invoke GetDlgItem ,hwnd, IDC_RECORD_BEG
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_RECORD_END
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_RECORD_BEG
invoke SetFocus,eax
.if (dwDataLength > 0)
invoke GetDlgItem ,hwnd, IDC_PLAY_BEG
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_PAUSE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_END
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_REV
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_REP
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_SPEED
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_RECORD_SAV
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_RECORD_BEG
invoke SetFocus,eax
.endif
mov bRecording , FALSE ;
.if (bTerminating)
invoke SendMessage ,hwnd, WM_SYSCOMMAND, SC_CLOSE, NULL
.endif
.elseif eax==MM_WOM_OPEN
invoke GetDlgItem ,hwnd, IDC_RECORD_BEG
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_RECORD_END
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_BEG
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_PAUSE
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_END
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_REV
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_REP
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_SPEED
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_RECORD_SAV
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_RECORD_END
invoke SetFocus,eax

assume edi:ptr WAVEHDR
mov edi ,pWaveHdr1
m2m [edi].lpData,pSaveBuffer
m2m [edi].dwBufferLength,dwDataLength
mov [edi].dwBytesRecorded ,0 ;
mov [edi].dwUser,0 ;
mov [edi].dwFlags,WHDR_BEGINLOOP or WHDR_ENDLOOP 
m2m [edi].dwLoops,dwRepetitions
mov [edi].lpNext,NULL ;
mov [edi].Reserved,0 ;
assume edi: nothing 
invoke waveOutPrepareHeader,hWaveOut, pWaveHdr1, sizeof (WAVEHDR)
invoke waveOutWrite,hWaveOut, pWaveHdr1, sizeof (WAVEHDR)
            mov bPlaying, TRUE ;
mov bEnding,FALSE ;
  .elseif eax==MM_WOM_DONE
invoke waveOutUnprepareHeader ,hWaveOut, pWaveHdr1, sizeof (WAVEHDR)
        invoke waveOutClose,hWaveOut
.elseif eax==MM_WOM_CLOSE
invoke GetDlgItem ,hwnd, IDC_RECORD_BEG
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_RECORD_END
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_BEG
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_PAUSE
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_END
invoke EnableWindow,eax,FALSE
invoke GetDlgItem ,hwnd, IDC_PLAY_REV
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_REP
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_SPEED
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_RECORD_SAV
invoke EnableWindow,eax,TRUE
invoke GetDlgItem ,hwnd, IDC_PLAY_BEG
invoke SetFocus,eax
invoke SetDlgItemText,hwnd, IDC_PLAY_PAUSE, CTXT ("Pause") ;
mov bPaused,FALSE ;
mov dwRepetitions , 1 ;
mov bPlaying , FALSE ;
.if (bReverse)
invoke _ReverseMemory ,pSaveBuffer, dwDataLength
mov bReverse,FALSE ;
.endif
.if (bTerminating)
invoke SendMessage,hwnd, WM_SYSCOMMAND, SC_CLOSE, NULL
  .endif
.elseif eax==WM_CLOSE
.if (bRecording)
mov bTerminating ,TRUE
mov bEnding , TRUE
invoke waveInReset ,hWaveIn
.endif
.if (bPlaying)
mov bTerminating ,TRUE
mov bEnding , TRUE
invoke waveOutReset,hWaveOut
.endif
invoke GlobalFree,pWaveHdr1
invoke GlobalFree,pWaveHdr2
invoke GlobalFree,pSaveBuffer
invoke EndDialog,hwnd,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret

DlgProc endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,ID_RECORD,NULL,addr DlgProc,NULL
invoke ExitProcess,0
end start
;record.rc
//Microsoft Developer Studio generated resource script.
#include "e:\masm32\include\resource.h"
#define  ID_RECORD                   101
#define  IDC_RECORD_BEG                   1000
#define  IDC_RECORD_END                   1001
#define  IDC_RECORD_SAV 1002
#define  IDC_PLAY_BEG                     1003
#define  IDC_PLAY_PAUSE                   1004
#define  IDC_PLAY_END                     1005
#define  IDC_PLAY_REV                     1006
#define  IDC_PLAY_REP                     1007
#define  IDC_PLAY_SPEED                   1008
#define ICO_MAIN                        0x1000
4096                    ICON    DISCARDABLE     "Main.ico"
ID_RECORD  DIALOG DISCARDABLE  100, 100, 152, 74
STYLE  WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION  "Waveform Audio Recorder"
FONT 8,  "MS Sans Serif"
BEGIN
     PUSHBUTTON       "录音",IDC_RECORD_BEG,8,8,40,14
     PUSHBUTTON       "停止",IDC_RECORD_END,56,8,40,14,WS_DISABLED
     PUSHBUTTON       "播放",IDC_PLAY_BEG,8,30,40,14,WS_DISABLED
     PUSHBUTTON       "暂停",IDC_PLAY_PAUSE,56,30,40,14,WS_DISABLED
     PUSHBUTTON       "停止",IDC_PLAY_END,104,30,40,14,WS_DISABLED
     PUSHBUTTON       "反向",IDC_PLAY_REV,8,52,40,14,WS_DISABLED
     PUSHBUTTON       "重复",IDC_PLAY_REP,56,52,40,14,WS_DISABLED
     PUSHBUTTON       "加速",IDC_PLAY_SPEED,104,52,40,14,WS_DISABLED
     PUSHBUTTON       "保存",IDC_RECORD_SAV,104,8,40,14,WS_DISABLED
END
 


[该贴于2006-1-31 23:35:26被pmason_rose编辑过]


[该贴于2006-2-1 0:47:57被pmason_rose编辑过]


发贴时间:2006-1-22 0:00:13IP:61.183.*.*
该用户目前不在线 pmason_rose::版主::
等级: 金牌会员
贴数: 84
积分: 202
来自: pmason_rose
头像:
查看pmason_rose的个人信息 pmason_rose的OICQ是332779423pmason_rose的OICQ是332779423
请大家测试测试,如有问题请回贴

发贴时间:2006-1-31 23:36:34IP:61.183.*.*
第1页
√ 快速回复  
回复主题 用API写的录音机(C的代码改写)
输入用户名和密码: 用户名: 您没有注册?  密码: 忘记密码?
内容





上海市浦东新区蔡伦路1200号37号信箱 
(021)51322112   13381636626(短信)
Email联系方式