- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我长期以来一直使用这个网站来寻找我的问题的答案,但我找不到关于这个问题的任何信息。如果我错过了什么,请提前道歉。
所以我有一个工作簿(Office 2013,VBA 7.1),我试图将用户窗体用作菜单,该菜单将在页面上保持静止并随工作簿移动。我使用了 http://www.cpearson.com/excel/SetParent.aspx 中的代码组合将表单锁定到窗口和http://www.oaltd.co.uk/Excel/Default.htm (FormFun.zip)从表单中删除标题并防止它在页面上移动。
此代码运行良好,但我一直遇到一个奇怪的错误,其中插入的表单“.Top”值与我在代码中分配的值不同。我也让一位同事运行代码并遇到同样的问题。我将在下面列出代码的相关部分。
我在模块(Module1)中有以下代码:
Sub CallFormTestA()
With UserForm1
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
.Top = 147
End With
End Sub
Option Explicit
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
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 FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
Private Const GWL_STYLE As Long = (-16) 'The offset of a window's style
Private Const WS_CAPTION As Long = &HC00000 'Style to add a titlebar
Private Sub SetBit(ByRef lStyle As Long, ByVal lBit As Long, ByVal bOn As Boolean)
If bOn Then
lStyle = lStyle Or lBit
Else
lStyle = lStyle And Not lBit
End If
End Sub
Private Sub Userform_Initialize()
Dim MeHWnd, ApphWnd, DeskhWnd, WindowhWnd, Res, lStyle As Long
'Get the window handle of the main Excel application window.
ApphWnd = Application.hwnd
If ApphWnd > 0 Then
'Get the window handle of the Excel desktop.
DeskhWnd = FindWindowEx(ApphWnd, 0&, "XLDESK", vbNullString)
If DeskhWnd > 0 Then
'Get the window handle of the ActiveWindow.
WindowhWnd = FindWindowEx(DeskhWnd, 0&, "EXCEL7", ActiveWindow.Caption)
If WindowhWnd > 0 Then
'OK
Else
MsgBox "Unable to get the window handle of the ActiveWindow."
End If
Else
MsgBox "Unable to get the window handle of the Excel Desktop."
End If
Else
MsgBox "Unable to get the window handle of the Excel application."
End If
MeHWnd = FindWindow("ThunderDFrame", Me.Caption)
If MeHWnd = 0 Then Exit Sub
lStyle = GetWindowLong(MeHWnd, GWL_STYLE)
SetBit lStyle, WS_CAPTION, False
SetWindowLong MeHWnd, GWL_STYLE, lStyle
If (MeHWnd > 0) And (WindowhWnd > 0) Then
Res = SetParent(MeHWnd, WindowhWnd)
If Res = 0 Then
MsgBox "The call to SetParent failed."
End If
End If
End Sub
With UserForm1
Debug.Print .Top 'Returns 139.5 then 286.5
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
.Top = 147
Debug.Print .Top 'Returns 286.5 then 286.5
End With
With UserForm1
Debug.Print .Top '139.5 then 286.5
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
.Top = .Top - .Top 'Changed
Debug.Print .Top '139.5 then 139.5
.Top = 147
Debug.Print .Top '286.5 then 286.5
End With
With UserForm1
Debug.Print .Top 'Returns 139.5 then 286.5
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
.Top = -.Top 'Changed
Debug.Print .Top 'Returns -372 then -147
.Top = 147
Debug.Print .Top 'Returns 286.5 then 286.5
End With
With UserForm1
Debug.Print .Top '139.5 then 286.5
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
.Top = Abs(-.Top) 'Changed
Debug.Print .Top '511.5 then 286.5
.Top = 147
Debug.Print .Top '286.5 then 286.5
End With
With UserForm1
Debug.Print .Top '286.5 then 286.5
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
.Top = 0 'Changed
Debug.Print .Top '139.5 then 139.5
.Top = 147
Debug.Print .Top '286.5 then 286.5
End With
Dim n As Long 'Tried using an integer to store the .top value
With UserForm1
Debug.Print .Top '139.5 then 286.5
.Show vbModal = False
.StartUpPosition = 0
.Left = 17
n = .Top 'This drops the decimal, but I don't care about that.
Debug.Print .Top & ", " & n '511.5, 512 then 286.5, 286
.Top = .Top - n
Debug.Print .Top '138.75 then 140.25
.Top = 147
Debug.Print .Top '286.5 then 286.5
End With
If (MeHWnd > 0) And (WindowhWnd > 0) Then
Res = SetParent(MeHWnd, WindowhWnd)
If Res = 0 Then
MsgBox "The call to SetParent failed."
End If
End If
Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
最佳答案
Dasmittel,我似乎正在走你的确切道路(尽管 4 年后),想知道你在那段时间是否取得了任何进展?作为记录,我已经在 Excel 2007 和(当前)Excel 2013 中处理了这个问题,就像您在示例案例中一样。
我还使用 Chip Pearson 代码(我在上面认识)使 userform 成为工作表的子项。和你一样,我也确定 SetParent 调用正在扩大定位。
'<=== Form IS correctly positioned here
Res = SetParent(hWndChild:=ChildHWnd, hWndNewParent:=ParentHWnd)
'<=== Form is NOT correctly positioned here
设置/更改用户窗体的父级也是使用户窗体相对于给定单元格定位的各种解决方案不起作用的原因。这是因为:
.Left = 10: '--> Debug.Print .Left = 149
我不明白的是为什么设置.Left也会改变.Top(同样设置.Top也会改变.Left)?!
Declarations
Private Type POINTAPI
x As Long
y As Long
End Type
#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare PtrSafe Function ScreenToClient Lib "user32.dll" (ByVal hwnd As Long, ByRef lpPoint As POINTAPI) As Long
Private Declare PtrSafe Function SetParent Lib "user32.dll" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Private Declare PtrSafe Function SetWindowPos Lib "user32.dll" (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 PtrSafe Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
#Else
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongLong
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As Long) As LongLong
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As LongLong
Private Declare PtrSafe Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As LongLong
Private Declare PtrSafe Function ScreenToClient Lib "user32.dll" (ByVal hwnd As Long, ByRef lpPoint As POINTAPI) As LongLong
Private Declare PtrSafe Function SetParent Lib "user32.dll" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As LongLong
Private Declare PtrSafe Function SetWindowPos Lib "user32.dll" (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 LongLong
Private Declare PtrSafe Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongLong
#End If
Private Declare PtrSafe Function WindowFromAccessibleObject Lib "oleacc" (ByVal pacc As IAccessible, phwnd As Long) As Long
#Else
Private Declare Function WindowFromAccessibleObject Lib "oleacc" (ByVal pacc As IAccessible, phwnd As Long) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hDC As Long) As Long
Private Declare Function ScreenToClient Lib "user32.dll" (ByVal hwnd As Long, ByRef lpPoint As POINTAPI) As Long
Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Private Declare Function SetWindowPos Lib "user32.dll" (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 ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
#End If
Public Sub PositionUserForm(Target As Range, frm As UserForm)
Const SWP_NOSIZE = &H1
Const SW_SHOW = 5
Dim pt As POINTAPI
Dim OffsetX As Long
Dim OffsetY As Long
Dim EXCEL7Hwnd As Long
Dim UserFormHwnd As Long
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' *Should* be the screen coords of the leftmost, visible range
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
OffsetX = ActiveWindow.PointsToScreenPixelsX(0)
OffsetY = ActiveWindow.PointsToScreenPixelsY(0)
pt.x = OffsetX + PointsToPixels(ActiveWindow.PointsToScreenPixelsX(Target.Left) - OffsetX, "X")
pt.y = OffsetY + PointsToPixels(ActiveWindow.PointsToScreenPixelsY(Target.Top) - OffsetY, "Y")
WindowFromAccessibleObject frm, UserFormHWnd
EXCEL7Hwnd = FindWindowEx(FindWindowEx(Application.hwnd, 0, "XLDESK", vbNullString), 0, "EXCEL7", vbNullString)
SetParent UserFormHwnd, EXCEL7Hwnd
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Note: In simple terms, the userform does not scroll with the worksheet. So you need to be
' sure that the cell you are using to position the userform is physically (in regards to
' Excel) positioned where the userform needs to be placed. Failure to do so, will result
' in an incorrectly placed (and possibly "invisible") userform.
'
' In a little more detail, the coords used in this subroutine are based upon a "virtual"
' desktop that extends beyond the Excel window. The *initial* location of the cell used
' for positioning upon this virtual desktop is critical. If the "home" cell is off the
' visible screen when the userform is positioned, the userform will be "visible" but
' permanently off screen until the appropriate .left or .top property is corrected.
'
' Personally, I place the userform over cell A1 and want the userform to cover the top/
' leftmost corner of usable window/area of the worksheet.
'
' If row 1 is scrolled off the top of the screen, pt.x will be negative.
' If column A is scrolled off the left of the screen, pt.y will be negative.
' In either case, your userform will be "Visible" but placed OUTSIDE of the visible window.
'
' A1 can neither be scrolled off the bottom or right the screen. However should you use a
' different cell, then that cell *could* be scrolled down and/or right which would result
' in an incorrectly larger positive value for .left and/or .top and possibly therefore an
' incorrectly placed userform. Should the number be large enough, the userform, though
' "visible" would be permanently placed oustide of the visible window.
'
' Should your userform be displayed outside of the visible screen, you will want to correct
' its position by adjusting .left or .top. Know that after having been made a child of the
' workbook, the userform's .left and .top will no longer work as expected (the very reason
' this routine is needed to properly place it). This is because .left and .top are based
' upon SCREEN positioning while after being made a child, the userform's .top and .left are
' based upon the Excel window's posititon AND also use a different unit of measure than
' previously.
'
' Additionally, note that after making the userform a child of the workbook, changing
' either of these two properties also changes *the other*?!! This seems to be an error
' in Excel (I am using Excel 2013) as noted in a previous post in this thread. If the userform
' is off screen, you can change either .Left or .Top. Once the userform appears on screen,
' drag it to where you want with the mouse.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Translate screen coords to client (new parent) coords
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ScreenToClient EXCEL7Hwnd, pt
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' SWP_NOSIZE tells the function to ignore the height and width args
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SetWindowPos UserFormHwnd, 0, pt.x, pt.y, 0, 0, SWP_NOSIZE
ShowWindow UserFormHwnd, SW_SHOW
End Sub
Private Function PointsToPixels(Pts As Double, Axis As String) As Long
Const WU_LOGPIXELSX = 88
Const WU_LOGPIXELSY = 90
Dim hdc As Long
hdc = GetDC(0)
PointsToPixels = (Pts / (72 / GetDeviceCaps(hdc, IIf(Axis = "X", WU_LOGPIXELSX, WU_LOGPIXELSY)))) * (ActiveWindow.Zoom / 100)
ReleaseDC 0, hdc
End Function
Public Sub GotoHomeCell
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' I am showing my low level of vba programming skills with this subroutine's method of
' being certain that the correct worksheet is active and that cell A1 is top/left
' so that the userform is correctly situated. I tried various ways and was not happy
' with the results. This while surely not optimal seems to work. I'd love a better
' solution should someone want to correct this.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Be sure A1 is displayed on screen
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sheets("GameDev").Activate
ActiveSheet.Range("A1").Select 'Goto ActiveCell did not seem to work without EntireRow but...
Application.Goto ActiveCell.EntireRow, True 'Leaves entire row selected so... next line...
ActiveSheet.Range("A1").Select
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Display userform in correct position
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Call PositionUserForm(Range("A1"), MyUserForm) '< Set flag? In theory, only need to execute PositionUserForm ONCE?
End Sub
这一行进入用户窗体的 UserForm_Initialize:
Call GotoHomeCell
请注意,我调用了 GotoHomeCell
关于vba - UserForm.Top 值从已分配更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35321580/
我长期以来一直使用这个网站来寻找我的问题的答案,但我找不到关于这个问题的任何信息。如果我错过了什么,请提前道歉。 所以我有一个工作簿(Office 2013,VBA 7.1),我试图将用户窗体用作菜单
我有一个柜台NumObjects我在 UserForm1 中声明,其中包含添加到 Userform 的标签数量。 单击命令按钮添加水平表时,程序会调用类模块中的子程序来为用户窗体添加标签。 添加的第一
我创建了一个用户表单(更改事件工作表或所有工作表的列和行宽度),它具有三个框架。 在第一帧中,我给出了两个选项框。 Firsts 选项框: - 从 B 列开始更改行和列宽度,其他选项框从 C 列开始更
我有一个使用 VBA 在 Excel 2010 中创建的用户窗体。基于来自特定工作表的数据以编程方式将控件添加到表单中。我的代码添加了所有控件,然后确定表单是否过长。如果是,则表单将设置为最大高度 5
我从其他人那里接管了一个用户表单(这个表单是由 Excel VBA 制作的)。我注意到那个人创建了两个文本框,一个是白色的,另一个是黑色的。但是我想将所有文本框的背景设为白色,但我不知道如何更改文本框
我知道并理解将项目添加到 ListBox 的常用方法使用逻辑测试: If a = 1 Then ListBox1.AddItem x End If 但是,我想知道是否有可能 .AddItem直
我正在尝试通过 Sub 使用参数在 excel-VBA 中创建相同无模式用户窗体的多个实例。 我可以使用我要分配的三个参数中的两个使其工作,但第三个参数不断返回我 "Run-time Error '9
我希望这不是那么愚蠢,但我真的没有找到适合我的帖子。 情况:我希望有人将日期放入用户窗体中的文本框中。 错误处理程序:如果用户没有输入正确的格式,我想有一个非常简单的解决方案。 (EB_Start.A
我在运行我创建的用户窗体时遇到问题。我的用户窗体中有 5 个标签,但是当我运行用户窗体以获取 excel 电子表格的输入时,我的标签不显示,只有日期、数字等我已放入文本框和组合框。 Deso有人知道这
我有一个带有文本框的用户窗体,这些文本框已经通过 ControlSource 属性绑定(bind)到某些工作表单元格。我需要在其中两个绑定(bind)值之间运行计算,并将结果放在第三个工作表单元格中。
我正在尝试删除 ActiveX OLEObject从工作表然后启动 UserForm如vbModeLess . 在下面的代码中: 首先,一个子创建一个 OLEObject (a Label )在工作表
更新:在对象浏览器中的进一步研究...看来 MSForms.TextBox 既没有实现 .Name 属性也没有实现_Exit 事件 - 只有 _Change 事件。有没有办法确定哪个特定的 TextB
我正在尝试在工作中创建一个库存系统,作为我们唯一拥有的 Excel 软件。基本上,我们有一个工作订单表,我们可以在其中输入维修情况以及所使用的零件。我编写了一个代码,可以从各个工作订单中提取插入的零件
只是一个我似乎找不到答案的问题。 我正在以编程方式创建一个用户窗体,并且我发现如果我将对象声明为“MSForms.Userform”类型,则似乎无法设置高度和宽度,因为这些属性不存在,和 inside
我正在通过代码创建我的标签和复选框: i = 1 While Not Sheets("I_M_1_1PW").Cells(9 + i, 43) = "koniec" Set theLabel
我有一个带有一个模块( main )和一个用户表单模块( myUserForm )的项目。 我在模块 main 上将变量声明为全局变量: Dim myGlobal As MyType ...然后我在模
我真的需要一些帮助,我是 VBA 编程的新手,只能自学。 感谢所有帮助。 我的问题是什么? 我的工具中有超过 1 个用户窗体,每个用户窗体都包含很多按钮,有些按钮在其他用户窗体上相同,有些不同。 如果
我正在尝试创建一个用户表单,将 TextBoxes 的值传输到 Word 文件中的书签位置,但出现错误。我尝试了一些在 Google 上找到的示例,但仍然出现错误。 我收到错误“VBA 对象不支持此属
我创建了一个带有三个文本框的用户表单。 第一个文本框用于输入第一个数字,第二个文本框用于输入第二个数字,最后一个是结果。 我创建了一个名为Calculate 的按钮。 我有 textbox1 的代码:
我的问题是:在 Excel 2013 中使用 VBA 当用户决定不想填写用户表单并单击退出或取消时,如何优雅地关闭整个 Excel 实例? 目前,如果用户单击退出或取消,我会检查我的实例是否是唯一打开
我是一名优秀的程序员,十分优秀!