|
|
来自: http://social.msdn.microsoft.com ... 9-a8c9-2e27eb9ec0589 c) w7 E) c/ }3 [* U
By Mukta & ToxicDream- 2 H2 d8 @2 a0 t: l
- //for delphi 5
! P% S- K- c4 O' o/ x - unit MMDevApi_tlb;1 T' f# n; W) B n, \1 ]8 m/ w
7 }% ]3 d$ ]+ `( R8 y* x* Y% P% H- interface7 ?* V0 a0 G; z
- uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;
- w" ]8 d2 }* q - const, H4 t8 s9 Y" b/ m+ n" ?0 h" ?
- // TypeLibrary Major and minor versions# T( B# e$ ?( {% t
& J8 X* ]1 T2 _" ?- CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';8 ?* l5 _, y2 T" [' R8 [
- IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';: y3 }6 j( G2 O) l1 Q0 w
- IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';) x0 n* j5 d4 q: P
- IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
/ }' w) e5 C$ ]5 l* d7 t8 f - IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';7 z7 I& A* a3 U% Y
- IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';, G" e+ b. Q/ h8 _8 q5 l( D
- IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
! M7 K* L5 V7 ~$ X) o
' q3 E; s7 d9 f' k- DEVICE_STATE_ACTIVE = $00000001;4 U# B, ~0 k$ I' @4 ~
- DEVICE_STATE_UNPLUGGED = $00000002;2 R- K- w9 _( w
- DEVICE_STATE_NOTPRESENT = $00000004;
- w5 O+ c- h' ?. K* s* t - DEVICE_STATEMASK_ALL = $00000007;. e. u* g f; O* O
, U! R5 t2 U' _$ ?' A- type
, f6 u% Q+ o( [ m' N, N# C - EDataFlow = TOleEnum;
" w; N3 y9 s) d( d8 l; K - const$ G4 H! e- U/ ` V. j) D- C
- eRender = $00000000;
( M! ]7 J! b& R+ M7 n - eCapture = $00000001;
+ t1 o& g- E& S- Y7 L - eAll = $00000002;
0 W1 L& y+ e( Y/ }! M - EDataFlow_enum_count = $00000003;* g& S" F; l1 u; E
) _( T( f0 a$ X8 \. k- type R% p! z7 u3 T$ u$ ?$ ?4 O
- ERole = TOleEnum;
( J8 I6 _3 A$ |. i - const' |5 N* s6 j* T' q% @* b
- eConsole = $00000000;
+ y# Z/ \# o7 o" v" y - eMultimedia = $00000001;; U. b, d% v; K3 a; n3 K4 O
- eCommunications = $00000002;2 @+ i. {" p" b. P! g6 x
- ERole_enum_count = $00000003;0 b& _% o7 y$ B) U- L- G
. Y5 A" S7 z7 \- m6 N- type
6 M4 q. U1 Z, v - IAudioEndpointVolumeCallback = interface(IUnknown)
. P. J# p9 J& p" U# ]: w - ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
0 ?3 T( V- C' P0 o6 I% X - end;4 ^7 q! X* t% U' j/ [6 F* I
- / ? L7 C: p3 L8 o0 [) t4 K
- IMMAudioEndpointVolume = interface(IUnknown)
3 S* d. K! U; r( J6 A3 \ - ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
$ G1 I+ U* K+ w - Function RegisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;0 w. c* V( ?: h1 i# B5 H
- Function UnregisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;& t% |0 q/ a4 u6 ^# m
- Function GetChannelCount(out PInteger): Integer; stdcall;) {$ ~& T, S3 S; _0 t
- Function SetMasterVolumeLevel(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;9 J' l E y& K& K( c
- Function SetMasterVolumeLevelScalar(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;; \, ]& b6 h$ Q# X& V
- Function GetMasterVolumeLevel(out fLevelDB: double):Integer; stdcall;
( ]. f, e( c/ N4 { - Function GetMasterVolumeLevelScaler(out fLevel: double):Integer; stdcall;9 W" d; g$ U( l4 Z6 g% b6 U
- Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
0 K# R! g3 J8 N6 t* g+ p9 n - Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;* I+ {) V j4 t5 T
- Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double) : Integer; stdcall;
6 B5 ~; g, N% M: P7 s7 r4 ?7 d& J - Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double) : Integer; stdcall;5 C1 j1 e6 k2 V% r X
- Function SetMute(bMute: Boolean ; pguidEventContext: TGUID) :Integer; stdcall;
2 U8 [- Q$ H3 H: q$ h2 O - Function GetMute(out bMute: Boolean ) :Integer; stdcall;
3 k: |' b, D6 E9 B! A- f/ G- S& c - Function GetVolumeStepInfo( pnStep: Integer; out pnStepCount: Integer):Integer; stdcall;
7 K$ J9 S7 F+ H: U$ R5 Z - Function VolumeStepUp(pguidEventContext: TGUID) :Integer; stdcall;8 W( h N, O. c( {+ r9 ]
- Function VolumeStepDown(pguidEventContext: TGUID) :Integer; stdcall;
6 v; f# A' j0 N! k$ D9 [ - Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
3 a O+ M5 R! M6 ~/ L4 A# _. h - Function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;+ k3 r4 ~* X* I4 B/ ^2 Q( h2 E
- end;4 m" S0 L+ p; J! G8 F1 H
- $ ?' {3 F* o/ U" H
- { IAudioMeterInformation = interface(IUnknown)
7 s8 j! u- H" x7 b+ c, p6 u o( | - ['{C02216F6-8C67-4B5B-9D00-D008E73E0064']
9 T, y% {/ I2 T0 g - end;}( `: {( m4 w8 \
- ; O2 ]! z0 j1 R
- IPropertyStore = interface(IUnknown)
- R# t- Q4 G+ y( q - end;/ B. y% \- u8 V& Q
3 ?* c: g3 v7 Q) i- type* Q; l2 A& x3 V( r S+ h5 X
- IMMDevice = interface(IUnknown)
* o! s; |5 o7 M& V' a - ['{D666063F-1587-4E43-81F1-B948E807363F}']
8 k6 E4 ~* ?" C - Function Activate( refId :TGUID;
# L- D) m1 E z9 J$ D7 C5 E6 X - dwClsCtx: DWORD;- z7 S. Y" \3 g% q, C
- pActivationParams: PInteger ;
" ?; a5 G z+ E7 ^1 E: ^. a - out pEndpointVolume: IMMAudioEndpointVolume): Hresult; stdCall;& |* T& Q/ s' K9 m2 |* g7 W
- Function OpenPropertyStore(stgmAccess: DWORD; out ppProperties :IPropertyStore): Hresult; stdcall;
! E$ o# e# p: a9 r - Function GetId(out ppstrId: PLPWSTR ): Hresult; stdcall;6 H6 G, A% `- i; D, c5 _ N0 L
- Function GetState(out State :Integer): Hresult; stdcall;
0 P; y$ E4 t Y( f z
* [/ h% ?, \6 [. S4 @! A. B5 q- end;
4 T! b/ Y# Z: V
, G$ Q/ F/ T9 m. n- A+ e1 `% [. T- 4 D: e+ R! V+ D; _
- IMMDeviceCollection = interface(IUnknown)$ h2 [2 A+ w9 @$ B% `
- ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']: i5 h9 J |8 k4 F) x; r
- end;3 z; p o4 t. i
6 i2 v# b# N `# Z* S- IMMNotificationClient = interface (IUnknown)
Q+ L+ l7 Z* P. U8 H - ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']* f( l! S2 d1 d) r' v% m
- end;, e% k G- R# J
9 F4 X2 V$ S9 D1 h6 q8 K- IMMDeviceEnumerator = interface(IUnknown)
' h' |) F- @9 x' O) j5 A0 l - ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']( F1 V# o9 a7 _$ B
- Function EnumAudioEndpoints( dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection:IMMDeviceCollection ): Hresult ; stdcall;
* I% J: `$ t9 t" x% S - Function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult ; stdcall;) A4 g8 ~1 j+ d, Q
- Function GetDevice( pwstrId: pointer ; out Dev :IMMDevice) : HResult; stdcall;
9 i p* V( y% e; N- H8 i - Function RegisterEndpointNotificationCallback(pClient :IMMNotificationClient) :Hresult; stdcall; C+ o9 ~& U! [6 }2 t% H- P
- end;- t5 {3 [8 [0 G3 J$ \
- ! ^! ~ m6 `0 o
- implementation7 A, @! z+ Y1 Y" A0 r6 D; P
- end.
0 S' p! l) D' {7 D0 m- G$ | - 8 `$ z" i- a/ O- b
- Thanks & Reagrds,2 x& _$ C4 T6 X- v b$ {4 x9 b) U
- Mukta ...3 ]+ Z4 p# o! x# o$ b
复制代码
9 w+ C! f3 P6 l+ Z+ t: `/ ]- it's work in Delphi 7; k5 ]# T5 ^0 _2 p1 _
- //////////////////////////
7 C$ _' R8 `: c- t/ w
, Y! f9 P( I I% A8 } e# @$ J3 }- }- unit MMDevApi;
+ M5 [& `/ J* |6 ]1 m" I3 L/ h/ c
! m) D- E) w, ~' `5 l- interface5 M- M7 u( v/ ^
v/ d8 y& W+ R h4 }9 ], c& e- uses
+ w& P) J/ a% u& X1 ~ - Windows, ActiveX, ComObj;) \' B) B) G4 v) v8 S( @2 e
. g' A5 r: h* ^ p: M. I- const
x* u+ u( E2 I" Y - CLASS_IMMDeviceEnumerator : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';. }: J, e$ I% @2 c* |. E
- IID_IMMDeviceEnumerator : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
# G4 o2 ~2 y1 `1 |! M' t - IID_IMMDevice : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
7 C+ K2 C; a6 h4 ? - IID_IMMDeviceCollection : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
7 ?! h* J v! n4 t - IID_IAudioEndpointVolume : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
, U/ a9 J4 [ T. R Q - IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
; J4 u& _9 M' M4 { - IID_IAudioEndpointVolumeCallback : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
" b! I5 X2 Q$ C, Q7 _ - 9 p& l1 W( I0 f$ B1 t9 G2 V6 A
- DEVICE_STATE_ACTIVE = $00000001;
# ~. y$ P% i9 J5 W! z; e) T I - DEVICE_STATE_UNPLUGGED = $00000002;
# A& A; X: p! ^5 Q" G6 j - DEVICE_STATE_NOTPRESENT = $00000004;( i# \$ }. y0 X6 z% h$ o2 R
- DEVICE_STATEMASK_ALL = $00000007;
9 B; ?9 B! x6 o2 x; m$ l% i/ f
3 R1 i2 o+ v* m, W6 O- type
! @5 {! Z$ H; s$ t8 [ J% p - EDataFlow = TOleEnum;
* z% d5 y' i" d6 b' D" T - ) N% i- c8 t$ D! f
- const
1 y. r" E) Q8 b0 v& P& ~ - eRender = $00000000;6 p/ y' G% z6 r1 Q6 N
- eCapture = $00000001;9 S% P+ _2 c% E) U+ Y" Q R9 J
- eAll = $00000002;
/ J6 h( T2 [$ I) G2 g - EDataFlow_enum_count = $00000003;
% Q# m' T( d& @8 B/ R - $ K9 {) o; C. ~- T# l7 |* a& E
- type9 r" P0 R0 @3 k s% j" x
- ERole = TOleEnum;
9 d. }) d# v: L7 V+ ?" i0 y5 X+ Y
6 F2 P7 a: k9 I* D8 ?' I( M- const3 G" m7 H" x. f4 g& g+ R
- eConsole = $00000000;
: W: E4 R5 R+ c/ p2 q - eMultimedia = $00000001;& O$ |3 n- y9 h( E
- eCommunications = $00000002;1 x. H/ S$ a, n* U5 [% V
- ERole_enum_count = $00000003;4 P; j$ ?) y: Z: J9 A% J
' [- p- ~7 a" h0 U- type2 ^' w- ?+ j* a" k# l `* L
- IAudioEndpointVolumeCallback = interface(IUnknown)+ { p# Z0 h) D2 {0 h7 q& ^
- ['{657804FA-D6AD-4496-8A60-352752AF4F89}'] Q! ~5 N; |& I% l
- end;9 N# W7 x. B2 n0 B+ m, E2 R
- D5 ?# j- Q# Q- IAudioEndpointVolume = interface(IUnknown): ~9 c+ w- A9 P! K
- ['{5CDF2C82-841E-4546-9722-0CF74078229A}']* w- m4 c! c" O6 _; c: F/ K
- function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;/ T8 p1 C% T. R% H3 p! Z
- function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;; G1 {8 {* S4 D) C8 X3 X. ^0 E
- function GetChannelCount(out PInteger): Integer; stdcall;
& f7 Y2 o R- q* \" ?+ k5 J% D - function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
* J/ n, t6 q1 t, l* { H* ^ - function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;- g( z( D; W8 F
- function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;
: N2 O% W+ Y- ?/ ? - function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall;' G) Y% B; D# D1 W7 r
- function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;6 C* S+ d/ C8 M4 L1 D* B Q) \
- function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
J9 m7 `" ?3 w- [! B - function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;
) D0 n7 j( l: i( d/ ]1 s" K/ z - function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;: W! W, F* b# |. D- d _3 k
- function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;
+ `/ ]& \3 |' e - function GetMute(out bMute: Boolean): Integer; stdcall;
6 x2 B/ H3 H- L0 o - function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;2 y7 r6 p/ y- i, ]6 [& U
- function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;0 D; |" r8 E+ f7 A! x
- function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;: h/ I5 r- I8 H7 { T
- function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;, ` g) t9 |9 t2 _8 m# L9 y0 c. T
- function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;) Y+ Y5 s/ c( Q; o6 _, ~
- end;
, L Y+ y! @* X v5 e
# N9 f' L7 h! Z) ?0 L# J- c- IAudioMeterInformation = interface(IUnknown)- u' R. m- n' U3 r q* X
- ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']! k9 D& \: n& l _4 G
- end;4 U* R5 C/ y0 C8 m' A+ I
) C( _7 O% e" ~9 p) V, X- IPropertyStore = interface(IUnknown)
6 V* U4 z& K+ } - end;, n2 t3 O: O; D3 J4 Q$ B& x) `6 d0 n
1 k& N# V- ?: J* N5 z& I/ y- IMMDevice = interface(IUnknown)
0 M3 w0 J* d i - ['{D666063F-1587-4E43-81F1-B948E807363F}']
8 c1 x! G+ z2 V1 Y8 H0 d" } - function Activate(const refId: TGUID;' i% v8 T2 s% V, }2 ~
- dwClsCtx: DWORD;
1 Z3 y% u9 H+ h1 S - pActivationParams: PInteger;
6 { R4 ^8 M; v5 h/ ~( m - out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;% P( w! }. _$ x1 @: _2 q$ ]
- function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
, g1 j5 U/ g0 k* H+ g - function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;7 J- ~) [3 r! V5 ]* V- r
- function GetState(out State: Integer): Hresult; stdcall;# s$ X' X1 m0 I. A
- end;
! u1 e `* O4 P! k - ) g6 z; i$ U W
. m: k' ^; c! H H$ X: K1 x/ g( J- IMMDeviceCollection = interface(IUnknown)
7 S: C @3 K d2 P( ~3 K7 N0 F - ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
+ ?* |' ~1 y, v3 I! ~4 L - end;
" i/ `# j4 h5 Z7 ]2 _( B
; Z$ ~9 v6 m3 g( F7 B$ N- IMMNotificationClient = interface(IUnknown)
- b9 y6 Z0 G1 l! e2 o - ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
8 V9 Y7 H( m! f' d" c( F - end;* \" }& j& ^* N" I
, a9 s, C5 I; O6 \! C- IMMDeviceEnumerator = interface(IUnknown)
% M" f. c9 v6 F, J' t2 r - ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']4 O5 x; p" V9 U# {8 y0 ^
- function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;
% ]* {9 k( K: L8 v# Z - function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;3 }6 {# v% A: [9 q7 Y
- function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;
7 X8 R6 U) w+ A2 V. l( S- \ - function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;$ N y& L/ _# H. u6 o! t) n' n% M
- end;: g c; f3 ~# u$ X% c- J
- + }" }) T; N' z& j9 F' [1 v
- implementation/ M* t/ X$ f; I3 k
- $ e# `6 z8 l L: I8 M4 H4 t
- end.1 `& E9 }& O" }4 B
- 3 U* M" q! h. L
- ///////////////////////
) ]' f* V* y# n6 @: v" E - simple sample :)8 t5 R. N# ~5 \3 p
- ///////////////////////# i% v0 N- n# J9 H
% r5 I( ]8 G( g; C- //...... other code& [8 W0 Z; r8 n+ G2 m( ?. s U
& Z& N1 F3 U9 p- uses ... ActiveX, MMDevApi, ...;
^4 I/ {8 n0 F* @' {/ {
$ n. v4 `8 p+ d( m& _- //...... other code
6 h8 c4 {7 h& F
0 ?$ a* m U5 c5 |- var( T! B f( H$ ~1 }( q0 n
- endpointVolume: IAudioEndpointVolume = nil;, p! _. T. {+ |, O) N7 }7 i6 F
- # Z4 o, {8 h5 D5 P, H- {( f' ~
- procedure TForm1.FormCreate(Sender: TObject);
# B0 u% g$ @. l' N - var
: p% x) z# D$ F1 I - deviceEnumerator: IMMDeviceEnumerator;# G. g t6 I* f, [, a
- defaultDevice: IMMDevice;
a8 V: z% K: |( e" i4 k - begin
( X" J! g0 A7 O( h8 a - CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);; B4 f, C9 o D. h0 x7 x6 V
- deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);* O" ^2 ^1 @6 _3 k- X- S
- defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);
5 \$ k6 O A# z5 a+ @# F0 R$ u - end;/ R, F* M6 ]+ Q! R: \. n' w
8 \8 U# ]1 z- M- procedure TForm1.Button1Click(Sender: TObject);
1 z, [( [+ k! g - var
. K# U: p; d2 S# e P. _! k - VolumeLevel: Single;
4 _- _" o7 b1 ~/ n3 o( d6 p - begin
0 t; l8 y: r* A: w1 d1 [* K8 ? - if endpointVolume = nil then Exit;
7 d: P, ? K( ~+ j/ W: v - VolumeLevel := 0.50;0 m% ]( j# n; O6 d7 C' ?
- endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil);! G; Y7 S, L/ [3 Q6 V2 f
- Caption := Format('%1.8f', [VolumeLevel])
7 M5 B* P2 s4 p5 _5 C3 @$ T1 p - end;" ?- [/ I+ o; `- q
* @+ n4 ^' D' x# w% z( M6 `+ k- /////////////////////////////////////
$ n V% p/ b- x, E$ o! G ^ - , d: d! U: ~3 w
- // with best regards ToxicDream# H7 t9 v c# R1 D; o, Z7 u+ z
复制代码 |
|