ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 4654|回复: 16

[原创] 鼠标屏幕点位置转换成EXCEl中磅坐标支持冻结缩放

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-2-7 12:03 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:工作表和工作簿
#If VBA7 And Win64 Then

Public Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As Long
Public Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hdc As LongPtr, ByVal nIndex As LongPtr) As Long
Public Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
#Else

Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Public Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
#End If
'鼠标屏幕坐标(x0,y0) 返回对应EXCEl窗口中位置磅(x,y)
Function CellScreenPos(x0 As Long, y0 As Long) As Variant
    Const SplitBarWidth = 6
    Const SplitBarHeight = 6
    Const RoundConst = 0.5000001
    Dim Wn As Window
    Dim hdc As Long, px As Long, py As Long
    Dim x As Double, y As Double '返回鼠标坐标在Excel屏幕中的位置
    Dim dx As Double, dy As Double '相对拆分线的距离
    Dim z As Double, spx As Double, spy As Double
    On Error GoTo ErrorHandler
    hdc = GetDC(0)
    px = GetDeviceCaps(hdc, LOGPIXELSX) '获取屏幕分辨率
    py = GetDeviceCaps(hdc, LOGPIXELSY) '获取屏幕分辨率
    ReleaseDC 0, hdc: hdc = 0
    Set Wn = ActiveWindow
    z = Wn.Zoom / 100 'Excel缩放因子
    spx = Wn.SplitHorizontal * px / 72 + RoundConst '垂直拆分线和Excel窗口左边距离
    spy = Wn.SplitVertical * py / 72 + RoundConst '水平拆分线和Excel窗口上边距离
    If Application.Version >= 12 Then
         ppx = ActiveWindow.Panes(1).PointsToScreenPixelsX(0) 'Excel坐标原点
         ppy = ActiveWindow.Panes(1).PointsToScreenPixelsY(0) 'Excel坐标原点
    Else
         ppx = ActiveWindow.PointsToScreenPixelsX(0) 'Excel坐标原点
         ppy = ActiveWindow.PointsToScreenPixelsY(0) 'Excel坐标原点
    End If
    dx = x0 - ppx - Cells(Wn.Panes(1).ScrollRow, Wn.Panes(1).ScrollColumn).Left * px * z / 72 - spx
    dy = y0 - ppy - Cells(Wn.Panes(1).ScrollRow, Wn.Panes(1).ScrollColumn).Top * py * z / 72 - spy
    If dx > 0 Then If Not Wn.FreezePanes Then x = x - SplitBarWidth '如果拆分线未冻结
    If dy > 0 Then If Not Wn.FreezePanes Then y = y - SplitBarHeight '如果拆分线未冻结
    Select Case Sgn(Wn.SplitVertical) * 2 + Sgn(Wn.SplitHorizontal)
        Case 0
                x = x0 - ppx
                y = y0 - ppy
        Case 2 '水平
            If dy >= 0 Then
                x = x0 - ppx
                y = y + dy + Cells(Wn.Panes(2).ScrollRow, Wn.Panes(2).ScrollColumn).Top * py * z / 72
            Else
                x = x0 - ppx
                y = y0 - ppy
            End If
        Case 1 '垂直
            If dx >= 0 Then
                x = x + dx + Cells(Wn.Panes(2).ScrollRow, Wn.Panes(2).ScrollColumn).Left * px * z / 72
                y = y0 - ppy
            Else
                x = x0 - ppx
                y = y0 - ppy
            End If
        Case 3 '水平垂直
            If dy >= 0 And dx < 0 Then
                 x = x0 - ppx
                 y = y + dy + Cells(Wn.Panes(3).ScrollRow, Wn.Panes(3).ScrollColumn).Top * py * z / 72
            ElseIf dy >= 0 And dx >= 0 Then
                 x = x + dx + Cells(Wn.Panes(4).ScrollRow, Wn.Panes(4).ScrollColumn).Left * px * z / 72
                 y = y + dy + Cells(Wn.Panes(4).ScrollRow, Wn.Panes(4).ScrollColumn).Top * py * z / 72
            End If
            If dy < 0 And dx < 0 Then
                 x = x0 - ppx
                 y = y0 - ppy
            ElseIf dy < 0 And dx >= 0 Then
                 x = x + dx + Cells(Wn.Panes(2).ScrollRow, Wn.Panes(2).ScrollColumn).Left * px * z / 72
                 y = y0 - ppy
            End If
    End Select
    x = x * 72 / (px * z)
    y = y * 72 / (py * z)
    CellScreenPos = Array(x, y)
    Exit Function
ErrorHandler:
    If hdc <> 0 Then ReleaseDC 0, hdc
    Exit Function
End Function

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-2-7 15:08 | 显示全部楼层
测试.zip (18.29 KB, 下载次数: 63)

TA的精华主题

TA的得分主题

发表于 2015-2-7 23:22 | 显示全部楼层
本帖最后由 liucqa 于 2015-2-7 23:31 编辑

好像有点小问题

1、缩小比例之后,位置偏左了
2、2013下,从400%点击滚动条缩小窗口比例,会发现工作表上也出现点了,大概是识别的问题。

支持一下,争取完善!

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-2-10 12:04 | 显示全部楼层
有点偏移不是程序本身问题,而是excel提供的ActiveWindow.Zoom的问题在缩小过程中理论上磅/像素是不变的,而实测的磅/像素是不同的,这就说明缩小过程中Zoom值是近视值,如果要在缩小过程中也能准确,那么需要采样实际的缩放比例来代替ActiveWindow.Zoom这个值

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-2-10 14:39 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2015-2-11 12:14 | 显示全部楼层
qqhuanxiang 发表于 2015-2-10 12:04
有点偏移不是程序本身问题,而是excel提供的ActiveWindow.Zoom的问题在缩小过程中理论上磅/像素是不变的,而 ...

应该有解决办法的

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-2-28 11:45 | 显示全部楼层
经过修正ActiveWindow.Zoom测试程序提供在此。请测试,应该是精确定位到一个像素 测试.zip (20.21 KB, 下载次数: 41)

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-2-28 11:58 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2015-2-28 23:02 | 显示全部楼层
qqhuanxiang 发表于 2015-2-28 11:45
经过修正ActiveWindow.Zoom测试程序提供在此。请测试,应该是精确定位到一个像素

捕获.JPG

第二个问题没解决

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-3-1 09:43 | 显示全部楼层
liucqa 发表于 2015-2-28 23:02
第二个问题没解决

这只是个测试程序,你是否需要如下效果

Function test() '测试程序鼠标左键开始右键停止
    Dim lngCurPos As POINTAPI
    On Error Resume Next
    Dim scalefact As Variant
    scalefact = okzoom(x, y)
    EnableHook
    GetCursorPos lngCurPos
    If ActiveWindow.RangeFromPoint(lngCurPos.x, lngCurPos.y) Is Nothing Then Exit Function '点工作表区域外,程序不打点?
    Dim pp As Variant
    pp = CellScreenPos(lngCurPos.x, lngCurPos.y, scalefact(0), scalefact(1))
    Set shp = ActiveSheet.Shapes.AddShape(9, pp(0) - 0.5, pp(1) - 0.5, 1, 1)
   
End Function
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-24 22:47 , Processed in 0.043938 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表