Registriert seit: 19.12.2020
Version(en): Microsoft 365 (32/64 Bit)
Hallo
Nur so: Ich arbeite schon mehrere Jahre mit Excel 64 bit ohne Probleme, ich werde immer dabei bleiben. Arbeite auch mit Addins die ich mir Dank mumpel erst in einer 32 bit Version vorbereitet habe und bei Gebrauch im Menü anzeigen lassen, auch dies klappt einwandfrei in 64 bit Version.
Viele Grüße PIVPQ
Registriert seit: 18.10.2020
Version(en): 365
22.05.2024, 20:12
(Dieser Beitrag wurde zuletzt bearbeitet: 22.05.2024, 20:12 von Warkings.)
Ich denke, Du solltest erst versuchen zu verstehen, was CopyMemory überhaupt macht. Anbei ein Beispiel, zum Verstehen und Debuggen!!Quelle: CopyMemory was ist das? - Sonstige Problemstellungen - VB-Paradise 2.0 – Die große Visual-Basic- und .NET-CommunityCode: Public Declare Sub CopyMemory Lib "kernel32" Alias _ "RtlMoveMemory" (destination As Any, source As Any, _ ByVal length As Long)
Sub test()
Dim b1(19) As Byte Dim i As Long For i = 0 To 19 b1(i) = i Next i Dim b2(5) As Byte
CopyMemory b2(0), b1(9), 6 End Sub
Wir haben hier ein Byte-Array. Arrays sind zusammenhängender Speicher. Arrays werden niemals auf unterschiedliche Speicheradressen aufgeteilt; jedes Array-Element folgt unmittelbar auf das vorherige Array-Element im Speicher. Also ist das zweite Element hier im Array 1 Byte hinter dem ersten Element, das dritte 2 Byte usw.
Registriert seit: 26.09.2022
Version(en): 2019
Moin,
Ich bin selbst nicht sehr Firm in API-Calls, aber soweit ich informiert bin, ist der Unterschied bei CopyMemory, dass du im 32-Bit System eine Variable ByRef übergibst und CopyMemory dabei die Speicheradresse der Variable erhält. In der 64 Bit Version wird ein Zeiger auf die Variable byVal erwartet. Und die Speicheradresse also selbst die übergebene Zahl ist. Den Zeiger erhältst du eben mit den VarPtr oder ObjPtr.
Schau mal im Beispielbereich des Forums, volti hat da seinen API-Viewer irgendwo hochgeladen da erhältst du immerhin die Deklarationen.
Viele Grüße derHöpp
Registriert seit: 18.10.2020
Version(en): 365
23.05.2024, 08:15
(Dieser Beitrag wurde zuletzt bearbeitet: 23.05.2024, 08:15 von Warkings.)
https://stackoverflow.com/a/62127904/6600940Es ist nicht so, dass die Benutzung von Any generell falsch ist, denn so ist CopyMemory definiert. Zitat:Having declared the same parameters as ByVal pDest As LongPtr, ByVal pSrc As LongPtr, you lose the ability to pass Longs ByRef like in the first example and will need to explicitly use VarPtr each time, but you won't need to think too much how to call the function.
There is still some danger though, because you can still call it as CopyMemory a, b with Long parameters, and it will crash for passing values as pointers, but at least you will see from the function definition what you are passing something wrong, while As Any doesn't give you a hint. Und man muss natürlich wissen, was VarPtr und ObjPtr zurückliefert.
Registriert seit: 22.11.2019
Version(en): 365
Hallo zusammen, ich weiß gar nicht, warum immer in den Foren auf der 64-Bit-Version rumgehakt wird Ich habe die jetzt schon seit 2016 und keine Probleme. Ich verwende sehr viel API-Kram. Hier zum Abschluss noch interessehalber meine seit Jahren funktionierende (aber für hier etwas veränderte) Version der Ribbonwiederherstellung. Allerdings werden sämtliche Invalidates über eine eigene Funktion geleitet und der Ribbon-Pointer nicht in der Registry sondern in der jeweiligen Mappe gespeichert. Vielleicht hilft es ja dem einen oder anderen oder einfach nur zum Gucken, wie es auch gehen kann. Code:
Dim goRibbon As IRibbonUI Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _ Destination As Any, Source As Any, ByVal Length As LongPtr)
'----- Ribbon initialisieren ----- '------ Diese Funktion ist im Ribbon für OnLoad="RibbonInit" angegeben ----- Private Sub RibbonInit(lpRibbon As IRibbonUI) Set goRibbon = lpRibbon 'globalen Pointer setzen und in einem Namen sichern ThisWorkbook.Names.Add Name:="MyRibbon", _ RefersTo:=CStr(ObjPtr(lpRibbon)), Visible:=False End Sub
Sub RefreshRibbon(Optional sID As String) ' Das angegebene Control oder der ganze Ribbon wird neu berechnet Dim lpRibbon As LongPtr If goRibbon Is Nothing Then 'Ribbon-Pointer aus Namen wiederherstellen On Error Resume Next lpRibbon = CLngPtr(Mid$(ThisWorkbook.Names("MyRibbon").RefersTo, 2)) CopyMemory goRibbon, lpRibbon, LenB(lpRibbon) End If If sID <> "" Then goRibbon.InvalidateControl sID Else goRibbon.Invalidate End If End Sub
_________ viele Grüße Karl-Heinz
Registriert seit: 26.09.2015
Version(en): 2013
24.05.2024, 00:56
(Dieser Beitrag wurde zuletzt bearbeitet: 24.05.2024, 00:58 von Stefan1.)
Guten Tag zusammen Zunächst vielen Dank für Eure Unterstützung. Das mit dem Speichern in der Arbeitsmappe finde ich interessant, verstehe aber nicht ganz, wo das genau sein soll. Das habe ich so noch nie gesehen. Weil mir ein Fehler (wollte den String "ribValue" zusätzlich einsetzen) unterlaufen ist, poste ich hier nochmals den lauffähigen Code mit Registry. Code: Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, source As Any, ByVal Length As LongPtr) Public Sub OnRibbonLoad(ribbon As IRibbonUI) SaveSetting "msoFile", CONmenuNEW, "objRibbonVar", ObjPtr(ribbon) On Error Resume Next If val(Application.Version) > 12 Then gobjRibbon.ActivateTab CONmenuNEW On Error GoTo 0 End Sub
…. If TestRibbon = True Then Call Application.OnTime(EarliestTime:=Now, Procedure:="SwitchTabMain")
…. If TestRibbon = True Then gobjRibbon.InvalidateControl "btnSpeichern" Public Sub SwitchTabMain() On Error Resume Next gobjRibbon.ActivateTab CONmenuNEW: If Err.Number < 0 Then Err.Clear End Sub
Public Function TestRibbon() As Boolean Dim varRegWert As Variant Dim ribValue As String If gobjRibbon Is Nothing Then varRegWert = CVar(GetAllSettings(appName:="msoFile", section:=CONmenuNEW)) If IsEmpty(varRegWert) = False Then ribValue = GetSetting("msoFile", CONmenuNEW, "objRibbonVar") If Len(ribValue) > 0 Then Set gobjRibbon = GetRibbon(CLngPtr(ribValue)) If gobjRibbon Is Nothing Then TestRibbon = False Else TestRibbon = True End If Else TestRibbon = False End If End If Else TestRibbon = True End If End Function
Public Function GetRibbon(ByVal lRibbonPointer As LongPtr) As Object Dim NewobjRibbon As IRibbonUI CopyMemory VarPtr(NewobjRibbon), lRibbonPointer, LenB(lRibbonPointer) Set GetRibbon = NewobjRibbon Set NewobjRibbon = Nothing CopyMemory NewobjRibbon, 0&, 4 If Err.Number > 0 Then Err.Clear End Function
Registriert seit: 11.04.2014
Version(en): Office 365
Zitat:verstehe aber nicht ganz, wo das genau sein soll. Das wird als Name in der Tabelle gespeichert. Das müsstest Du dann als Name auch finden, wie auch beim manuellen Eibfügen eines Namens (Einfügen=>Name).
Registriert seit: 22.11.2019
Version(en): 365
Hallo Stefan,
noch mal 'ne Frage zu Deinem Code.
Was steht denn in ConMenueNew? Ein Tabellenname oder der gerade aktuelle Tabellenname?
Hierfür wird ja dann wohl ein Eintrag in der Registry gemacht. Warum ich das mit der Registry nicht gemacht habe ist folgender Gedanke:
Was passiert, wenn man mehrere Mappen mit Ribbons aufmacht? Wird jetzt für jedes Ribbon ein Eintrag in der Registry gesetzt oder nur ein Eintrag mit dem jeweils zuletzt Geöffneten. Dann könnte es beim Wiederherstellen Probleme geben. Wird der Eintrag in der Registry auch wieder entfernt, z.B. beim Schließen der Mappe, oder bleibt der jetzt nach z.B. einmaligen Öffnen der Mappe für immer dort drin?
Sicher alles nur theoretisch und ohne weitere Probleme, aber vielleicht mal denkenswert.
Gruß KH
Registriert seit: 11.04.2014
Version(en): Office 365
Folgende(r) 2 Nutzer sagen Danke an mumpel für diesen Beitrag:2 Nutzer sagen Danke an mumpel für diesen Beitrag 28
• Stefan1, Stefan1
Registriert seit: 26.09.2015
Version(en): 2013
26.05.2024, 10:05
Guten Tag KH
ConMenueNew ist eine Konstante. Dahinter steht ein Name z.B. Dim const ConMenueNew as String = "Menü01" oder so. Es gibt Beispiele mit ThisWorkbook.Name, jedoch wollte ich das nicht, weil ich Versioniere im Dateinamen sowie den Dateinamen häufig bis zu letzt wieder anpasse und damit ungewohnt in der Tat immer wieder neue Registry eröffnen würde. Ja, zunächst habe ich das Registry jeweils beim schließen wieder gelöscht, doch mittlerweile ist das mir ziemlich egal, weil ja sowieso wieder mal ein neuer PC kommt und ich dafür alle in der gleichen Registry am gleichen zentralen Ort "objRibbonVar" ablege mit der kleinen generischen oder auch funktional wiedererkennbaren Unterscheidung "Menü01", "Menü02", "Tool X" usw. und so hat jede Arbeitsmappe, die ein eigenes Ribbon hat, sein eigener Ablageort in der Registry. Ich überlege trotzdem das Registry-Löschen wieder einführen. Gibt es dafür wirklich einen valablen Grund?
Zunächst bin ich mal dankbar, dass es nun mit dieser letztendlich banalen 64-bit-Version ohne Veränderung der Microsoft-Empfehlung für die Schreibweise dieser API CopyMemory wieder stabil funktioniert bis dann die 128-bit-Version kommt oder VBA nur noch Geschichte ist, was ich Nostalgiker vermissen werde (Smiley). Freuen wir uns, so lange wir noch können.
64-bit VBA-Version von Microsoft Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, source As Any, ByVal Length As LongPtr)
Vielen Dank für Eure Beiträge.
Gruß Stefan1
|