桌面歌词的同步显示

要实现桌面歌词,第一步必须做到将view置于屏幕顶端,实现这个效果可以用window系统自带的winmanager来实现,具体实现代码:
WindowManager wm;//创建浮动窗口盛放歌词
    public void createFloatView(int paddingBottom) {

        wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        view = LayoutInflater.from(this).inflate(R.layout.floatlrc,null,false);//拿到桌面歌词的布局
        desk =(LrcView2)view.findViewById(R.id.lrc);//自定义的盛放桌面歌词的textview
        final LinearLayout gone = (LinearLayout)view.findViewById(R.id.lrcgone);
        final ImageView iv = (ImageView)view.findViewById(R.id.iv);

//设置监听点击关闭按钮关闭桌面歌词
        iv.setOnClickListener(new View.OnClickListener() {
            @Override
            publicvoidonClick(View v) {
                removeFloatView();
                lrcIsShow=true;
            }
        });

//定义布局参数
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL//设置浮动窗口下面的组件可以被点击
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        params.format = PixelFormat.TRANSLUCENT;// 不设置这个弹出框的透明遮罩显示为黑色params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;;
        params.gravity = Gravity.TOP | Gravity.LEFT;
        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        int screenHeight = getResources().getDisplayMetrics().heightPixels;
        params.x = screenWidth;
        params.y = screenHeight - paddingBottom;
        view.setBackgroundColor(Color.TRANSPARENT);
        view.setVisibility(View.VISIBLE);

//重写onTouchListener,达到可拖动的目的,只可以上下拖动
        view.setOnTouchListener(new View.OnTouchListener() {
            // 触屏监听float lastX, lastY;
            int oldOffsetX, oldOffsetY;
            int tag = 0;// 悬浮球 所需成员变量

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final int action = event.getAction();
                float x = event.getX();
                float y = event.getY();
                if (tag == 0) {
                    oldOffsetX = params.x; // 偏移量
                    oldOffsetY = params.y; // 偏移量
                }
                if (action == MotionEvent.ACTION_DOWN) {
                    lastX = x;
                    lastY = y;
                } elseif (action == MotionEvent.ACTION_MOVE) {
                    params.x += (int) (x - lastX) / 3; // 减小偏移量,防止过度抖动params.y += (int) (y - lastY) / 3; // 减小偏移量,防止过度抖动
                    tag = 1;
                    wm.updateViewLayout(v, params);//更新位置
                } elseif (action == MotionEvent.ACTION_UP) {

//判断为点击后做的事
                    int newOffsetX = params.x;
                    int newOffsetY = params.y;
                    // 只要按钮一动位置不是很大,就认为是点击事件if (Math.abs(oldOffsetX - newOffsetX) <= 20
                            && Math.abs(oldOffsetY - newOffsetY) <= 20) {
                        if (gone.getVisibility() == View.GONE) {
                            gone.setVisibility(View.VISIBLE);
                        } else {
                            gone.setVisibility(View.GONE);
                        }
                        v.setFocusable(false);
                    } else {
                        tag = 0;
                    }
                }
                return  true;
            }
        });
        initLrc();
        wm.addView(view, params);
    }

第二步就是对布局中自定义的textview(desk)做的事了,initLrc()就是为desk绑定监听事件,首先呢需要自定义接口初始化歌词以及监听歌词的变化
publicinterfaceOnLrcChangedListener {
    publicvoidonLrcLoaded(List<LrcModel> lrcModels);
    publicvoidonLyricSentenceChanged(int index);
}

第三步:从网络或者本地数据库中拿到lrc歌词,将歌词处理成我们需要的,一行一行的格式,定义LrcDownloadManager类做这些事情,
package com.example.user.myapplication;

