Move Event des Application Fenster gesucht
Ich suche etwas Vergleichbares zu UserForm_Layout() oder andere Möglichkeit eine Bewegung des Application Fensters zu erkennen.
Hallo
ich habe ein Add-In in Excel programmiert.
Dieses Add-In enthält unter anderem ein Fenster (UserForm) zur Steuerung.
Nun ist das Problem das beim Verschieben des Fensters der Excel Anwendung die UserForm sich nicht mit verschiebt.
Ich hätte das Ganze gerne so das sich die UserForm relativ zum Excel Fenster mit verschiebt.
Das Positionieren der Userform mit .Top und .Left wäre auch nicht das Problem.
Nur müsste ich, um ein relatives Verschieben zu realisieren, die Position des Excel Fensters haben (um damit die Position der UserForm zu errechnen) und einen Event der ausgelöst wird sobald das Excel Fenster verschoben wird.
Für eine Form kenne ich diesen Event mit:
Für das Hauptfenster habe ich aber keine Idee wie das gehen könnte.
Ich suche also nach einer Funktion in der Art Application_Layout().
Gesucht habe ich zwar schon aber ich habe nicht mal ansatzweiße eine Idee erhalten (oder unter den flaschen Suchbegriffen gesucht)
Das ganze soll unter Windowx xp mit Excel 2003 genau so laufen wir unter Windows 7 mit Excel 2010.
Ich bin für alle Ansatzpunkte dankbar.
Gruß
miniversum
Hallo
ich habe ein Add-In in Excel programmiert.
Dieses Add-In enthält unter anderem ein Fenster (UserForm) zur Steuerung.
Nun ist das Problem das beim Verschieben des Fensters der Excel Anwendung die UserForm sich nicht mit verschiebt.
Ich hätte das Ganze gerne so das sich die UserForm relativ zum Excel Fenster mit verschiebt.
Das Positionieren der Userform mit .Top und .Left wäre auch nicht das Problem.
Nur müsste ich, um ein relatives Verschieben zu realisieren, die Position des Excel Fensters haben (um damit die Position der UserForm zu errechnen) und einen Event der ausgelöst wird sobald das Excel Fenster verschoben wird.
Für eine Form kenne ich diesen Event mit:
Private Sub UserForm_Layout()
Debug.Print Me.Top, Me.Left, Me.Height, Me.Width
End Sub
Für das Hauptfenster habe ich aber keine Idee wie das gehen könnte.
Ich suche also nach einer Funktion in der Art Application_Layout().
Gesucht habe ich zwar schon aber ich habe nicht mal ansatzweiße eine Idee erhalten (oder unter den flaschen Suchbegriffen gesucht)
Das ganze soll unter Windowx xp mit Excel 2003 genau so laufen wir unter Windows 7 mit Excel 2010.
Ich bin für alle Ansatzpunkte dankbar.
Gruß
miniversum
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 193108
Url: https://administrator.de/contentid/193108
Ausgedruckt am: 21.11.2024 um 12:11 Uhr
4 Kommentare
Neuester Kommentar
Hallo miniversum.
Wie du sicher schon herausgefunden hast, gibt es so ein Event nicht für Excel.
Du musst schon die WinAPI bemühen. Leider habe ich aber erst heute die Zeit gefunden, um mich damit zu beschäftigen (hoffe, noch nicht zu spät).
Natürlich wollte ich das Rad nicht neu erfinden und habe im Netz nach ähnlichen Umsetzungen gesucht. Du kannst dir hier das Beispiel genauer ansehen, dass ich für dein Vorhaben adaptiert habe. Dort findest du auch einiges an Erklärungen und Kommentaren.
Zum Test eine Neue Exceldatei erstellen, mit 2 Standardmodulen (Modul1, Modul2). Weiterhin ein Formular (UserForm1) mit einem Textfeld (TextBox1).
In "Modul1":
In "Modul2" die Prozedur, um das Ganze anzuschubsen:
In "DieseArbeitsmappe":
In "UserForm1":
Nun solltest du folgendes feststellen:
Wenn du das Excelfenster unter dem Formular bewegst, sollte im Textfeld des Formulars die Position des Excelfensters angezeigt werden.
Ich hoffe bei dir funktioniert das auch so wie bei mir (Excel 2003 auf Win7 x86).
Grüße
rubberman
Wie du sicher schon herausgefunden hast, gibt es so ein Event nicht für Excel.
Du musst schon die WinAPI bemühen. Leider habe ich aber erst heute die Zeit gefunden, um mich damit zu beschäftigen (hoffe, noch nicht zu spät).
Natürlich wollte ich das Rad nicht neu erfinden und habe im Netz nach ähnlichen Umsetzungen gesucht. Du kannst dir hier das Beispiel genauer ansehen, dass ich für dein Vorhaben adaptiert habe. Dort findest du auch einiges an Erklärungen und Kommentaren.
Zum Test eine Neue Exceldatei erstellen, mit 2 Standardmodulen (Modul1, Modul2). Weiterhin ein Formular (UserForm1) mit einem Textfeld (TextBox1).
In "Modul1":
Option Explicit
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, _
ByVal MSG As Long, _
ByVal wParam 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 GetDesktopWindow Lib "user32.dll" () As Long
Private Declare Function ShowWindow Lib "user32.dll" ( _
ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByRef lParam As Any) As Long
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 SetTimer Lib "user32.dll" ( _
ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32.dll" ( _
ByVal hwnd As Long, _
ByVal nIDEvent As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32.dll" ( _
ByVal hwndLock As Long) As Long
Private Declare Function GetProp Lib "user32" Alias "GetPropA" ( _
ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Declare Function SetProp Lib "user32" Alias "SetPropA" ( _
ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal hData As Long) As Long
Private Declare Function RemoveProp Lib "user32" Alias "RemovePropA" ( _
ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Const GWL_WNDPROC As Long = -4
Private Const WM_USER As Long = &H400
Private Const WM_MOVE As Long = &H3
Private Const WM_EXITSIZEMOVE As Long = &H232
Private Const WM_SETREDRAW As Long = &HB
Private Const VBE_CLASS_NAME As String = "wndclass_desked_gsk"
Private Const EXCEL_CLASS_NAME As String = "XLMAIN"
Private lOldWinProc As Long
Private lVBEhwnd As Long
Sub Safe_Subclass(hwnd As Long)
If GetProp(GetDesktopWindow, "HWND") <> 0 Then
Exit Sub
End If
SetProp GetDesktopWindow, "HWND", hwnd
lVBEhwnd = FindWindow(VBE_CLASS_NAME, vbNullString)
LockWindowUpdate lVBEhwnd
SendMessage GetDesktopWindow, ByVal WM_SETREDRAW, ByVal 0&, 0&
PostMessage lVBEhwnd, ByVal WM_USER + &HC44, ByVal &H30, ByVal 0&
PostMessage lVBEhwnd, ByVal WM_USER + &HC44, ByVal &H33, ByVal 0&
PostMessage lVBEhwnd, ByVal WM_USER + &HC44, ByVal &H83, ByVal 0&
SetTimer GetProp(GetDesktopWindow, "HWND"), 0&, 1, AddressOf TimerProc
End Sub
Sub UnSubClassExcel(hwnd As Long)
SetWindowLong hwnd, GWL_WNDPROC, lOldWinProc
RemoveProp GetDesktopWindow, "HWND"
lOldWinProc = 0
End Sub
Private Function WindowProc( _
ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
On Error Resume Next
Select Case uMsg
Case WM_MOVE
UserForm1.TextBox1 = Application.Top & vbTab & Application.Left
DoEvents
'Case WM_EXITSIZEMOVE
' UserForm1.TextBox1 = Application.Top & vbTab & Application.Left
' DoEvents
End Select
WindowProc = CallWindowProc(lOldWinProc, hwnd, uMsg, wParam, lParam)
End Function
Sub TimerProc(ByVal hwnd As Long, ByVal nIDEvent As Long, _
ByVal uElapse As Long, ByVal lpTimerFunc As Long)
lVBEhwnd = FindWindow(VBE_CLASS_NAME, vbNullString)
KillTimer GetProp(GetDesktopWindow, "HWND"), 0&
SendMessage GetDesktopWindow, WM_SETREDRAW, ByVal 1, 0&
ShowWindow lVBEhwnd, 0&
LockWindowUpdate 0&
lOldWinProc = SetWindowLong _
(GetProp(GetDesktopWindow, "HWND"), _
GWL_WNDPROC, AddressOf WindowProc)
End Sub
In "Modul2" die Prozedur, um das Ganze anzuschubsen:
Option Explicit
Sub UF_show()
UserForm1.Show vbModeless
End Sub
In "DieseArbeitsmappe":
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call UnSubClassExcel(Application.hwnd)
End Sub
In "UserForm1":
Option Explicit
Private Sub UserForm_Activate()
Me.TextBox1 = Application.Top & vbTab & Application.Left
Call Safe_Subclass(Application.hwnd)
Application.OnTime Now + TimeValue("00:00:00"), "UF_show"
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Call UnSubClassExcel(Application.hwnd)
End Sub
Private Sub UserForm_Deactivate()
Call UnSubClassExcel(Application.hwnd)
End Sub
Nun solltest du folgendes feststellen:
Wenn du das Excelfenster unter dem Formular bewegst, sollte im Textfeld des Formulars die Position des Excelfensters angezeigt werden.
Ich hoffe bei dir funktioniert das auch so wie bei mir (Excel 2003 auf Win7 x86).
Grüße
rubberman
Hallo miniversum.
Daran hatte ich auch schon gedacht, allerdings hatte nicht geglaubt, dass das für dich infrage kommt. Das Formular wir so immer einen Teil der Tabelle verdecken, da es in das Application Fenster integriert ist.
Egal. Einfacher ist es so in jedem Fall und stabiler als das Subclassing erst recht. Danke fürs Teilen deiner Lösung
Grüße
rubberman
Daran hatte ich auch schon gedacht, allerdings hatte nicht geglaubt, dass das für dich infrage kommt. Das Formular wir so immer einen Teil der Tabelle verdecken, da es in das Application Fenster integriert ist.
Egal. Einfacher ist es so in jedem Fall und stabiler als das Subclassing erst recht. Danke fürs Teilen deiner Lösung
Grüße
rubberman