前在網(wǎng)上有一位VB高手,用vb6.0做了一個光標(biāo)跟隨的代碼,我現(xiàn)在把它改為vb.net的代碼。
不過,這個光標(biāo)跟隨的效果,在某些程序的文本編輯器里沒有效果,我猜想這些沒有效果的所謂光標(biāo),是假的光標(biāo),是模擬的光標(biāo)。
還有些場景,比如,瀏覽器里,有時有效果,有時沒有效果。我在瀏覽器的百度搜索框里,光標(biāo)跟隨有些有效果,有時卻沒有效果,原因不明。
下面是代碼
Public Class Form1
'獲得擁有輸入焦點(diǎn)的窗口的句柄
Private Declare Function GetFocus Lib "user32" () As Integer
'獲得前臺窗口的句柄。這里的“前臺窗口”是指前臺應(yīng)用程序的活動窗口
Private Declare Function GetForegroundWindow Lib "user32" () As Integer
'通常,系統(tǒng)內(nèi)的每個線程都有自己的輸入隊(duì)列。本函數(shù)(既“連接線程輸入函數(shù)”)允許線程和進(jìn)程共享輸入隊(duì)列。連接了線程后,輸入焦點(diǎn)、窗口激活、鼠標(biāo)捕獲、鍵盤狀態(tài)以及輸入隊(duì)列狀態(tài)都會進(jìn)入共享狀態(tài)
Private Declare Function AttachThreadInput Lib "user32" (ByVal idAttach As Integer, ByVal idAttachTo As Integer, ByVal fAttach As Integer) As Integer
'獲取當(dāng)前線程一個唯一的線程標(biāo)識符
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Integer
'獲取與指定窗口關(guān)聯(lián)在一起的一個進(jìn)程和線程標(biāo)識符
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
'暫停線索
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)
'判斷插入符的當(dāng)前位置
Private Declare Function GetCaretPos Lib "user32" (ByRef lpPoint As POINTAPI) As Integer
Private Structure POINTAPI
Dim x As Integer
Dim y As Integer
End Structure
'判斷窗口內(nèi)以客戶區(qū)坐標(biāo)表示的一個點(diǎn)的屏幕坐標(biāo)
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Integer, ByRef lpPoint As POINTAPI) As Integer
'這個函數(shù)能為窗口指定一個新位置和狀態(tài)。它也可改變窗口在內(nèi)部窗口列表中的位置。該函數(shù)與DeferWindowPos函數(shù)相似,只是它的作用是立即表現(xiàn)出來的(在vb里使用:針對vb窗體,如它們在win32下屏蔽或最小化,則需重設(shè)最頂部狀態(tài)。如有必要,請用一個子類處理模塊來重設(shè)最頂部狀態(tài)
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
Private Const SWP_NOACTIVATE As Short=&H10S
Private Const SWP_NOSIZE As Short=&H1S
Private Const SWP_SHOWWINDOW As Short=&H40S
Private Const HWND_TOPMOST As Short=-1
Sub Gen()
Dim FoHandle As Integer
Dim PHandle As Integer
Dim ThisPoint As Integer
Dim Point As POINTAPI
FoHandle=GetFocus
PHandle=GetForegroundWindow
AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(PHandle, 0), 1)
ThisPoint=GetCaretPos(Point)
ClientToScreen(FoHandle, Point)
If FoHandle <> Me.Handle.ToInt32 Then
System.Windows.Forms.Application.DoEvents()
'Debug.Print Form1.Left
SetWindowPos(Me.Handle.ToInt32, HWND_TOPMOST, Point.x, Point.y + 22, 0, 0, SWP_NOACTIVATE Or SWP_NOSIZE Or SWP_SHOWWINDOW)
System.Windows.Forms.Application.DoEvents()
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Timer1.Interval=100 '設(shè)置成每秒觸發(fā)一次事件
Call Gen()
End Sub
End Class
運(yùn)行環(huán)境:visual studio 2022 運(yùn)行效果如下:
<script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>
跟隨鼠標(biāo)的位置,在VB.NET相對來說,比較簡單,可以用Cursor.Position.X 和 Cursor.Position.Y 得到鼠標(biāo)的位置,我用計(jì)時器來實(shí)現(xiàn)窗口隨時跟隨鼠標(biāo)的位置。
代碼如下:
Public Class Form1
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
Private Const HWND_TOPMOST As Short=-1
Private Const SWP_NOACTIVATE As Short=&H10S
Private Const SWP_NOSIZE As Short=&H1S
Private Const SWP_SHOWWINDOW As Short=&H40S
Dim WZX, WZY As Integer '鼠標(biāo)的位置
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
WZX=Cursor.Position.X ' 得到鼠標(biāo)的位置
WZY=Cursor.Position.Y
SetWindowPos(Me.Handle.ToInt32, HWND_TOPMOST, WZX, WZY, 0, 0, SWP_NOACTIVATE Or SWP_NOSIZE Or SWP_SHOWWINDOW)
'鼠標(biāo)的縱坐標(biāo) + 30 ,防止窗體太靠近光標(biāo)
End Sub
End Class
效果如下:
<script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>
對了,拖一個計(jì)時器到窗體上,先在屬性欄里,請把計(jì)時器的Enabled設(shè)置為True
的教程一共九套及VBA漢英手冊一部,分為初級、中級、高級三大部分。是對VBA的系統(tǒng)講解,從簡單的入門,到數(shù)據(jù)庫,到字典,到高級的網(wǎng)抓及類的應(yīng)用。大家在學(xué)習(xí)的過程中可能會存在困惑,這么多知識點(diǎn)該如何組織成自己的程序呢?VBA可否能組織一個大型的程序呢?如何讓VBA形成一個工具,拿來就用呢?在我的教程完結(jié)后,我陸續(xù)推出這類技術(shù)工具資料,這類工具整合了若干多的VBA知識點(diǎn),讓大家感受到VBA之強(qiáng)大。工具資料共兩個系列,一個是YZ系列,一個是NZ系列。今日給大家介紹的是VBA_NZ系列工具NZ11:VBA光標(biāo)跟隨策略
【分享成果,隨喜正能量】 人生有可為之事,也有不可為之事。可為之事,當(dāng)盡力為之,此謂盡性;不可為之事,當(dāng)盡心從之,此謂知命。。
這個應(yīng)用工具將展現(xiàn)給大家如何利用VBA代碼進(jìn)行光標(biāo)的跟隨操作,與其說是一個工具,不如說這是一個非常好的VBA實(shí)例應(yīng)用教程。因?yàn)檫@個工具中集合了非常多的VBA操作,如窗體、類模塊、圖形操作、菜單的操作等等。
工具的核心代碼我封裝在FollowMouse.xlam的加載項(xiàng)中,使用的時候可以直接打開這個加載項(xiàng),就可以利用了。工具是開放源碼的(注意VBE的打開密碼是123456789,但強(qiáng)烈建議您不要輕易打開代碼窗口,即使打開也要留有備份)。
1 打開任意一個EXCEL文件,如下截圖:
2 打開我提供的加載項(xiàng)文件FollowMouse.xlam,雙擊即可打開。
3 此時EXCEL文件的界面變化:
我們會發(fā)現(xiàn)多了一個菜單:NZFM, 兩個線條,這個兩個線條指向了鼠標(biāo)當(dāng)前位置。
我們點(diǎn)擊NZFM菜單:
此時我們會發(fā)現(xiàn)有5個子菜單,我們點(diǎn)擊“格式設(shè)置‘:
’
這里就可以設(shè)置線條和箭頭了。
NZ11工具利用到的技術(shù)總結(jié)如下:
1 自定義菜單欄的添加
2 圖形的繪制
3 圖形的修改
4 顏色的拾取
5 類模對象實(shí)例化的操作
【分享成果,隨喜正能量】
下面是NZ系列VBA應(yīng)用工具:
篇教程將展示如何制作一個可以跟隨鼠標(biāo)移動導(dǎo)航菜單特效,enjoy~
完成圖層創(chuàng)建后,我們對鼠標(biāo)移動到按鈕上,焦點(diǎn)背景跟隨鼠標(biāo)移動的特效。
點(diǎn)擊“菜單A”圖層,在觸發(fā)面板選擇“鼠標(biāo)懸浮”,同時在該觸發(fā)效果下選擇“移動”選項(xiàng),并且將坐標(biāo)值設(shè)置為“X:88 / Y:80.75”。使用相同的方法,對“菜單B”和“菜單C”進(jìn)行設(shè)置,坐標(biāo)軸分別為:“X:187.5 / Y:80.75”和“X:287 / Y:80.75”。
完成以上設(shè)置,我們可以看到跟隨鼠標(biāo)移動的導(dǎo)航特效已經(jīng)完成。
下一步我們來制作點(diǎn)擊按鈕后,焦點(diǎn)背景圓角變化的特效。這里我們會用到“下?lián)簟薄ⅰ疤稹?個動作來模擬“鼠標(biāo)點(diǎn)擊”和“松開鼠標(biāo)”的動作。
選擇“菜單A”圖層,在觸發(fā)面板選擇“下?lián)簟保瑫r在該觸發(fā)效果下選擇“圓角”選項(xiàng),并且將圓角值設(shè)置為50。
完成了模擬鼠標(biāo)點(diǎn)擊的特效,下一步我們使用相同的方法完成鼠標(biāo)抬起的特效。選擇“菜單A”圖層,在觸發(fā)面板選擇“抬起”,同時在該觸發(fā)效果下選擇“圓角”選項(xiàng),并且將圓角值設(shè)置為5。
使用“菜單A”相同的設(shè)置去設(shè)置“菜單B”“菜單C”,設(shè)置完成后,就可以看到最終的演示效果。
作者,ioioi,ZQZ原型師,專注原型設(shè)計(jì)/交互設(shè)計(jì)
本文由 @ioioi 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載。
題圖來自 Unsplash,基于CC0協(xié)議。