/**
 * Created by user on 2016/9/13.
 */public class LrcDownLoadManager {

    private LrcDao lrcDao;
    private List<LrcModel> lrcModels;
//可能不止一个地方需要歌词信息,因此定义一个集合存放监听器,需要的时候遍历就好
    private List<OnLrcChangedListener> onLrcChangedListeners = new ArrayList<>();
    private OnLrcChangedListener lrcChangedListener;
    publicvoid setOnLrcChangedListener(OnLrcChangedListener lrcChangedListener){
        onLrcChangedListeners.add(lrcChangedListener);
    }
    public LrcDownLoadManager(Context context) {
        lrcModels = new ArrayList<LrcModel>();
        lrcDao = new LrcDao(context);
    }
//从本地数据库加载格式为lrc的歌词,如果没有就从网络中加载
    publicvoid getSongInfo(final BenDiMusic music){
        List<Lrc> lrcs = lrcDao.queryForName(music.getName());
        if(lrcs.size()!=0){
                String[] lines = lrcs.get(0).getContent().split("\\n");
                lrcModels.clear();
                for(String l:lines) {
                    parseLrc(l);
                }
for(OnLrcChangedListener l:onLrcChangedListeners){
                if(l!=null){
                    l.onLrcLoaded(lrcModels);
                }
            }

        }else{
            if(1==1){

                VolleyUtil.get().setCallBack(new CallBack() {
                    @Override
                    publicvoid onSuccess(String response) {
                        lrcModels.clear();
                        try {
                            Log.i("response", music.getName());
                            JSONObject jsonObject = newJSONObject(response);
                            JSONArray array = jsonObject.getJSONArray("song");
                            for(int i = 0;i<array.length();i++){
                                JSONObject object = array.getJSONObject(i);
                                if(object.getString("artistname").equals(music.getCuthor())){
                                    music.setId(object.getString("songid"));
                                    break;
                                }
                            }
                            getLrc(music.getId(),music.getName());
                        } catch (JSONException e) {
                            lrcModels.clear();
                            e.printStackTrace();
                            return;
                        }
                    }

                    @Override
                    publicvoid onError(VolleyError error) {
                        lrcModels.clear();
                    }
                }).setUrl("http://tingapi.ting.baidu.com/v1/restserver/ting?format=json&calback=&" +
                        "from=webapp_music&method=baidu.ting.search.catalogSug&query="+music.getName()).builder()
                        .setPriority(Request.Priority.HIGH)
                        .start();

            }


        }

    }
    publicvoid getLrc(String id, finalString name){
        VolleyUtil.get().setCallBack(new CallBack() {
            @Override
            publicvoid onSuccess(String response) {
                lrcModels.clear();
                try {
                    JSONObject jsonObject = newJSONObject(response);
                  if(jsonObject.getString("lrcContent")==null){
                      return;
                  }
                        Lrc lrc = new Lrc();
                        lrc.setContent(jsonObject.getString("lrcContent"));
                        lrc.setName(name);
                        lrcDao.addBook(lrc);

                    String[] lines = jsonObject.getString("lrcContent").split("\\n");
                    lrcModels.clear();
                    for(String l:lines) {
                        parseLrc(l);
                    }
                    for(OnLrcChangedListener l:onLrcChangedListeners){
                        if(lrcModels.size()==0&&l!=null){
                            lrcModels.clear();
                            l.onLrcLoaded(lrcModels);
                        }
                        if(l!=null){
                            l.onLrcLoaded(lrcModels);
                        }
                    }

                } catch (JSONException e) {
                    e.printStackTrace();
                    return;
                }
            }

            @Override
            publicvoid onError(VolleyError error) {
            }
        }).setUrl("http://tingapi.ting.baidu.com/v1/restserver/ting?" +
                "method=baidu.ting.song.lry&songid="+id)
                .builder().setPriority(Request.Priority.HIGH).start();
    }
//将歌词每行的文字提取出来放入集合
publicvoid parseLrc(Stringline){
        String reg="\\[(\\d{2}:\\d{2}\\.\\d{2})\\]";
        Pattern pattern=Pattern.compile(reg);
        Matcher matcher=pattern.matcher(line);
        while(matcher.find()){
            String time=matcher.group();
            LrcModel lModel=new LrcModel();
            lModel.setCurrentTime(parseTime(time));
            lModel.setCurrentContent(line.substring(time.length()));
            lrcModels.add(lModel);
        }
    }
//每行歌词的播放时间提取出来
public Integer parseTime(String time){
        String temp=time.substring(1,time.length()-1);
        String[] s = temp.split(":");
        intmin = Integer.parseInt(s[0]);
        String[] ss = s[1].split("\\.");
        int sec = Integer.parseInt(ss[0]);
        int mill = Integer.parseInt(ss[1]);
        returnmin * 60 * 1000 + sec * 1000 + mill * 10;
    }
//通过当前播放进度判断播放位置,返回当前行在集合中的索引位置
publicint lrcIndex(int duration,int currentTime) {
        int index = 0;
        if (currentTime < duration) {
            for (int i = 0; i < lrcModels.size(); i++) {
                if (i < lrcModels.size() - 1) {
                    if (currentTime < lrcModels.get(i).getCurrentTime() && i == 0) {
                        index = i;
                    }
                    if ((currentTime > lrcModels.get(i).getCurrentTime())&& currentTime < lrcModels.get(i+1).getCurrentTime()) {
                        index = i;
                    }
                }
                if ((i == lrcModels.size() - 1)&& currentTime > lrcModels.get(i).getCurrentTime()) {
                    index = i;
                }
            }
        }
        return index;
    }

}


