|
|
来自: http://social.msdn.microsoft.com ... 9-a8c9-2e27eb9ec0583 c/ s S& B, K0 U8 }. B8 G0 q$ X
By Mukta & ToxicDream- . D) d* X: V s
- //for delphi 5% b1 F/ a" l( ?4 |, P, A+ G+ ~8 g9 N
- unit MMDevApi_tlb;
$ \3 x) s4 N6 X% M
* ]( m9 }; W( G4 ?- interface' b, A, V* x7 \0 e$ ^4 o
- uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;
2 Y" w! c( X5 W Z6 [ - const0 X( S- Z6 H% p; X3 M( r; w
- // TypeLibrary Major and minor versions
6 ~2 z H3 [$ C
& Q5 ?( H" F+ z- T* s8 }$ ^- CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
" l% A1 [/ l/ `" i+ b1 u- r - IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';- H( b- f2 v/ S0 F
- IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
5 J4 q# Y( w% ?8 H7 g, c& \# w - IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';: H3 A" p5 y$ N) E! I
- IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';! h& _. W, @* L; i- x+ ?* I8 r* x: w
- IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';7 o# p# i( j4 T) L
- IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';* `: r, y( g. j' u- y6 s
- - C( y1 V1 e/ k1 i
- DEVICE_STATE_ACTIVE = $00000001;
" N" t( c& B4 w5 B+ l8 B - DEVICE_STATE_UNPLUGGED = $00000002;$ @3 R! q3 U: n; o6 P
- DEVICE_STATE_NOTPRESENT = $00000004;
) j' V8 _, `9 @( v; h6 c - DEVICE_STATEMASK_ALL = $00000007;7 c7 B+ b; k4 s5 v$ T
' Q( S1 u5 Q, a- type
$ T, A" {8 k# x, f F- t - EDataFlow = TOleEnum;
4 o2 M) D1 o: d, r - const/ f' f* E% ?7 [" t' l6 m
- eRender = $00000000;
0 N8 O# A' P4 _) p - eCapture = $00000001;
8 S: ?+ l1 R0 k/ z - eAll = $00000002;! t& ]# g4 q2 }9 ~8 R' H7 A
- EDataFlow_enum_count = $00000003;
9 E/ r4 [& t2 I& K
$ q6 @$ W# u4 w* m+ f- type
& W% {# z5 Q0 Z0 M! \9 H - ERole = TOleEnum;5 I) C5 L3 A( D* g/ g% I
- const
7 e) A1 S r4 G$ I - eConsole = $00000000;. e8 A" Z1 {' ?' T- r
- eMultimedia = $00000001;1 V" q! T/ i8 W7 _
- eCommunications = $00000002;8 I' _1 w' k8 o6 k7 e% P
- ERole_enum_count = $00000003;
( i% W! b5 F3 J: R# ~* |
# @3 \- W4 Z' C U- type
" F# J& h/ Y4 ]) u' c - IAudioEndpointVolumeCallback = interface(IUnknown)2 E3 w& z8 h N( n3 y
- ['{657804FA-D6AD-4496-8A60-352752AF4F89}']$ ]6 j8 T( h/ d6 y+ `" z
- end;& D% K8 u) ~( Q3 P! [ j( _
( v* Q8 S# j& v! @- IMMAudioEndpointVolume = interface(IUnknown)# p& I7 n+ @ j" A$ B
- ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
2 E& R$ A& w# d: D( L! P' c - Function RegisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
3 n* I# T1 {" h - Function UnregisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;2 f! {) `7 |2 P3 r# e/ E
- Function GetChannelCount(out PInteger): Integer; stdcall;! P2 H# F) q V# T# S# m& ^; H
- Function SetMasterVolumeLevel(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;; i. P1 c7 o$ p$ }
- Function SetMasterVolumeLevelScalar(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;, @7 @" L P; y, r* R) Q9 u
- Function GetMasterVolumeLevel(out fLevelDB: double):Integer; stdcall;* H* i) W& X4 x7 v O" F
- Function GetMasterVolumeLevelScaler(out fLevel: double):Integer; stdcall; ]2 @/ h0 n- N6 r0 y3 W
- Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
& V' n- g1 ^9 [6 B' c0 T - Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
. y0 p" S7 @8 f2 B5 W) Y* O - Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double) : Integer; stdcall;) Q& }0 e' _1 i' a) F
- Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double) : Integer; stdcall;
; Q$ G6 h; h; W. }! N2 M3 R: M - Function SetMute(bMute: Boolean ; pguidEventContext: TGUID) :Integer; stdcall;
& _ P- ?; _- m - Function GetMute(out bMute: Boolean ) :Integer; stdcall;5 D4 r8 ^0 e% z' C$ ]$ U
- Function GetVolumeStepInfo( pnStep: Integer; out pnStepCount: Integer):Integer; stdcall;( n3 F5 a f; f2 X9 r
- Function VolumeStepUp(pguidEventContext: TGUID) :Integer; stdcall;/ Z4 w: e5 A8 @& a9 V$ z) L- o
- Function VolumeStepDown(pguidEventContext: TGUID) :Integer; stdcall;
: |$ K6 q( M4 r" _ - Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;9 L$ ]; H- t% H! Y5 Q
- Function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
$ @: U* [# ^5 ^7 p - end;
0 r: C' J# H' Y6 u
" q3 K0 L- ]5 d- { IAudioMeterInformation = interface(IUnknown)- r2 `6 ]* A% x: ~) w
- ['{C02216F6-8C67-4B5B-9D00-D008E73E0064']2 c( H) {& B, s+ c, H! m7 y8 w8 N
- end;}- }, {1 d7 o2 z+ H7 b) `& v
- 1 F h3 j) d5 I. r8 n1 u* @) d" ^
- IPropertyStore = interface(IUnknown)4 @4 ?# g M5 ^" I; H% \
- end;
3 v# C9 m; U+ e1 j" o - P+ k C' j3 F2 f! j' c
- type
2 R) [6 h' |- `$ B9 R - IMMDevice = interface(IUnknown); \# p: m2 O/ B" f1 K
- ['{D666063F-1587-4E43-81F1-B948E807363F}']; c2 r' \8 x9 B& h. O) L
- Function Activate( refId :TGUID;; d( s) a- ~! L& t! R$ o) Z
- dwClsCtx: DWORD;
% q' e: ?2 V/ v- o4 \2 { - pActivationParams: PInteger ;2 H5 I+ G% H! y, r
- out pEndpointVolume: IMMAudioEndpointVolume): Hresult; stdCall;
* d- m5 s2 z- l" P: A* i V8 ]/ ] - Function OpenPropertyStore(stgmAccess: DWORD; out ppProperties :IPropertyStore): Hresult; stdcall;- i* _0 W% H$ _$ [& z7 S
- Function GetId(out ppstrId: PLPWSTR ): Hresult; stdcall;% e0 j- r6 n) Q& W: _/ K
- Function GetState(out State :Integer): Hresult; stdcall;; ^' H# h( o; T6 j8 @
, v2 p/ C0 N% ]- end;
% ^6 y9 y2 X: t3 }9 C7 G9 ^# i - " S* l: Z" W _" Z; s
* z6 O5 {0 F; i- IMMDeviceCollection = interface(IUnknown)
f8 i$ V0 {# d7 ^" ~" o. n - ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
4 p; E3 m; j1 I" b - end;, ]' z# [1 U) j( F& m
- * b1 _: W. r, V/ w' g
- IMMNotificationClient = interface (IUnknown)
" ~9 I/ B6 B. {. ]3 x# G3 t - ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
5 H; M$ \0 f: D: u- o - end;. L4 F& y5 f2 |- ~2 g8 }: @
B& A7 ?/ |$ @4 n9 ~+ X- IMMDeviceEnumerator = interface(IUnknown)
5 i1 i' a) x6 o l - ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
0 U& M+ q. f# K5 d - Function EnumAudioEndpoints( dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection:IMMDeviceCollection ): Hresult ; stdcall;/ ~. S4 r1 Y" c# {8 n
- Function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult ; stdcall;
* v. B4 B* _# G* o - Function GetDevice( pwstrId: pointer ; out Dev :IMMDevice) : HResult; stdcall;
. N9 |" A3 l5 @- R" w! H( Q - Function RegisterEndpointNotificationCallback(pClient :IMMNotificationClient) :Hresult; stdcall; Y0 h4 _$ ` u/ U& L$ d- {9 t7 }
- end;- a, C/ v8 r/ ]3 g( }) `2 G
( R! D% F. i9 ^6 |+ S! \0 r- implementation
+ Z) {( P/ g; Q" J - end.
. A8 s/ n, m9 O' `2 O
* O$ i: K8 m& z( N1 @- Thanks & Reagrds,
* I) B+ d( Y w* d" K4 E8 q- x - Mukta ...) s8 s# h) @9 _7 d
复制代码
2 f2 `/ g6 ]& ^: F3 U( z% }, y9 k3 D- it's work in Delphi 7( G0 I7 v; p( g: ^
- //////////////////////////
) A2 S: m7 k, H* q* p: }# N
4 S+ E5 o- @. I! n! [ a9 U- unit MMDevApi;$ F5 k( X) f% c0 O: b: k
- e9 d4 W. t7 ~2 C2 [& K- interface
+ ~) B3 |: w% b: m. Z* l* H
( P1 G/ v: N- d' X& O- uses( v/ F3 j" Z& o ? C
- Windows, ActiveX, ComObj;& c1 B7 q, [" S) N& ]
7 W7 U7 W5 h1 ~# R- {- const+ M" k( ~. W9 a) {. n
- CLASS_IMMDeviceEnumerator : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
% f2 K r6 j4 X7 I. i4 ^9 f& F - IID_IMMDeviceEnumerator : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
9 s3 ^! I# ~. F/ F. V$ j. e - IID_IMMDevice : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
: m& s, [1 D6 { _8 T) z8 I- r - IID_IMMDeviceCollection : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
+ R x4 b/ {1 T1 B - IID_IAudioEndpointVolume : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';8 I: `! v6 P6 L. k0 r
- IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
3 {5 g& A6 Z' D' U/ `0 R - IID_IAudioEndpointVolumeCallback : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
4 N4 C7 G4 x+ [ - + m" c- `0 }9 m3 x% l
- DEVICE_STATE_ACTIVE = $00000001;
% R9 r H$ V6 _% w9 Z1 @ - DEVICE_STATE_UNPLUGGED = $00000002;3 ^! ]1 m5 ?7 _( S. O% {. l
- DEVICE_STATE_NOTPRESENT = $00000004;
6 S- k; K6 { T1 W- C6 C% G7 S - DEVICE_STATEMASK_ALL = $00000007;
]: x2 u4 B- v `. A( X" C
1 ^9 g0 d% @* V* |1 S% v7 E1 b4 D- type
( _, W# i8 ]: s5 p6 j - EDataFlow = TOleEnum;
* F' K/ l' i" P6 t& s - / i+ _( s+ T* L, s1 @8 H @
- const% Y8 G* M9 k2 t6 T
- eRender = $00000000;
* a) t; O: p& s( }# |- I - eCapture = $00000001;
3 `6 }' z) I2 p G - eAll = $00000002;, l/ u# }9 U: z1 h, [5 {
- EDataFlow_enum_count = $00000003;
8 z& i& U) G# B& a& R& b3 p% `
) A! R/ T# ?- @, h- type) u0 I, c8 @: V2 T4 |
- ERole = TOleEnum;
+ c9 t4 ]" [ X$ a - f7 V7 k2 {3 f# Z
- const
8 @7 K" ~6 s+ k" C2 H4 Z* t$ q# ? - eConsole = $00000000;
" c. r3 T2 k2 U/ P1 t - eMultimedia = $00000001;) T6 z$ O+ r! D7 h
- eCommunications = $00000002;
\! [5 k5 g7 B* C0 E, F* h0 K1 _* _3 h - ERole_enum_count = $00000003;
7 @* S# {1 q _) W6 V; u* q' V" B! s
, W5 e5 e+ g5 C9 r# ?5 [- type: i9 Z: r$ a+ g
- IAudioEndpointVolumeCallback = interface(IUnknown)
( t- Q5 O6 W$ T9 H8 v4 l$ i, X+ o8 p - ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
* p+ H& \% X* e - end;
' e( q' z1 v4 \6 I C4 I9 l
% K! Q; r7 r8 |% c" g3 P- IAudioEndpointVolume = interface(IUnknown)
& y6 F/ p' J8 @6 r$ s3 V! J - ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
3 v: T: N$ B! A - function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
! y# @4 P7 L, r# c6 a - function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
4 F! x- b/ l+ P2 Z' } - function GetChannelCount(out PInteger): Integer; stdcall;
3 T) h1 W( J, O, b - function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;& [+ m& K' K0 t+ r
- function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;0 b' Q0 e* K0 c5 _
- function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;
* {1 h+ Q1 y5 ?; s; V - function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall;
1 K: G% F+ f. S2 I - function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall; R! V. h. h7 y9 A
- function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
) R$ }% B4 S/ P5 J - function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;
' G% |% @ A, Q) e - function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;
~1 D$ z. X m - function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;
/ ^) A# i$ K$ h7 F2 F - function GetMute(out bMute: Boolean): Integer; stdcall;$ m) P9 y. Z& r: M, J4 ]; E, d
- function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;9 b t5 H; p" A1 H
- function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;
0 D2 u* x# K% V* H* y$ i - function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;' i" b% ^- ~$ _% W
- function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;/ x( S# m( j. f3 n/ i; P6 @: j
- function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;- x/ B. }) ~, A( [1 e2 T7 Z
- end;
; M" m) E* J1 @7 ]' t - ! q% W9 q; S/ W# J5 h
- IAudioMeterInformation = interface(IUnknown)0 L/ _ X% d* o3 ~. M( O3 \
- ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
, j, w: _* M% P4 N+ R7 w/ O - end;
B* M2 ]$ H* L/ Y6 {' @2 m - 0 l" h8 Z3 u9 U/ G3 t+ E
- IPropertyStore = interface(IUnknown)
8 g. M* c, R$ m/ E - end;3 @5 f" ]% H$ A$ p P+ U
0 k% G' P- I3 A7 p, b0 G- IMMDevice = interface(IUnknown)' N6 a6 T8 c( T& r3 Q8 h" F
- ['{D666063F-1587-4E43-81F1-B948E807363F}']
" b; ~" p* x( Q0 W( X+ ^( I* H - function Activate(const refId: TGUID;
. n0 j; R/ ?& I, w7 }) F - dwClsCtx: DWORD;
0 N. B% B2 k. @! H; _ - pActivationParams: PInteger;5 u4 Q0 @$ `6 Q& S% i' D, v8 P
- out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;
4 G' F$ \* l% }- i - function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
% J( r0 ?6 n0 V1 W8 o) Z1 x" a - function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;
$ Q8 Q+ E/ Z2 {+ C+ u - function GetState(out State: Integer): Hresult; stdcall;1 D9 \3 e6 `- y% r I0 d
- end;
4 Y! B i2 }8 R" g0 ? x: F
: N% O/ F K- r' ~. W
7 o" o4 i7 K, b; Q- j- IMMDeviceCollection = interface(IUnknown)1 B* Z- G) i4 @' r0 K
- ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']# M3 Y. T( s( c" `* Y9 M; D
- end;
+ d- X+ ~: ?4 J- _) Y - 9 M- b) E0 L) H3 [/ s. ]: F
- IMMNotificationClient = interface(IUnknown)9 Y& g4 O2 a! h
- ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}'] z% G7 r8 @* ^- E! |6 c
- end;
( M9 t; n0 C$ q1 V
( `0 V6 L- y7 X- IMMDeviceEnumerator = interface(IUnknown)
/ n: t" s( {1 u: K# O - ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']5 L$ l; }3 v- @0 G+ b8 b
- function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;
& e6 i3 b L1 x - function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;1 q7 A1 P2 W3 p% d2 t
- function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;7 U4 z8 r* p9 _6 _9 Z1 X' I' x2 z5 Y
- function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;
$ k! t8 U) x! U( g6 k - end;; [" o J8 ]& r! \+ b2 | O' h0 O
- + L" i4 A/ _5 l- S+ H* h
- implementation
^3 O- p: I, h9 T0 G
) d0 N. h! |( M3 S# X- end.- c$ w. q0 T% X# F8 M
/ O! U% h# |3 }/ o2 x- //////////////////////// I0 u% T+ o/ |
- simple sample :)4 @ @: k C; b! P, B$ t
- ///////////////////////+ `6 c3 z3 m& D* b; ?! a7 O- Y; h
- - f2 L5 |% O' n% S0 z1 ?8 A' n
- //...... other code
0 p1 r+ D2 ~) j% {' Q& B: ^3 x - 1 m& z5 t( v9 d6 M. d! {
- uses ... ActiveX, MMDevApi, ...;, }- S) q6 p9 T/ R9 `" Y
, W) x( f6 v, b8 d- //...... other code! m, Z5 }& _, d' \5 j
- ; |; ^) Q" m" }- T
- var& Q/ O* w* u5 T+ M
- endpointVolume: IAudioEndpointVolume = nil;3 m* n a' k& i" T+ M7 T0 g8 M; A
- - S/ \4 `6 {. M# Y" Z7 n: ]* n+ J! f
- procedure TForm1.FormCreate(Sender: TObject);
2 O0 {' c/ x; m9 C0 o - var& c. Z3 K5 _/ F: Y' S
- deviceEnumerator: IMMDeviceEnumerator;! F$ ^* H7 @& A
- defaultDevice: IMMDevice;
V8 b2 T9 j. n, K0 }5 O& T - begin! f3 L/ ~& |! w
- CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);5 V) f! V0 V5 \+ t$ y
- deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);7 ?# d! D, ^: z* U
- defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);
d0 M# ~: w! T4 V& `/ M - end;- S2 n$ T4 A( ?: C$ y
( G$ d) G# x9 f, P- procedure TForm1.Button1Click(Sender: TObject);
7 x U- g* P8 k) n9 G - var
( }+ ]& c3 Z! @' `3 M2 a3 h6 l - VolumeLevel: Single;) b7 k* x A" H; P8 x1 K1 s
- begin
$ ~; ]6 J6 w( q1 c; d! G+ h. X - if endpointVolume = nil then Exit;
2 Z% i8 W0 A' [9 f9 ?1 u - VolumeLevel := 0.50;; r3 v' T. P5 q1 p! E, p
- endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil);
# T! \" _! q# i$ L! j* D2 n! I - Caption := Format('%1.8f', [VolumeLevel])
" b/ a ~: a' P) M- l c - end;
- r% x8 J! |+ K! [8 Q' z2 t+ W6 n3 x
2 N! s% P( I' f1 ]- /////////////////////////////////////
9 j' O$ Q* k1 R; v9 J i
' p) H0 J+ J, G! r1 F0 j( o; i) e- // with best regards ToxicDream
: N; S' ^$ c% B! `
复制代码 |
|