zoukankan      html  css  js  c++  java
  • 用代码移动桌面图标(贪吃蛇)

    效果图

    实例.gif

    前言

    记得上高二的时候,闲来无事,上b站搜电脑病毒的视频看(不要问我为什么会搜这个),看到一个很有意思的"病毒",其实也不算病毒,它会控制桌面图标形成一个人形,并跳舞,跳完之后电脑就蓝屏了.之后下定决心也要整一个,埋头研究了两个星期吧,写了一个贪吃蛇,此贪吃蛇非彼贪吃蛇,它当然是控制的桌面图标来玩啦,还写了个网络版的,通过手机去控制.

    贪吃蛇效果

    本文章只介绍如何移动图标,不介绍贪吃蛇实现(源码太多),可以评价私信要源码

    实例.gif

    实现思路

    说到这,真的很后悔以前没第一个学c语言,反而学了vb,现在被其他语言搞得没有精力去学了,并没有说vb不好,它也很强大,只是它封装了很多,让很多人接触底层得知识更少了,比如窗体,归根到底,所有窗体都是用CreateWindow 函数来创建,但是学了vb,谁会傻到在用CreateWindow来创建窗口呢?

    好了,说原理吧.
    首先要了解什么是句柄,通俗得讲它就是一个整数,具体它标识窗口、位图、画笔等对象,并且是不变得整数,就像身份证一样,当人出生后,必定会有一个18位的身份证号,并且是不变得,通过它,可以知道某人得姓名,地址,年龄等信息,句柄也是如此.

    上面所说的CreateWindow,当它成功创建一个窗口后,它的返回值就是一个句柄,你拿到这个句柄后,你就可以对它做你想做的事了,比如用SetWindowText 给它设置一个标题.

    明白了句柄,现在就要拿到桌面的句柄,对它进行控制,用spy++可以分析一下它

    image.png

    这里有一点不一样,在windows7中,它的父窗口类名是Program Manage,但是在windows10中,它的类名是WorkerW,并且有多个WorkerW.下图是windows 7中

    image.png

    但是这不影响我们.从中可以看到,桌面就是一个ListView,我们只要拿到它的句柄,就可以对他进行控制.

    获取桌面句柄

    需要用到api:
    FindWindow:根据窗口的类名和窗口名称匹配指定的窗口,并且返回这个窗口的句柄
    FindWindowEx:根据所在的父窗口中查找类名和窗口名称匹配的窗口,并且返回这个窗口的句柄

    查找桌面句柄如下.
    注:在win7下可就不这么写了,

    Private Function getDesktopHwnd() As Long
    Dim hwndWorkerW As Long, hwndShelldll As Long, hwndDesktop As Long
    
    Do While (hwndDesktop = 0)
        hwndWorkerW = FindWindowEx(0, hwndWorkerW, "WorkerW", vbNullString)
            If (hwndWorkerW <> 0) Then
                hwndShelldll = FindWindowEx(hwndWorkerW, 0, "SHELLDLL_DefView", vbNullString)
       
                hwndDesktop = FindWindowEx(hwndShelldll, 0, "SysListView32", vbNullString)
            End If
    Loop
    getDesktopHwnd = hwndDesktop
    End Function
    

    移动图标

    知道了桌面的句柄,然后就是移动图标了
    既然桌面就是一个ListView,那么只需要给ListView发送一个LVM_SETITEMPOSITION消息来设置item的位置.
    如果你对windows机制不太了解的话,可能不明白为何要这样做,简单说一下,windows是根据消息来驱动程序运行的,例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序,应用程序会在一个叫窗口过程函数的地方处理消息,windows定义了大量的消息,列入:WM_CLOSE,对这个窗口发送WM_CLOSE,如果应用程序不做特殊处理的话,窗口就会关闭,

    如果对ListView操作的话,就需要发送以LVM开头的消息,WM开头的是窗口消息,还有对列表框的消息LB_xxx

    发送消息可以用SendMessage函数或PostMessage,区别在于使用PostMessage是立即返回,SendMessage需要等待应用程序处理完之后返回,在这里我们也不需要等待程序返回,所以用PostMessage.

    看一下PostMeeage的定义

    image.png
    参数hwnd:消息接收的窗口句柄
    参数msg:具体消息
    参数wparam和lparam:其他特定于消息的信息。

    在看一下LVM_SETITEMPOSITION消息的定义

    image.png

    也就是说,使用PostMeeage投递LVM_SETITEMPOSITION消息的时候,参数wparam是某个图标的索引,lparam是位置.
    但是如何用一个整数标识一个坐标呢,在c中可以用MAKELPARAM来获取,vb中可没有这样的方法,那就自己写一个

    Public Function MAKELPARAM(ByVal l As Integer, ByVal h As Integer) As Long
    Dim ll As String
    Dim lh As String
    Dim r As String
    ll = Format(Hex(l), "@@@@")
    lh = Format(Hex(h), "@@@@")
    Dim result As Long
    
    result = CLng("&h" & Replace(lh & ll, " ", "0"))
     MAKELPARAM = result
     
    End Function
    

    全部代码

    Private Const LVM_FIRST As Long = &H1000
    
    Private Declare Function GetDesktopWindow Lib "user32.dll" () As Long
    
    Private Const LVM_SETITEMPOSITION32 As Long = (LVM_FIRST + 49)
    Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    
    Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    
    Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    
    Private Const LVM_SETITEMPOSITION As Long = (LVM_FIRST + 15)
    
    Private Type POINTAPI
        x As Long
        y As Long
    End Type
    
    Dim curPoint As POINTAPI
    
    Dim listViewhwnd As Long
    
    Public Function MAKELPARAM(ByVal l As Integer, ByVal h As Integer) As Long
    Dim ll As String
    Dim lh As String
    Dim r As String
    ll = Format(Hex(l), "@@@@")
    lh = Format(Hex(h), "@@@@")
    Dim result As Long
    
    result = CLng("&h" & Replace(lh & ll, " ", "0"))
     MAKELPARAM = result
     
    End Function
    
    
    Private Function getDesktopHwnd() As Long
    Dim hwndWorkerW As Long, hwndShelldll As Long, hwndDesktop As Long
    
    Do While (hwndDesktop = 0)
        hwndWorkerW = FindWindowEx(0, hwndWorkerW, "WorkerW", vbNullString)
            If (hwndWorkerW <> 0) Then
                hwndShelldll = FindWindowEx(hwndWorkerW, 0, "SHELLDLL_DefView", vbNullString)
       
                hwndDesktop = FindWindowEx(hwndShelldll, 0, "SysListView32", vbNullString)
            End If
    Loop
    getDesktopHwnd = hwndDesktop
    End Function
    Private Sub Form_Load()
    listViewhwnd = getDesktopHwnd()
    
    End Sub
    
    Private Sub Timer1_Timer()
    curPoint.x = curPoint.x + 10
    
    PostMessage listViewhwnd, LVM_SETITEMPOSITION, 10, MAKELPARAM(curPoint.x, 110)
    End Sub
    
    

    注:右击桌面--->查看---->自动排列图标 、将图标和网格对齐 需要取消勾选

  • 相关阅读:
    vue input输入框验证10的n次方
    Django2.2使用mysql数据库pymysql版本不匹配问题的解决过程与总结
    数据结构(四):树
    数据结构(三):队列
    数据结构(二):栈
    数据结构(一):链表
    python深拷贝与浅拷贝
    python yield、yield from与协程
    python __getattribute__、__getattr__、__setattr__详解
    python迭代、可迭代对象、迭代器及生成器
  • 原文地址:https://www.cnblogs.com/HouXinLin/p/11072503.html
Copyright © 2011-2022 走看看