第四步当然是开启桌面歌词的同时为desk添加监听器了,我是在服务中为desk添加的监听器,创建浮动窗口也是在服务中封装好的方法,提供一个调用的方法,
public void initLrc(){
      setLrcChangedListener(new OnLrcChangedListener() {
          @Override
public void onLrcLoaded(List<LrcModel> lrcModels){
              desk.setLrcList(lrcModels);
          }

          @Override

public void onLyricSentenceChanged(int index){
              desk.setIndex(index);
              desk.invalidate();

          }
      });

最主要的就是要在服务中实例化LrcDownloadManager的一个对象,调用加载歌词的方法,并完成歌词的制作(制作成我们需要的格式),这里定义了一个set方法添加监听器是为了方便除服务外地方使用这个功能,
public void setLrcChangedListener(OnLrcChangedListener lrcChangedListener){
        onLrcChangedListeners.add(lrcChangedListener);
        if(this.lrcDownLoadManager!=null){
            this.lrcDownLoadManager.setOnLrcChangedListener(lrcChangedListener);
            loadLrc();
        }
    }
    publicvoidloadLrc(){
        //下载歌词
        lrcDownLoadManager.getSongInfo(mdata.get(POSITION));
    }


做完这些还有最重要的一步,就是更新歌词了,利用handler的定时机制更新当前播放进度,
private Handler mServiceHandler = new Handler(){
        @Overridepublicvoid handleMessage(Message msg) {
            super.handleMessage(msg);
            if(mdata.get(POSITION).getTime()!=0){
                if(msg.what==MSG_TYPE_PROGRESS){//更新进度条,与桌面歌词功能无关
                    if(mState==State.PLAYING){
                        for(OnMusicPlayStateListener l:musicPlayStateListeners){
                            l.onProgressChanged(player.getCurrentPosition());
                        }

//定时每隔100毫秒,更新当前播放位置的索引
                        for(OnLrcChangedListener l:onLrcChangedListeners){
                            if(lrcDownLoadManager!=null){
                                if(l!=null)
                                    l.onLyricSentenceChanged(lrcDownLoadManager
                                            .lrcIndex((int) mdata.get(POSITION).getTime()
                                                    , player.getCurrentPosition()));

                            }
                        }
                       mServiceHandler.sendEmptyMessageDelayed(MSG_TYPE_PROGRESS, 100);//隔500毫秒发song
                    }
                }
            }

        }
    };

最后在添一个移除桌面 歌词的方法

public void removeFloatView(){
        if (wm != null && view != null) {
            wm.removeViewImmediate(view);
            //          wm.removeView(view);//不要调用这个,WindowLeaked
            view = null;
            wm = null;
        }<pre name="code" class="java">public float getShaderSpeed(){
        float speed = getCharacterWidth(infos.get(index).getCurrentContent(),60)/infos.get(index).getCurrentTime()/2;
        return speed;
    }

}

如果要实现歌词逐字渲染的效果,还需要再做些工作,因为我的desk(放歌词的textview)的宽度是match_parent,所以再计算渲染速度的时候就不能用这个宽度,需要写一个方法返回当前文本的宽度,下面的是我自定义盛放歌词的view的全部代码

package com.example.user.myapplication.myScroview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

import com.example.user.myapplication.LrcModel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by user on 2016/9/30.
 */
public class LrcView2 extends TextView {
    private int indexChanged = 0;
    boolean b = true;
    private float width;                   //歌词视图宽度
    private float height;                 //歌词视图高度
    private Paint currentPaint;          //当前画笔对象
    private Paint notCurrentPaint;      //非当前画笔对象
    private float textHeight = 70;      //文本高度
    private float textMaxSize = 60;
    private float textSize = 55;        //文本大小
    private int index = 0;              //list集合下标
    private List<LrcModel> infos;              //歌词信息
    private float float1 = 0.0f;
    private float float2 = 0.01f;
    private boolean whichLine = true;判断是第一行歌词还是第二行歌词
    private boolean whatLine = true;//判断是否需要切换歌词
    private int nextIndex;

    public LrcView2(Context context) {
        super(context);
        init();
    }

    public LrcView2(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }
    public LrcView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public void setLrcList(List<LrcModel> infos) {
        this.infos.clear();
        this.infos.addAll(infos);
    }

    private void init() {
        infos = new ArrayList<>();
        setFocusable(true);     //设置可对焦
        //显示歌词部分
        currentPaint = new Paint();
        currentPaint.setAntiAlias(true);    //设置抗锯齿,让文字美观饱满
        currentPaint.setTextAlign(Paint.Align.CENTER);//设置文本对齐方式

        //非高亮部分
        notCurrentPaint = new Paint();
        notCurrentPaint.setAntiAlias(true);
        notCurrentPaint.setTextAlign(Paint.Align.CENTER);
    }

    /**
     * 绘画歌词
     */
    @Override
    protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (canvas == null) {
                return;
            }
            currentPaint.setColor(Color.argb(210, 251, 248, 29));
            notCurrentPaint.setColor(Color.argb(140, 255, 255, 255));
            notCurrentPaint.setTextAlign(Paint.Align.CENTER);
            currentPaint.setTextAlign(Paint.Align.CENTER);
            currentPaint.setTextSize(textMaxSize);
            currentPaint.setTypeface(Typeface.SERIF);

            notCurrentPaint.setTextSize(textSize);
            notCurrentPaint.setTypeface(Typeface.DEFAULT);

        //如果index的大小改变重置float
        if(indexChanged!=index){
            indexChanged=index;
            float1 = 0;
            float2 =  0;

        }
        //设置渲染速度
        if(infos.size()!=0){
            if(float2 < 1.0){
                float1 +=  getShaderSpeed();
                float2 +=  getShaderSpeed();
            }
        }
        Log.i("width", float1 + "");
        if(infos.size()!=0){
            Shader shader = new LinearGradient(getBeginX(),0, getEndX(), 0, new int[] { Color.YELLOW,Color.GREEN},new float[]{float1, float2},Shader.TileMode.CLAMP);
            currentPaint.setShader(shader);
//第一个参数是渲染在X轴的起始位置,第二个是Y轴的起始位置,第三个是X轴的结束位置,第四个是Y轴的结束位置,第五个参数传入一组颜色,数组中的第一个颜色就是渲染后的颜色,第六个参数就是渲染的位置,1.0f表示全部渲染,最后一个参数类似于一些特效吧,<div style="">//可以看出渲染歌词的关键点就是第六个参数了,传入的位置不同渲染的位置就不同,因此我们只需要不停的调用ondraw方法,每次改变float的位置即可,</div>
 }
        float tempY = height / 2;
        tempY = tempY + textHeight;
            try {
                setText("");
                if(infos.size()!=0){//判断当前有没有歌词信息
                    if(infos.get(index).getCurrentContent().equals("")){
                        //当前时间段没有歌词
                        canvas.drawText("......", width /2, height/2 , currentPaint);
                    }else{
                            canvas.drawText(infos.get(index)
                                    .getCurrentContent(), width/2 , height /2, currentPaint);
                            canvas.drawText(infos.get(index+1)
                                    .getCurrentContent(), width/2 , tempY , notCurrentPaint);
                    }
                }else{
                    canvas.drawText("暂无歌词", width /2, height/2 , currentPaint);
                }


            } catch (Exception e) {
                 setText("");
                 setText("正在加载歌词...");
            }

        }

    /**
     * 当view大小改变的时候调用的方法
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.width = w;
        this.height = h;
    }
    //返回渲染的速度
    public float getShaderSpeed(){
        long time;
        if(index==0){
            time = infos.get(index).getCurrentTime();
        }else{
            time = infos.get(index).getCurrentTime()-infos.get(index-1).getCurrentTime();
        }
        float speed = (float)1.0/time*10;
        return speed;
    }
    //返回渲染起始点x位置
    public float getBeginX(){
        return   width/2-getCharacterWidth(infos.get(index).getCurrentContent(),60)/2;
    }
    //返回渲染结束点x位置
    public float getEndX(){
        return   width/2+getCharacterWidth(infos.get(index).getCurrentContent(),60)/2;
    }


    //获取当前歌词文本的宽度
    public float getCharacterWidth(String text,float size){
        if(text==null||text.equals("")){
            return 0;
        }
        Paint paint = new Paint();
        paint.setTextSize(size);
        float text_width= paint.measureText(text);//得到总体长度
        return text_width;
    }
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的VB6桌面歌词显示窗体模块的示例代码: ``` '模块名称: frmDesktopLyrics '功能:用于在桌面显示歌词 Option Explicit Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hwnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long Private Declare Function GetDesktopWindow Lib "user32" () As Long Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long Private Declare Function UpdateWindow Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal lpString As String, ByVal nCount As Long) As Long Private Declare Function SetTextColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long Private Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal nBkMode As Long) As Long Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private m_lyrics As String '歌词文本 Private m_lyricsFont As String '歌词字体 Private m_lyricsFontSize As Integer '歌词字体大小 Private m_lyricsColor As Long '歌词颜色 Private m_lyricsPosition As Integer '歌词位置 Private m_lyricsWindow As Long '歌词窗口句柄 Public Enum LyricsPosition Top = 0 Middle = 1 Bottom = 2 End Enum Public Property Let Lyrics(Text As String) m_lyrics = Text If m_lyricsWindow <> 0 Then UpdateLyrics End If End Property Public Property Let LyricsFont(FontName As String) m_lyricsFont = FontName If m_lyricsWindow <> 0 Then UpdateLyrics End If End Property Public Property Let LyricsFontSize(FontSize As Integer) m_lyricsFontSize = FontSize If m_lyricsWindow <> 0 Then UpdateLyrics End If End Property Public Property Let LyricsColor(Color As Long) m_lyricsColor = Color If m_lyricsWindow <> 0 Then UpdateLyrics End If End Property Public Property Let LyricsPosition(Position As LyricsPosition) m_lyricsPosition = Position If m_lyricsWindow <> 0 Then UpdateLyrics End If End Property Public Sub ShowLyrics() Dim desktopHDC As Long Dim lyricsHDC As Long Dim desktopRect As RECT Dim lyricsRect As RECT Dim desktopWidth As Long Dim desktopHeight As Long Dim lyricsWidth As Long Dim lyricsHeight As Long Dim lyricsX As Long Dim lyricsY As Long Dim lyricsRegion As Long Dim lyricsStyle As Long Dim lyricsFlags As Long '获取桌面的设备上下文句柄 desktopHDC = GetDC(GetDesktopWindow) '获取桌面的尺寸 GetClientRect GetDesktopWindow, desktopRect desktopWidth = desktopRect.Right - desktopRect.Left desktopHeight = desktopRect.Bottom - desktopRect.Top '创建歌词窗口 m_lyricsWindow = CreateWindow("", "", WS_POPUP Or WS_VISIBLE, 0, 0, 0, 0, 0, 0, App.hInstance, ByVal 0&) lyricsHDC = GetDC(m_lyricsWindow) '设置歌词字体、大小、颜色、位置 SetTextColor lyricsHDC, m_lyricsColor SetBkMode lyricsHDC, TRANSPARENT SelectObject lyricsHDC, CreateFont(m_lyricsFontSize, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_lyricsFont) Select Case m_lyricsPosition Case LyricsPosition.Top lyricsY = desktopHeight / 4 Case LyricsPosition.Middle lyricsY = desktopHeight / 2 Case LyricsPosition.Bottom lyricsY = desktopHeight * 3 / 4 End Select '获取歌词文本的尺寸 GetClientRect m_lyricsWindow, lyricsRect TextOut lyricsHDC, 0, 0, m_lyrics, Len(m_lyrics) lyricsWidth = lyricsRect.Right - lyricsRect.Left lyricsHeight = lyricsRect.Bottom - lyricsRect.Top '计算歌词窗口的位置 lyricsX = desktopWidth / 2 - lyricsWidth / 2 '设置歌词窗口的位置和尺寸 MoveWindow m_lyricsWindow, lyricsX, lyricsY, lyricsWidth, lyricsHeight, True '创建歌词窗口的区域 lyricsRegion = CreateRectRgn(0, 0, lyricsWidth, lyricsHeight) SetWindowRgn m_lyricsWindow, lyricsRegion, True '将歌词窗口置于桌面顶层 SetWindowPos m_lyricsWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOACTIVATE '将歌词窗口设置为半透明 lyricsStyle = GetWindowLong(m_lyricsWindow, GWL_EXSTYLE) SetWindowLong m_lyricsWindow, GWL_EXSTYLE, lyricsStyle Or WS_EX_LAYERED SetLayeredWindowAttributes m_lyricsWindow, 0, 128, LWA_ALPHA '更新歌词窗口 UpdateLyrics '释放设备上下文句柄 ReleaseDC GetDesktopWindow, desktopHDC ReleaseDC m_lyricsWindow, lyricsHDC End Sub Public Sub HideLyrics() '销毁歌词窗口 If m_lyricsWindow <> 0 Then DestroyWindow m_lyricsWindow m_lyricsWindow = 0 End If End Sub Private Sub UpdateLyrics() Dim lyricsHDC As Long Dim lyricsRect As RECT '获取歌词窗口的设备上下文句柄 lyricsHDC = GetDC(m_lyricsWindow) '设置歌词文本的位置和颜色 SelectObject lyricsHDC, CreateFont(m_lyricsFontSize, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_lyricsFont) SetTextColor lyricsHDC, m_lyricsColor '获取歌词文本的尺寸 GetClientRect m_lyricsWindow, lyricsRect '在歌词窗口上绘制歌词文本 TextOut lyricsHDC, 0, 0, m_lyrics, Len(m_lyrics) '更新歌词窗口 UpdateWindow m_lyricsWindow '释放设备上下文句柄 ReleaseDC m_lyricsWindow, lyricsHDC End Sub ``` 使用示例: ``` Private Sub Form_Load() '创建桌面歌词显示窗口 Dim desktopLyrics As frmDesktopLyrics Set desktopLyrics = New frmDesktopLyrics desktopLyrics.Lyrics = "Hello, world!" desktopLyrics.LyricsFont = "Arial" desktopLyrics.LyricsFontSize = 24 desktopLyrics.LyricsColor = vbRed desktopLyrics.LyricsPosition = LyricsPosition.Middle desktopLyrics.ShowLyrics End Sub ``` 注意事项: - 此示例代码仅供参考和学习,可能存在不足和错误,请谨慎使用。 - 由于桌面歌词显示窗口是在桌面上绘制的,因此在使用时应避免与其他桌面应用程序冲突。 - 在使用时应注意歌词窗口的位置和尺寸,以免遮挡其他桌面元素和应用程序窗口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值